a 'Dg.@sBddlZddlZddlZddlZddlZddlmZddlmZe e Z dZ dZ dZdZdZd ZdZd Zd Zd ZeeZeeZeeZd Zd ZdZdZdZdZdZ dZ!d Z"dZ#dZ$edgdZ%edddgZ&edgdZ'Gddde(Z)ddZ*ddZ+d-dd Z,d!d"Z-d#d$Z.d%d&Z/d'd(Z0d)d*Z1d+d,Z2dS).N) namedtuple)utili<ZIHHIIZBHiIIRTAAttr)lengthrta_typedataInterfaceOperstateifname operstate NetlinkHeader)rtypeflagsseqpidc@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|z4ttjtjtj}|ttf|dWn8tj 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_ROUTEZbindosgetpid RTMGRP_LINKZ setblockingerrorrLOGdebug)netlink_socketemsgr r r!create_bound_netlink_socket9s    r,cCs:tt|dt\}}}}}td|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 */ }; NzGot netlink msg of type %d)structunpack NLMSGHDR_FMTMSG_TYPE_OFFSETr'r(r)rZmsg_lenZmsg_typerrrr r r!get_netlink_msg_headerOs   r1cCsNt|ggg|\}}}||vr$dStd|t}|durJtd|S)aSelect 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 Nznetlink socket ready for readz,Reading from Netlink socket returned no data)selectr'r(ZrecvMAX_SIZEr&)r)timeoutZread_set_rr r r!read_netlink_sockeths    r6cCstd}}d}z0tjd||dd}tjd||ddd}WntjyRYdS0||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. rNH)offsetr )r- unpack_fromr&RTA_DATA_START_OFFSETr)rr8rrZ attr_datar r r!unpack_rta_attrs r;cCsd}}t}|t|krt||}|r|jdkr2qt|jtt}||j|7}|jtkrht|j}q |jt kr t |jd}| d}q |r|durdSt d||t||S)aReads 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. Nrzutf-8z!rta attrs: ifname %s operstate %d)RTATTR_START_OFFSETlenr;r PAD_ALIGNMENTrIFLA_OPERSTATEordr IFLA_IFNAMErZ decode_binarystripr'r(r)rrrr8attrpadlenZinterface_namer r r!read_rta_oper_states&        rFcs6tddfdd}t|dtgttg|S)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.Ncs|vr dS|dS)NTFr inamecarrier prevCarrier existing_nicsrr r!should_continue_cbsz5wait_for_nic_attach_event..should_continue_cb)r'r(read_netlink_messages RTM_NEWLINKOPER_UP OPER_DOWN)r)rLrMr rKr!wait_for_nic_attach_events  rRcs2tddfdd}t|dtgtg|S)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.Ncs|dS)NFr rGrr r!rMsz5wait_for_nic_detach_event..should_continue_cb)r'r(rN RTM_DELLINKrQ)r)rMr rSr!wait_for_nic_detach_events  rUcs2fdd}tdt|ttgttg|dS)aBlock 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. cs(|tko|tk}|r$tddSdS)NzMedia switch happened on %s.FT)rQrPr'r()rHrIrJZ isVnetSwitchrSr r!rMs  z=wait_for_media_disconnect_connect..should_continue_cbz1Wait for media disconnect and reconnect to happenN)r'r(rNrOrTrPrQ)r)rrMr rSr!!wait_for_media_disconnect_connects  rVcCsx|durtdt}t}t}t|t}|dur2qtdt|||7}tdt|d} t|} | | krf|| d} t| tkrtdqft | } t| | j krtdqf| j t dt d@} | | } td | | j |vrqft | }|durtd |qf|dur:|j|kr:td |j|qf|j|vrHqf|}|j}||j||sfdSqf|| d}qdS) aReads 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.) RuntimeErrorbytesrPr6SELECT_TIMEOUTr'r(r> NLMSGHDR_SIZEr1rr?rrFrr)r)Z ifname_filterZ rtm_typesZ operstatesZshould_continue_callbackrrIrJZ recv_datar8ZdatalenZnl_msgZnlheaderrEZinterface_stater r r!rNsh            rN)N)3Zloggingr#r2r"r- collectionsrZ cloudinitrZ getLoggerrr'r%rOrTZ RTM_GETLINKZ RTM_SETLINKr3r0rYr/Z IFINFOMSG_FMTcalcsizerZZIFINFOMSG_SIZEr=r:r?rBr@Z OPER_UNKNOWNZOPER_NOTPRESENTrQZOPER_LOWERLAYERDOWNZ OPER_TESTINGZ OPER_DORMANTrPrrrrWrr,r1r6r;rFrRrUrVrNr r r r!s\      %