a '¡Dg›.ã@sBddlZddlZddlZddlZddlZddlmZddlmZe  e ¡Z dZ dZ dZdZdZd ZdZd Zd Zd Ze e¡Ze e¡ZeeZd Zd ZdZdZdZdZdZ dZ!d Z"dZ#dZ$edgd¢ƒZ%edddgƒZ&edgd¢ƒZ'Gdd„de(ƒZ)dd„Z*dd„Z+d-dd „Z,d!d"„Z-d#d$„Z.d%d&„Z/d'd(„Z0d)d*„Z1d+d,„Z2dS).éN)Ú namedtuple)Úutiléééééiÿÿé<ZIHHIIZBHiIIéééééÚRTAAttr)ÚlengthÚrta_typeÚdataÚInterfaceOperstateÚifnameÚ operstateÚ NetlinkHeader)rÚtypeÚflagsÚseqÚpidc@seZdZdZdS)ÚNetlinkCreateSocketErrorz5Raised if netlink socket fails during create or bind.N)Ú__name__Ú __module__Ú __qualname__Ú__doc__©r r úE/usr/lib/python3.9/site-packages/cloudinit/sources/helpers/netlink.pyr5src Cs|z4t tjtjtj¡}| t ¡tf¡| d¡Wn8tj yl}zd|}t |ƒ|‚WYd}~n d}~00t   d¡|S)auCreates 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 rz*Exception during netlink socket create: %sNzCreated netlink socket) ÚsocketZ AF_NETLINKZSOCK_RAWZ NETLINK_ROUTEZbindÚosÚgetpidÚ RTMGRP_LINKZ setblockingÚerrorrÚLOGÚdebug)Únetlink_socketÚeÚmsgr r r!Úcreate_bound_netlink_socket9s  ÿ  r,cCs^|dusJdƒ‚t|ƒtks$Jdƒ‚t t|dt…¡\}}}}}t d|¡t|||||ƒS)aGets 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 headerzGot netlink msg of type %d) ÚlenÚ NLMSGHDR_SIZEÚstructÚunpackÚ NLMSGHDR_FMTÚMSG_TYPE_OFFSETr'r(r)rZmsg_lenZmsg_typerrrr r r!Úget_netlink_msg_headerOs ÿþ ÿ r4cCs^|dusJdƒ‚t |ggg|¡\}}}||vr4dSt d¡| t¡}|durZt 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 = ) from socket, if no data read, returns None :raises: AssertionError if netlink_socket is None Núnetlink socket is noneznetlink socket ready for readz,Reading from Netlink socket returned no data)Úselectr'r(ZrecvÚMAX_SIZEr&)r)ÚtimeoutZread_setÚ_rr r r!Úread_netlink_sockeths    r:cCs¦|dusJdƒ‚t|tƒs"Jdƒ‚|tks2Jdƒ‚d}}d}z0tjd||d�d}tjd||dd�d}Wntjy„YdS0||t||…}t|||ƒS) 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-zoffset is not integerz'rta offset is less than expected lengthrÚH)Úoffsetr )Ú isinstanceÚintÚRTATTR_START_OFFSETr0Ú unpack_fromr&ÚRTA_DATA_START_OFFSETr)rr<rrZ attr_datar r r!Úunpack_rta_attrsÿþrBcCsØ|dusJdƒ‚t|ƒtks$Jdƒ‚d}}t}|t|ƒkr°t||ƒ}|r°|jdkrVq°t|jtt}||j|7}|jtkrŒt|jƒ}q0|jt kr0t   |jd¡}|  d¡}q0|r¼|durÀdSt  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. Nr-z2length of data is smaller than RTATTR_START_OFFSETrzutf-8úz!rta attrs: ifname %s operstate %d)r.r?rBrÚ PAD_ALIGNMENTrÚIFLA_OPERSTATEÚordrÚ IFLA_IFNAMErZ decode_binaryÚstripr'r(r)rrrr<ÚattrÚpadlenZinterface_namer r r!Úread_rta_oper_state™s0  ÿþ   þ     rKcs6t d¡d‰‡‡fdd„}t|dtgttg|ƒˆ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.Ncs|ˆvr dS|‰dS)NTFr ©ÚinameÚcarrierÚ prevCarrier©Ú existing_nicsrr r!Úshould_continue_cbÈsz5wait_for_nic_attach_event..should_continue_cb)r'r(Úread_netlink_messagesÚ RTM_NEWLINKÚOPER_UPÚ OPER_DOWN)r)rQrRr rPr!Úwait_for_nic_attach_event¾s  ûrWcs2t d¡d‰‡fdd„}t|dtgtg|ƒˆ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.Ncs|‰dS)NFr rL©rr r!rRãsz5wait_for_nic_detach_event..should_continue_cb)r'r(rSÚ RTM_DELLINKrV)r)rRr rXr!Úwait_for_nic_detach_eventÛs  ÿrZcsf|dusJdƒ‚ˆdus Jdƒ‚tˆƒdks4Jdƒ‚‡fdd„}t d¡t|ˆttgttg|ƒdS) 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. Nr5zinterface name is nonerzinterface name cannot be emptycs(|tko|tk}|r$t dˆ¡dSdS)NzMedia switch happened on %s.FT)rVrUr'r()rMrNrOZ isVnetSwitchrXr r!rRüs  z=wait_for_media_disconnect_connect..should_continue_cbz1Wait for media disconnect and reconnect to happen)r.r'r(rSrTrYrUrV)r)rrRr rXr!Ú!wait_for_media_disconnect_connectîs   ûr[cCsx|durtdƒ‚tƒ}t}t}t|tƒ}|dur2qt dt|ƒ¡||7}t dt|ƒ¡d} t|ƒ} | | k�rf|| d…} t| ƒtkr–t d¡�qft | ƒ} t| ƒ| j krºt d¡�qf| j t dt d@} | | } t d | ¡| j |vròqft | ƒ}|du�rt d |¡qf|du�r:|j|k�r:t d |j|¡qf|j|v�rHqf|}|j}||j||ƒsfdSqf|| d…}qdS) 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. NzNetlink socket is nonezread %d bytes from socketzLength of data after concat %drz#Data is smaller than netlink headerz*Partial data. Smaller than netlink messagerz"offset to next netlink message: %dz!Failed to read rta attributes: %sz6Ignored netlink event on interface %s. Waiting for %s.)Ú RuntimeErrorÚbytesrUr:ÚSELECT_TIMEOUTr'r(r.r/r4rrDrrKrr)r)Z ifname_filterZ rtm_typesZ operstatesZshould_continue_callbackrrNrOZ recv_datar<ZdatalenZnl_msgZnlheaderrJZinterface_stater r r!rSsh       ÿ    ÿþý ÿrS)N)3Zloggingr#r6r"r0Ú collectionsrZ cloudinitrZ getLoggerrr'r%rTrYZ RTM_GETLINKZ RTM_SETLINKr7r3r^r2Z IFINFOMSG_FMTÚcalcsizer/ZIFINFOMSG_SIZEr?rArDrGrEZ OPER_UNKNOWNZOPER_NOTPRESENTrVZOPER_LOWERLAYERDOWNZ OPER_TESTINGZ OPER_DORMANTrUrrrr\rr,r4r:rBrKrWrZr[rSr r r r!Ús\     ÿ %