
    \eF                     T   d 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ddlm	Z	 ddl
Z
ddlmZ  ej                  e      ZdaddZddZd Zd	 Zd
 Zd Zej.                  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$ G d dejJ                        Z&ddZ'	 	 	 	 ddZ(y) z1
Network-related utilities and helper functions.
    N)parse)	INET_PTON)_c                     | sy| d   dk(  r5| dd j                  d      \  }}|}d|v r|j                  d      d   }n0|}n-| j                  d      dk(  r| j                  d      \  }}n| }|}||dfS t        |      fS )a  Interpret a string as a host:port pair.

    An IPv6 address MUST be escaped if accompanied by a port,
    because otherwise ambiguity ensues: 2001:db8:85a3::8a2e:370:7334
    means both [2001:db8:85a3::8a2e:370:7334] and
    [2001:db8:85a3::8a2e:370]:7334.

    >>> parse_host_port('server01:80')
    ('server01', 80)
    >>> parse_host_port('server01')
    ('server01', None)
    >>> parse_host_port('server01', default_port=1234)
    ('server01', 1234)
    >>> parse_host_port('[::1]:80')
    ('::1', 80)
    >>> parse_host_port('[::1]')
    ('::1', None)
    >>> parse_host_port('[::1]', default_port=1234)
    ('::1', 1234)
    >>> parse_host_port('2001:db8:85a3::8a2e:370:7334', default_port=1234)
    ('2001:db8:85a3::8a2e:370:7334', 1234)
    >>> parse_host_port(None)
    (None, None)
    )NNr   [   N]:)splitcountint)addressdefault_port_host_porthostports         5/usr/lib/python3/dist-packages/oslo_utils/netutils.pyparse_host_portr   %   s    2 qzSqr{((-u%<;;s#A&DD==" s+JD$ DD$,$66CI66    c                 @   |"|rt         nd}	 t        j                  | |      S 	 t        j                  | t               ryt        j                  |       rt        j                  d       yy# t        j                  $ r Y yw xY w# t        j                  $ r Y yw xY w)aR  Verify that address represents a valid IPv4 address.

    :param address: Value to verify
    :type address: string
    :param strict: flag allowing users to restrict validation
        to IP addresses in presentation format (``a.b.c.d``) as opposed to
        address format (``a.b.c.d``, ``a.b.c``, ``a.b``, ``a``).
    :type flags: bool
    :returns: bool

    .. versionadded:: 1.1
    .. versionchanged:: 4.8.0
       Allow to restrict validation to IP addresses in presentation format
       (``a.b.c.d``) as opposed to address format
       (``a.b.c.d``, ``a.b.c``, ``a.b``, ``a``).
    r   )flagsFTzqConverting in non strict mode is deprecated. You should pass strict=False if you want to preserve legacy behavior)r   netaddr
valid_ipv4AddrFormatErrorLOGwarning)r   strictflags      r   is_valid_ipv4r    U   s    " "y	%%gT::
gY7!!'*/0  && 		  "" s(   A. B *B .BBBBc                 .   | sy| j                  dd      }|d   } t        |      dkD  r|d   nd}|t        |      dk  st        |      dkD  ry	 t        j                  | t        j                  j
                        S # t        j                  $ r Y yw xY w)zVerify that address represents a valid IPv6 address.

    :param address: Value to verify
    :type address: string
    :returns: bool

    .. versionadded:: 1.1
    F%r   r   N   )rsplitlenr   
valid_ipv6corer   r   )r   partsscopes      r   is_valid_ipv6r*   ~   s     NN3"EAhGE
QE!HDEc%j1nE
R!!'7<<+A+ABB"" s   -A> >BBc                     	 t        j                  |        | j	                  d      }t        |      dk  s|d   dk(  ryy# t        t         j                  f$ r Y yw xY w)zVerify that address represents a valid CIDR address.

    :param address: Value to verify
    :type address: string
    :returns: bool

    .. versionadded:: 3.8
    F/r    T)r   	IPNetwork	TypeErrorr   r   r%   )r   
