
    x[h.                        S SK r S SKrS SKrS SKrS SKrS SKJr  S SKJr  \ R                  " \
5      rSrSrSrSrSrS	rSrS
rSrSr\R,                  " \5      r\R,                  " \5      r\\-   rSrSrSrSrS rSrSr Sr!Sr"Sr#Sr$\" S/ SQ5      r%\" SSS/5      r&\" S/ SQ5      r' " S S\(5      r)S r*S r+S$S jr,S r-S r.S  r/S! r0S" r1S# r2g)%    N)
namedtuple)util               i  <   IHHIIBHiII               RTAAttr)lengthrta_typedataInterfaceOperstateifname	operstateNetlinkHeader)r   typeflagsseqpidc                       \ rS rSrSrSrg)NetlinkCreateSocketError5   z5Raised if netlink socket fails during create or bind. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r!       C/usr/lib/python3/dist-packages/cloudinit/sources/helpers/netlink.pyr   r   5   s    ?r(   r   c                      [         R                   " [         R                  [         R                  [         R                  5      n U R	                  [
        R                  " 5       [        45        U R                  S5        [        R                  S5        U $ ! [         R                   a  nSU-  n[        U5      UeSnAff = f)a]  Creates netlink socket and bind on netlink group to catch interface
down/up events. The socket will bound only on RTMGRP_LINK (which only
includes RTM_NEWLINK/RTM_DELLINK/RTM_GETLINK events). The socket is set to
non-blocking mode since we're only receiving messages.

:returns: netlink socket in non-blocking mode
:raises: NetlinkCreateSocketError
r   z*Exception during netlink socket create: %sNzCreated netlink socket)socket
AF_NETLINKSOCK_RAWNETLINK_ROUTEbindosgetpidRTMGRP_LINKsetblockingerrorr   LOGdebug)netlink_socketemsgs      r)   create_bound_netlink_socketr:   9   s    3v0D0D
 	RYY[+67""1% II&'	 << 3:Q>&s+23s   A=B C *B;;C c                     U c   S5       e[        U 5      [        :  d   S5       e[        R                  " [        U S[
         5      u  pp4n[        R                  SU5        [        XX4U5      $ )a  Gets netlink message type and length

:param: data read from netlink socket
:returns: netlink message type
:raises: AssertionError if data is None or data is not >= NLMSGHDR_SIZE
struct nlmsghdr {
           __u32 nlmsg_len;    /* Length of message including header */
           __u16 nlmsg_type;   /* Type of message content */
           __u16 nlmsg_flags;  /* Additional flags */
           __u32 nlmsg_seq;    /* Sequence number */
           __u32 nlmsg_pid;    /* Sender port ID */
};
Ndata is nonez+data is smaller than netlink message headerzGot netlink msg of type %d)	lenNLMSGHDR_SIZEstructunpackNLMSGHDR_FMTMSG_TYPE_OFFSETr5   r6   r   )r   msg_lenmsg_typer   r   r   s         r)   get_netlink_msg_headerrE   O   ss     +^+D	]"545")/d+O,*&Gu3 II*H5E<<r(   c                     U c   S5       e[         R                   " U // / U5      u  n  nX;  a  g[        R                  S5        U R                  [        5      nUc  [        R                  S5        U$ )a  Select and read from the netlink socket if ready.

:param: netlink_socket: specify which socket object to read from
:param: timeout: specify a timeout value (integer) to wait while reading,
        if none, it will block indefinitely until socket ready for read
:returns: string of data read (max length = <MAX_SIZE>) from socket,
          if no data read, returns None
:raises: AssertionError if netlink_socket is None
Nnetlink socket is noneznetlink socket ready for readz,Reading from Netlink socket returned no data)selectr5   r6   recvMAX_SIZEr4   )r7   timeoutread_set_r   s        r)   read_netlink_socketrN   h   sr     %?'??%]]N#3RWENHa %II-.x(D|		@AKr(   c                 H   U c   S5       e[        U[        5      (       d   S5       eU[        :  d   S5       eS=p#Sn [        R                  " SXS9S   n[        R                  " SXS-   S9S   nX[        -   X-    n[        X#U5      $ ! [        R
                   a     gf = f)	a  Unpack a single rta attribute.

