Ë
    x[h›.  ã                   óž  — 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mZ  e j                  e
«      ZdZdZdZdZdZd	ZdZd
ZdZdZ ej,                  e«      Z ej,                  e«      Zeez   ZdZdZdZdZd ZdZdZ dZ!dZ"dZ#dZ$ edg d¢«      Z% edddg«      Z& edg d¢«      Z' G d„ de(«      Z)d„ Z*d„ Z+d$d„Z,d„ Z-d„ Z.d „ Z/d!„ Z0d"„ Z1d#„ Z2y)%é    N)Ú
namedtuple)Úutilé   é   é   é   é   iÿÿ  é<   ÚIHHIIÚBHiIIé   é   é   é   é   ÚRTAAttr)ÚlengthÚrta_typeÚdataÚInterfaceOperstateÚifnameÚ	operstateÚNetlinkHeader)r   ÚtypeÚflagsÚseqÚpidc                   ó   — e Zd ZdZy)ÚNetlinkCreateSocketErrorz5Raised if netlink socket fails during create or bind.N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    úC/usr/lib/python3/dist-packages/cloudinit/sources/helpers/netlink.pyr   r   5   s   „ Ú?r%   r   c                  ó€  — 	 t        j                   t         j                  t         j                  t         j                  «      } | j	                  t        j                  «       t        f«       | j                  d«       t        j                  d«       | S # t         j                  $ r}d|z  }t        |«      |‚d}~ww xY w)au  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_socketr7   9   s—   € ð3ÜŸ™Ü×ÑœvŸ™´×0DÑ0Dó
ˆð 	×ÑœRŸY™Y›[¬+Ð6Ô7Ø×"Ñ" 1Ô%ô ‡I�IÐ&Ô'ØÐøô	 �<‰<ò 3Ø:¸QÑ>ˆÜ& sÓ+°Ð2ûð3ús   ‚A;B ÂB=Â'B8Â8B=c                 óÞ   — | €J d«       ‚t        | «      t        k\  sJ d«       ‚t        j                  t        | dt
         «      \  }}}}}t        j                  d|«       t        |||||«      S )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_OFFSETr2   r3   r   )r   Úmsg_lenÚmsg_typer   r   r   s         r&   Úget_netlink_msg_headerrB   O   s{   € ð ÐÐ+˜^Ó+ÐäˆD‹	”]Ò"ð5à4ó5Ø"ä)/¯©Ü�dÐ+œOÐ,ó*Ñ&€GˆX�u˜c 3ô ‡I�IÐ*¨HÔ5Ü˜ (¨E°3¸Ó<Ð<r%   c                 óÞ   — | €J d«       ‚t        j                   | gg g |«      \  }}}| |vryt        j                  d«       | j                  t        «      }|€t        j                  d«       |S )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)Úselectr2   r3   ÚrecvÚMAX_SIZEr1   )r4   ÚtimeoutÚread_setÚ_r   s        r&   Úread_netlink_socketrK   h   st   € ð Ð%Ð?Ð'?Ó?Ð%Ü—]‘] NÐ#3°R¸¸WÓE�N€Hˆa�ð ˜XÑ%ØÜ‡I�IÐ-Ô.Ø×ÑœxÓ(€DØ€|Ü�	‰	Ð@ÔAØ€Kr%   c                 óL  — | €J d«       ‚t        |t        «      sJ d«       ‚|t        k\  sJ d«       ‚dx}}d}	 t        j                  d| |¬«      d   }t        j                  d| |dz   ¬«      d   }| |t        z   ||z    }t        |||«      S # t        j
                  $ r Y yw xY w)	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.
    Nr9   zoffset is not integerz'rta offset is less than expected lengthr   ÚH)Úoffsetr   )Ú