ip_segments     r   is_valid_cidrr1      sb    '" s#JJ1qMR w../ s   A   AAc                     	 t        j                  | d      j                   y# t        t         j                  f$ r Y yw xY w)zVerify that address represents a valid IPv6 CIDR address.

    :param address: address to verify
    :type address: string
    :returns: true if address is valid, false otherwise

    .. versionadded:: 3.17
       )versionTF)r   r.   cidrr/   r   r   s    r   is_valid_ipv6_cidrr7      s=    '1-22w../ s   !$ A A c                    t        |       rt        d      }t        |      	 t        t	        j
                  |      j                               }t	        j                  |       } t	        j                  | j                  |z   dz        S # t        t        j                  f$ r t        t        d      | |dz        t        $ r t        t        d      | z        w xY w)an  Calculate IPv6 address using EUI-64 specification.

    This method calculates the IPv6 address using the EUI-64
    addressing scheme as explained in rfc2373.

    :param prefix: IPv6 prefix.
    :param mac: IEEE 802 48-bit MAC address.
    :returns: IPv6 address on success.
    :raises ValueError, TypeError: For any invalid input.

    .. versionadded:: 1.4
    z6Unable to generate IP address by EUI64 for IPv4 prefixl          zTBad prefix or mac format for generating IPv6 address by EUI-64: %(prefix)s, %(mac)s:)prefixmacz9Bad prefix type for generating IPv6 address by EUI-64: %s)r    r   
ValueErrorr   r   EUIeui64r.   	IPAddressfirstr   r/   )r9   r:   msgr=   s       r   get_ipv6_addr_by_EUI64rA      s     VHIo
2GKK$**,-""6*  !5!ABB//0 ; E F&,S9: ; 	;  2 ' (*01 2 	22s   A%B	 	ACc                 `    t        j                  t        | dz  dz	  | dz  z   dz        |      S )aa  Extract MAC address from interface identifier based IPv6 address.

    For example from link-local addresses (fe80::/10) generated from MAC.

    :param ipv6: An interface identifier (i.e. mostly MAC) based IPv6
                 address as a netaddr.IPAddress() object.
    :param dialect: The netaddr dialect of the the object returned.
                    Defaults to netaddr.mac_unix_expanded.
    :returns: A MAC address as a netaddr.EUI() object.

    See also:
    * https://tools.ietf.org/html/rfc4291#appendix-A
    * https://tools.ietf.org/html/rfc4291#section-2.5.6

    .. versionadded:: 4.3.0
    l        |    i l        )dialect)r   r<   r   )ipv6rD   s     r   get_mac_addr_by_ipv6rF      sH    " ;;s ++
2


 				 	 	r   c                      t         ad} t        j                  j                  |       r>t	        | d      5 }|j                         j                         }ddd       dk(  a t         S da t         S # 1 sw Y   xY w)a  Check if IPv6 support is enabled on the platform.

    This api will look into the proc entries of the platform to figure
    out the status of IPv6 support on the platform.

    :returns: True if the platform has IPv6 support, False otherwise.

    .. versionadded:: 1.4
    Nz,/proc/sys/net/ipv6/conf/default/disable_ipv6r0F)_IS_IPV6_ENABLEDospathexistsopenreadstrip)disabled_ipv6_pathfdisableds      r   is_ipv6_enabledrT      su     K77>>,-(#. ,!668>>+,'3   %, ,s   A..A7c                 &    t        |       rd| z  S | S )zEscape an IP address in square brackets if IPv6

    :param address: address to optionaly escape
    :type address: string
    :returns: string

    .. versionadded:: 3.29.0
    z[%s])r*   r6   s    r   escape_ipv6rV     s     WNr   c                 2    t        |       xs t        |       S )zVerify that address represents a valid IP address.

    :param address: Value to verify
    :type address: string
    :returns: bool

    .. versionadded:: 1.1
    )r    r*   r6   s    r   is_valid_iprX   !  s     !;]7%;;r   c                 r    d}t        | t              xr$ t        j                  || j	                               S )a  Verify the format of a MAC address.

    Check if a MAC address is valid and contains six octets. Accepts
    colon-separated format only.

    :param address: MAC address to be validated.
    :returns: True if valid. False if not.

    .. versionadded:: 3.17
    z[0-9a-f]{2}(:[0-9a-f]{2}){5}$)