:param: data: string of data read from netlink socket
:param: offset: starting offset of RTA Attribute
:return: RTAAttr object with length, type and data. On error, return None.
:raises: AssertionError if data is None or offset is not integer.
Nr<   zoffset is not integerz'rta offset is less than expected lengthr   H)offsetr   )
isinstanceintRTATTR_START_OFFSETr?   unpack_fromr4   RTA_DATA_START_OFFSETr   )r   rQ   r   r   	attr_datas        r)   unpack_rta_attrrX      s     +^+fc"";$;;"%%101%FI##C=a@%%c4
CAF
 33foFI6Y// << s   3B
 
B! B!c                 ~   U c   S5       e[        U 5      [        :  d   S5       eS=p[        nU[        U 5      ::  a  [        X5      nU(       a  UR                  S:X  a  O[        UR                  [        -  -
  [        -  nX4R                  U-   -  nUR
                  [        :X  a  [        UR                  5      nOFUR
                  [        :X  a2  [        R                  " UR                  S5      nUR                  S5      nU[        U 5      ::  a  M  U(       a  Uc  g[        R                  SX5        [        X5      $ )a  Reads Interface name and operational state from RTA Data.

:param: data: string of data read from netlink socket
:returns: InterfaceOperstate object containing if_name and oper_state.
          None if data does not contain valid IFLA_OPERSTATE and
          IFLA_IFNAME messages.
:raises: AssertionError if data is None or length of data is
         smaller than RTATTR_START_OFFSET.
Nr<   z2length of data is smaller than RTATTR_START_OFFSETr   zutf-8 z!rta attrs: ifname %s operstate %d)r=   rT   rX   r   PAD_ALIGNMENTr   IFLA_OPERSTATEordr   IFLA_IFNAMEr   decode_binarystripr5   r6   r   )r   r   r   rQ   attrpadleninterface_names          r)   read_rta_oper_staterd      s    +^+D	''<;<'F F
CI
t,t{{a' T[[=89 	++&&==N*DIII]]k)!//		7CN#))$/F CI
 Y&II16Ef00r(   c                    ^^ [         R                  S5        SmUU4S jn[        U S[        /[        [
        /U5        T$ )zBlock until a single nic is attached.

:param: netlink_socket: netlink_socket to receive events
:param: existing_nics: List of existing nics so that we can skip them.
:raises: AssertionError if netlink_socket is none.
z!Preparing to wait for nic attach.Nc                    > U T;   a  gU mg)NTFr!   )inamecarrierprevCarrierexisting_nicsr   s      r)   should_continue_cb5wait_for_nic_attach_event.<locals>.should_continue_cb   s    M!r(   )r5   r6   read_netlink_messagesRTM_NEWLINKOPER_UP	OPER_DOWN)r7   rj   rk   r   s    ` @r)   wait_for_nic_attach_eventrq      sC     II12F 		) Mr(   c                 t   ^ [         R                  S5        SmU4S jn[        U S[        /[        /U5        T$ )zBlock until a single nic is detached and its operational state is down.

:param: netlink_socket: netlink_socket to receive events.
z!Preparing to wait for nic detach.Nc                 
   > U mg)NFr!   )rg   rh   ri   r   s      r)   rk   5wait_for_nic_detach_event.<locals>.should_continue_cb   s    r(   )r5   r6   rm   RTM_DELLINKrp   )r7   rk   r   s     @r)   wait_for_nic_detach_eventrv      s=    
 II12F
 {mi[:L Mr(   c                    ^ U c   S5       eTc   S5       e[        T5      S:  d   S5       eU4S jn[        R                  S5        [        U T[        [
        /[        [        /U5        g)a  Block until media disconnect and connect has happened on an interface.
Listens on netlink socket to receive netlink events and when the carrier
changes from 0 to 1, it considers event has happened and
return from this function

:param: netlink_socket: netlink_socket to receive events
:param: ifname: Interface name to lookout for netlink events
:raises: AssertionError if netlink_socket is None or ifname is None.
NrG   zinterface name is noner   zinterface name cannot be emptyc                 t   > U[         :H  =(       a	    U[        :H  nU(       a  [        R                  ST5        gg)NzMedia switch happened on %s.FT)rp   ro   r5   r6   )rg   rh   ri   isVnetSwitchr   s       r)   rk   =wait_for_media_disconnect_connect.<locals>.should_continue_cb   s/    #y0Jw'7III4f=r(   z1Wait for media disconnect and reconnect to happen)r=   r5   r6   rm   rn   ru   ro   rp   )r7   r   rk   s    ` r)   !wait_for_media_disconnect_connectr{      st     %?'??%777v;?<<<? IIAB	k"	)r(   c                    U c  [        S5      e[        5       n[        n[        n [        U [        5      nUc  M  [
        R                  S[        U5      5        XX-  n[
        R                  S[        U5      5        Sn	[        U5      n
X:  GaT  XYS n[        U5      [        :  a  [
        R                  S5        GO&[        U5      n[        U5      UR                  :  a  [
        R                  S5        OUR                  [        -   S-
  [        S-
  ) -  nX-   n	[
        R                  S	U	5        UR                  U;  a  M  [        U5      nUc  [
        R                  S
U5        M  Ub4  UR                  U:w  a$  [
        R                  SUR                  U5        GM  UR                  U;  a  GM+  UnUR                  nU" UR                  Xg5      (       d  gX:  a  GMT  XYS nGM  )a  Reads from the netlink socket until the condition specified by
the continuation callback is met.

:param: netlink_socket: netlink_socket to receive events.
:param: ifname_filter: if not None, will only listen for this interface.
:param: rtm_types: Type of netlink events to listen for.
:param: operstates: Operational states to listen.
:param: should_continue_callback: Specifies when to stop listening.
NzNetlink socket is nonezread %d bytes from socketzLength of data after concat %dr   z#Data is smaller than netlink headerz*Partial data. Smaller than netlink messager   z"offset to next netlink message: %dz!Failed to read rta attributes: %sz6Ignored netlink event on interface %s. Waiting for %s.)RuntimeErrorbytesro   rN   SELECT_TIMEOUTr5   r6   r=   r>   rE   r   r[   r   rd   r   r   )r7   ifname_filter	rtm_types
operstatesshould_continue_callbackr   rh   ri   	recv_datarQ   datalennl_msgnlheaderrb   interface_states                  r)   rm   rm     s     3447DGK
'G			-s9~>		2CI>d)']F6{]*		?@-f5H6{X__,		FGoo59!> F _FII:FC}}I-1&9O&		=O)#**m;		L#**!
 ((
:!K%//G+&&  M N G}a r(   )N)3loggingr0   rH   r+   r?   collectionsr   	cloudinitr   	getLoggerr"   r5   r2   rn   ru   RTM_GETLINKRTM_SETLINKrJ   rB   r   rA   IFINFOMSG_FMTcalcsizer>   IFINFOMSG_SIZErT   rV   r[   r^   r\   OPER_UNKNOWNOPER_NOTPRESENTrp   OPER_LOWERLAYERDOWNOPER_TESTINGOPER_DORMANTro   r   r   r   r}   r   r:   rE   rN   rX   rd   rq   rv   r{   rm   r!   r(   r)   <module>r      s0  
  	    " ! -/#n4   	 

Y >
? 4x6MN >
@| @,=2.04"1J:&@Er(   