isinstanceÚintÚRTATTR_START_OFFSETr<   Úunpack_fromr1   ÚRTA_DATA_START_OFFSETr   )r   rN   r   r   Ú	attr_datas        r&   Úunpack_rta_attrrU      sÍ   € ð ÐÐ+˜^Ó+ÐÜ�fœcÔ"Ð;Ð$;Ó;Ð"àÔ%Ò%ð1à0ó1Ø%àÐ€FˆXØ€IðÜ×#Ñ# C¨°fÔ=¸aÑ@ˆÜ×%Ñ% c¨4¸À¹
ÔCÀAÑFˆð
 �VÔ3Ñ3°f¸v±oÐF€IÜ�6˜8 YÓ/Ð/øô �<‰<ò Ùðús   ¸9B ÂB#Â"B#c                 ó`  — | €J d«       ‚t        | «      t        kD  sJ d«       ‚dx}}t        }|t        | «      k  rÍt        | |«      }|r|j                  dk(  rn¯t        |j                  t        z  z
  t        z  }||j                  |z   z  }|j
                  t        k(  rt        |j                  «      }nD|j
                  t        k(  r1t        j                  |j                  d«      }|j                  d«      }|t        | «      k  rŒÍ|r|€yt        j                  d||«       t        ||«      S )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.
    Nr9   z2length of data is smaller than RTATTR_START_OFFSETr   zutf-8ú z!rta attrs: ifname %s operstate %d)r:   rQ   rU   r   ÚPAD_ALIGNMENTr   ÚIFLA_OPERSTATEÚordr   ÚIFLA_IFNAMEr   Údecode_binaryÚstripr2   r3   r   )r   r   r   rN   ÚattrÚpadlenÚinterface_names          r&   Úread_rta_oper_statera   ™   s   € ð ÐÐ+˜^Ó+ÐäˆD‹	Ô'Ò'ð<à;ó<Ø'àÐ€FˆYÜ €FØ
”C˜“IÒ
Ü˜t VÓ,ˆÙ�t—{‘{ aÒ'Øô ˜TŸ[™[¬=Ñ8Ñ9Üñˆð 	�$—+‘+ Ñ&Ñ&ˆà�=‰=œNÒ*Ü˜DŸI™I›‰IØ�]‰]œkÒ)Ü!×/Ñ/°·	±	¸7ÓCˆNØ#×)Ñ)¨$Ó/ˆFð ”C˜“IÓ
ñ �YÐ&ØÜ‡I�IÐ1°6¸9ÔEÜ˜f iÓ0Ð0r%   c                 ó€   ‡‡— t         j                  d«       dŠˆˆfd„}t        | dt        gt        t
        g|«       ‰S )zêBlock 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                 ó   •— | ‰v ry| Šy)NTFr$   )ÚinameÚcarrierÚprevCarrierÚexisting_nicsr   s      €€r&   Úshould_continue_cbz5wait_for_nic_attach_event.<locals>.should_continue_cbÈ   s   ø€ Ø�MÑ!ØàˆØr%   )r2   r3   Úread_netlink_messagesÚRTM_NEWLINKÚOPER_UPÚ	OPER_DOWN)r4   rg   rh   r   s    ` @r&   Úwait_for_nic_attach_eventrm   ¾   sC   ù€ ô ‡I�IÐ1Ô2Ø€Fõô ØØÜ	ˆÜ	”)ÐØôð €Mr%   c                 ór   ‡— t         j                  d«       dŠˆfd„}t        | dt        gt        g|«       ‰S )z‹Block 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                 ó
   •— | Šy)NFr$   )rd   re   rf   r   s      €r&   rh   z5wait_for_nic_detach_event.<locals>.should_continue_cbã   s   ø€ àˆØr%   )r2   r3   ri   ÚRTM_DELLINKrl   )r4   rh   r   s     @r&   Úwait_for_nic_detach_eventrq   Û   s=   ø€ ô
 ‡I�IÐ1Ô2Ø€Fôô
 Ø˜œ{˜m¬i¨[Ð:Lôð €Mr%   c                 óÎ   ‡— | €J d«       ‚‰€J d«       ‚t        ‰«      dkD  sJ d«       ‚ˆfd„}t        j                  d«       t        | ‰t        t
        gt        t        g|«       y)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.
    NrD   zinterface name is noner   zinterface name cannot be emptyc                 ó`   •— |t         k(  xr	 |t        k(  }|rt        j                  d‰«       yy)NzMedia switch happened on %s.FT)rl   rk   r2   r3   )rd   re   rf   ÚisVnetSwitchr   s       €r&   rh   z=wait_for_media_disconnect_connect.<locals>.should_continue_cbü   s/   ø€ à#¤yÑ0ÒJ°wÄ'Ñ7IˆÙÜ�I‰IÐ4°fÔ=ØØr%   z1Wait for media disconnect and reconnect to happen)r:   r2   r3   ri   rj   rp   rk   rl   )r4   r   rh   s    ` r&   Ú!wait_for_media_disconnect_connectru   î   st   ø€ ð Ð%Ð?Ð'?Ó?Ð%ØÐÐ7Ð7Ó7ÐÜˆv‹;˜Š?Ð<Ð<Ó<ˆ?ôô ‡I�IÐAÔBÜØØÜ	”kÐ"Ü	”)ÐØõr%   c                 ó²  — | €t        d«      ‚t        «       }t        }t        }	 t        | t        «      }|€Œt
        j                  dt        |«      «       ||z  }t
        j                  dt        |«      «       d}	t        |«      }