isinstancestrrematchlower)r   ms     r   is_valid_macr`   -  s,     	(Ags#DGMMO(DDr   c                 d    	 t        |       }||cxk  xr |k  S c S # t        t        f$ r Y yw xY w)zTry to convert value to int and check if it lies within
    range 'start' to 'end'.

    :param value: value to verify
    :param start: start number of range
    :param end: end number of range
    :returns: bool
    F)r   r;   r/   )valuestartendvals       r   _is_int_in_rangerf   <  sA    %j SC   	" s    //c                     t        | dd      S )zVerify that port represents a valid port number.

    Port can be valid integer having a value of 0 up to and
    including 65535.

    .. versionadded:: 1.1.1
    r   i  rf   )r   s    r   is_valid_portri   L  s     D!U++r   c                     t        | dd      S )zVerify if ICMP type is valid.

    :param type: ICMP *type* field can only be a valid integer
    :returns: bool

    ICMP *type* field can be valid integer having a value of 0
    up to and including 255.
    r      rh   )types    r   is_valid_icmp_typerm   W  s     D!S))r   c                 "    | yt        | dd      S )zVerify if ICMP code is valid.

    :param code: ICMP *code* field can be valid integer or None
    :returns: bool

    ICMP *code* field can be either None or valid integer having
    a value of 0 up to and including 255.
    Tr   rk   rh   )codes    r   is_valid_icmp_coderp   c  s     |D!S))r   c                     	 t        j                   t         j                  t         j                        } | j                  d       | j	                         \  }}| j                          |S # t         j                  $ r t               cY S w xY w)a  Returns the actual ipv4 of the local machine.

    This code figures out what source address would be used if some traffic
    were to be sent out to some well known address on the Internet. In this
    case, IP from RFC5737 is used, but the specific address does not
    matter much. No traffic is actually sent.

    .. versionadded:: 1.1

    .. versionchanged:: 1.2.1
       Return ``'127.0.0.1'`` if there is no default interface.
    )z	192.0.2.0P   )socketAF_INET
SOCK_DGRAMconnectgetsocknamecloseerror_get_my_ipv4_address)csockaddrr   s      r   get_my_ipv4r}   q  sj    &fnnf.?.?@'(((*t<< &#%%&s   A'A* *B
	B
c                     d} t        j                         }	 |d   t         j                     d   }	 t        j                  |      t         j                     d   d   S # t        t        f$ r t
        j                  d       | cY S w xY w# t        t        f$ r t
        j                  d|       Y | S t        $ r$}t
        j                  d||d	       Y d
}~| S d
}~ww xY w)zFigure out the best ipv4
    z	127.0.0.1defaultr   zOCould not determine default network interface, using 127.0.0.1 for IPv4 addressr   r|   zBCould not determine IPv4 address for interface %s, using 127.0.0.1zGCould not determine IPv4 address for interface %(interface)s: %(error)s	interfacery   N)		netifacesgatewaysrt   KeyError
IndexErrorr   infoifaddresses	Exception	LOCALHOSTgtwr   es       r   rz   rz     s     I



C	N9#4#45a8		7$$Y/	0A0AB1EfMM j!  4 	5 j!  #	 	  7 6(15	7 	7 	7s.   A +B
 &BB
%C2C:CCc                     	 t        j                   t         j                  t         j                        } | j                  d       | j	                         \  }}}}| j                          |S # t         j                  $ r t               cY S w xY w)a  Returns the actual IPv6 address of the local machine.

    This code figures out what source address would be used if some traffic
    were to be sent out to some well known address on the Internet. In this
    case, IPv6 from RFC3849 is used, but the specific address does not
    matter much. No traffic is actually sent.

    .. versionadded:: 6.1
       Return ``'::1'`` if there is no default interface.
    )z2001:db8::1rr   )rs   AF_INET6ru   rv   rw   rx   ry   _get_my_ipv6_address)r{   r|   r   s      r   get_my_ipv6r     sn    &foov/@/@A)*++-q!Q<< &#%%&s   A)A, ,BBc                     d} t        j                         }	 |d   t         j                     d   }	 t        j                  |      t         j                     d   d   S # t        t        f$ r t
        j                  d|        | cY S w xY w# t        t        f$ r t
        j                  d|| d       Y | S t        $ r$}t
        j                  d	||d
       Y d}~| S d}~ww xY w)z%Figure out the best IPv6 address
    z::1r   r   zHCould not determine default network interface, using %s for IPv6 addressr   r|   zOCould not determine IPv6 address for interface %(interface)s, using %(address)s)r   r   zGCould not determine IPv6 address for interface %(interface)s: %(error)sr   N)	r   r   r   r   r   r   r   r   r   r   s       r   r   r     s     I



C	N9#5#56q9		7$$Y/	0B0BCAFvNN j!  -.7	9 j! A 4(Y?	A 	  7 6(15	7 	7 	7s.   A +B 'BB(C"6C">CC"c                       e Zd ZdZddZy)_ModifiedSplitResultz!Split results class for urlsplit.c                 @   | j                   r|r(t        t        j                  | j                               S i }t        j                  | j                         D ]A  \  }}||v r3t	        ||   t
              r||   j                  |       2||   |g||<   =|||<   C |S i S )a  Extracts the query parameters from the split urls components.

        This method will provide back as a dictionary the query parameter
        names and values that were provided in the url.

        :param collapse: Boolean, turn on or off collapsing of query values
        with the same name. Since a url can contain the same query parameter
        name with different values it may or may not be useful for users to
        care that this has happened. This parameter when True uses the
        last value that was given for a given name, while if False it will
        retain all values provided by associating the query parameter name with
        a list of values instead of a single (non-list) value.
        )querydictr   	parse_qslrZ   listappend)selfcollapseparamskeyrb   s        r   r   z_ModifiedSplitResult.params  s     ::EOODJJ788$)OODJJ$? ,LS%f}%fSk48"3K..u5+1#;*>F3K&+s, Ir   N)T)__name__
__module____qualname____doc__r    r   r   r   r     s
    +r   r   c                     t        j                  | ||      \  }}}}}|rd|v r|j                  dd      \  }}d|v r|j                  dd      \  }}t        |||||      S )zParse a URL using urlparse.urlsplit(), splitting query and fragments.
    This function papers over Python issue9374_ when needed.

    .. _issue9374: http://bugs.python.org/issue9374

    The parameters are the same as urlparse.urlsplit.
    #r   ?)r   urlsplitr   r   )urlschemeallow_fragmentsnetlocrL   r   fragments          r   r   r     st     -2NNV_-&)FFD%3$;C+h
d{jja(e $eX7 7r   c                    t        |t              r0| j                  t        j                  t        j
                  |       nt        d      |sy|Ut        t        d      r0| j                  t        j                  t        j                  |       nt        j                  d       |Ut        t        d      r0| j                  t        j                  t        j                  |       nt        j                  d       |Vt        t        d      r0| j                  t        j                  t        j                  |       yt        j                  d       yy)	a/  Set values for tcp keepalive parameters

    This function configures tcp keepalive parameters if users wish to do
    so.

    :param tcp_keepalive: Boolean, turn on or off tcp_keepalive. If users are
      not sure, this should be True, and default values will be used.

    :param tcp_keepidle: time to wait before starting to send keepalive probes
    :param tcp_keepalive_interval: time between successive probes, once the
      initial wait time is over
    :param tcp_keepalive_count: number of probes to send before the connection
      is killed
    ztcp_keepalive must be a booleanNTCP_KEEPIDLEz)tcp_keepidle not available on your systemTCP_KEEPINTVLz*tcp_keepintvl not available on your systemTCP_KEEPCNTz(tcp_keepcnt not available on your system)rZ   bool
setsockoptrs   
SOL_SOCKETSO_KEEPALIVEr/   hasattrIPPROTO_TCPr   r   r   r   r   )socktcp_keepalivetcp_keepidletcp_keepalive_intervaltcp_keepalive_counts        r   set_tcp_keepaliver     s    * -&))6+>+>N9:: 6>*OOF.."//(* KKCD)6?+OOF.."0024 KKDE&6=)OOF.."../1 KKBC 'r   )N)r-   T)TNNN))r   loggingrK   r\   rs   urllibr   r   netaddr.corer   r   oslo_utils._i18nr   	getLoggerr   r   rJ   r   r    r*   r1   r7   rA   mac_unix_expandedrF   rT   rV   rX   r`   rf   ri   rm   rp   r}   rz   r   r   SplitResultr   r   r   r   r   r   <module>r      s      	 	    "   g! -7`&R04 2< (/'@'@ :0	<E! ,	**&.2&*2 5,,  F7$ +/#'-1*.3Dr   