def nl_wait_for_ack(sk): """Wait for ACK. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/nl.c#L1058 Waits until an ACK is received for the latest not yet acknowledged Netlink message. Positional arguments: sk -- Netlink socket (nl_sock class instance). Returns: Number of received messages or a negative error code from nl_recvmsgs(). """ cb = nl_cb_clone(sk.s_cb) nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, lambda *_: NL_STOP, None) return int(nl_recvmsgs(sk, cb))
def genl_ctrl_probe_by_name(sk, name): """Look up generic Netlink family by family name querying the kernel directly. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/genl/ctrl.c#L237 Directly query's the kernel for a given family name. Note: This API call differs from genl_ctrl_search_by_name in that it queries the kernel directly, allowing for module autoload to take place to resolve the family request. Using an nl_cache prevents that operation. Positional arguments: sk -- Generic Netlink socket (nl_sock class instance). name -- family name (bytes). Returns: Generic Netlink family `genl_family` class instance or None if no match was found. """ ret = genl_family_alloc() if not ret: return None genl_family_set_name(ret, name) msg = nlmsg_alloc() orig = nl_socket_get_cb(sk) cb = nl_cb_clone(orig) genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1) nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, ret) if nl_send_auto(sk, msg) < 0: return None if nl_recvmsgs(sk, cb) < 0: return None if wait_for_ack( sk ) < 0: # If search was successful, request may be ACKed after data. return None if genl_family_get_id(ret) != 0: return ret
def genl_ctrl_probe_by_name(sk, name): """Look up generic Netlink family by family name querying the kernel directly. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/genl/ctrl.c#L237 Directly query's the kernel for a given family name. Note: This API call differs from genl_ctrl_search_by_name in that it queries the kernel directly, allowing for module autoload to take place to resolve the family request. Using an nl_cache prevents that operation. Positional arguments: sk -- Generic Netlink socket (nl_sock class instance). name -- family name (bytes). Returns: Generic Netlink family `genl_family` class instance or None if no match was found. """ ret = genl_family_alloc() if not ret: return None genl_family_set_name(ret, name) msg = nlmsg_alloc() orig = nl_socket_get_cb(sk) cb = nl_cb_clone(orig) genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1) nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, probe_response, ret) if nl_send_auto(sk, msg) < 0: return None if nl_recvmsgs(sk, cb) < 0: return None if wait_for_ack(sk) < 0: # If search was successful, request may be ACKed after data. return None if genl_family_get_id(ret) != 0: return ret
def nl_socket_modify_cb(sk, type_, kind, func, arg): """Modify the callback handler associated with the socket. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/socket.c#L633 Sets specific callback functions in the existing nl_cb class instance stored in the nl_sock socket. Positional arguments: sk -- Netlink socket (nl_sock class instance). type_ -- which type callback to set (integer). kind -- kind of callback (integer). func -- callback function. arg -- argument to be passed to callback function. Returns: 0 on success or a negative error code. """ return int(nl_cb_set(sk.s_cb, type_, kind, func, arg))