|	|
k  �rD||	d }t        |«      t        k  rt
        j                  d«       �nt        |«      }t        |«      |j                  k  rt
        j                  d«       nÝ|j                  t        z   dz
  t        dz
   z  }|	|z   }	t
        j                  d	|	«       |j                  |vrŒ¸t        |«      }|€t
        j                  d
|«       ŒÜ|�2|j                  |k7  r#t
        j                  d|j                  |«       �Œ|j                  |vr�Œ |}|j                  } ||j                  ||«      sy|	|
k  r�ŒD||	d }�Œ´)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Úbytesrk   rK   ÚSELECT_TIMEOUTr2   r3   r:   r;   rB   r   rX   r   ra   r   r   )r4   Úifname_filterÚ	rtm_typesÚ
operstatesÚshould_continue_callbackr   re   rf   Ú	recv_datarN   ÚdatalenÚnl_msgÚnlheaderr_   Úinterface_states                  r&   ri   ri     sÔ  € ð  ÐÜÐ3Ó4Ð4Ü‹7€DÜ€GÜ€KØ
Ü'¨¼ÓGˆ	ØÐØÜ�	‰	Ð-¬s°9«~Ô>Ø�	ÑˆÜ�	‰	Ð2´C¸³IÔ>ØˆÜ�d“)ˆØ�wÓØ˜&˜'�]ˆFÜ�6‹{œ]Ò*Ü—	‘	Ð?Ô@ÙÜ-¨fÓ5ˆHÜ�6‹{˜XŸ_™_Ò,Ü—	‘	ÐFÔGØØ—o‘o¬Ñ5¸Ñ9Ü Ñ!ð>ñ ˆFð ˜f‘_ˆFÜ�I‰IÐ:¸FÔCà�}‰} IÑ-ØÜ1°&Ó9ˆOØÐ&Ü—	‘	Ð=¸ÔOØàÐ)Ø#×*Ñ*¨mÒ;ä—	‘	ØLØ#×*Ñ*Ø!ôñ
 Ø×(Ñ(°
Ñ:ÙØ!ˆKØ%×/Ñ/ˆGÙ+Ø×&Ñ&¨°ôð ðM �wÔðN �F�Gˆ}ˆña r%   )N)3Úloggingr-   rE   r(   r<   Úcollectionsr   Ú	cloudinitr   Ú	getLoggerr    r2   r/   rj   rp   ÚRTM_GETLINKÚRTM_SETLINKrG   r?   ry   r>   ÚIFINFOMSG_FMTÚcalcsizer;   ÚIFINFOMSG_SIZErQ   rS   rX   r[   rY   ÚOPER_UNKNOWNÚOPER_NOTPRESENTrl   ÚOPER_LOWERLAYERDOWNÚOPER_TESTINGÚOPER_DORMANTrk   r   r   r   rw   r   r7   rB   rK   rU   ra   rm   rq   ru   ri   r$   r%   r&   ú<module>r‘      s6  ðó
 Û 	Û Û Û Ý "å à€g×Ñ˜Ó!€ð €Ø€Ø€Ø€Ø€Ø€Ø€Ø€à€Ø€Ø�—‘ Ó-€Ø �—‘ Ó/€Ø# nÑ4Ð ØÐ Ø€à€Ø€ð €Ø€Ø€	ØÐ Ø€Ø€Ø
€á
�YÒ >Ó
?€ÙÐ 4°xÀÐ6MÓNÐ ÙØÒ>ó€ô
@˜|ô @òò,=ó2ò.0ò4"1òJò:ò&ó@Er%   