def nl_socket_alloc(cb=None): """Allocate new Netlink socket. Does not yet actually open a socket. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/socket.c#L206 Also has code for generating local port once. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/nl.c#L123 Keyword arguments: cb -- custom callback handler. Returns: Newly allocated Netlink socket (nl_sock class instance) or None. """ # Allocate the callback. cb = cb or nl_cb_alloc(default_cb) if not cb: return None # Allocate the socket. sk = nl_sock() sk.s_cb = cb sk.s_local.nl_family = getattr(socket, 'AF_NETLINK', -1) sk.s_peer.nl_family = getattr(socket, 'AF_NETLINK', -1) sk.s_seq_expect = sk.s_seq_next = int(time.time()) sk.s_flags = NL_OWN_PORT # The port is 0 (unspecified), meaning NL_OWN_PORT. # Generate local port. nl_socket_get_local_port(sk) # I didn't find this in the C source, but during testing I saw this behavior. return sk
def nl_socket_alloc(cb=None): """Allocate new Netlink socket. Does not yet actually open a socket. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/socket.c#L206 Also has code for generating local port once. https://github.com/thom311/libnl/blob/libnl3_2_25/lib/nl.c#L123 Keyword arguments: cb -- custom callback handler. Returns: Newly allocated Netlink socket (nl_sock class instance) or None. """ # Allocate the callback. cb = cb or nl_cb_alloc(default_cb) if not cb: return None # Allocate the socket. sk = nl_sock() sk.s_cb = cb sk.s_local.nl_family = getattr(socket, 'AF_NETLINK', -1) sk.s_peer.nl_family = getattr(socket, 'AF_NETLINK', -1) sk.s_seq_expect = sk.s_seq_next = int(time.time()) sk.s_flags = NL_OWN_PORT # The port is 0 (unspecified), meaning NL_OWN_PORT. # Generate local port. nl_socket_get_local_port( sk ) # I didn't find this in the C source, but during testing I saw this behavior. return sk
def test_nl_socket_alloc(): r"""C code to test against. // gcc a.c $(pkg-config --cflags --libs libnl-genl-3.0) && ./a.out #include <netlink/msg.h> struct nl_cb { nl_recvmsg_msg_cb_t cb_set[NL_CB_TYPE_MAX+1]; void * cb_args[NL_CB_TYPE_MAX+1]; nl_recvmsg_err_cb_t cb_err; void * cb_err_arg; int (*cb_recvmsgs_ow)(struct nl_sock *, struct nl_cb *); int (*cb_recv_ow)(struct nl_sock *, struct sockaddr_nl *, unsigned char **, struct ucred **); int (*cb_send_ow)(struct nl_sock *, struct nl_msg *); int cb_refcnt; enum nl_cb_type cb_active; }; struct nl_sock { struct sockaddr_nl s_local; struct sockaddr_nl s_peer; int s_fd; int s_proto; unsigned int s_seq_next; unsigned int s_seq_expect; int s_flags; struct nl_cb *s_cb; size_t s_bufsize; }; void print(struct nl_sock *sk) { printf("sk.s_local.nl_family = %d\n", sk->s_local.nl_family); printf("sk.s_local.nl_pid = %d # changes every process, remains same throughout proc.\n", sk->s_local.nl_pid); printf("sk.s_local.nl_groups = %d\n", sk->s_local.nl_groups); printf("sk.s_peer.nl_family = %d\n", sk->s_peer.nl_family); printf("sk.s_peer.nl_pid = %d\n", sk->s_peer.nl_pid); printf("sk.s_peer.nl_groups = %d\n", sk->s_peer.nl_groups); printf("sk.s_fd = %d\n", sk->s_fd); printf("sk.s_proto = %d\n", sk->s_proto); printf("sk.s_flags = %d\n", sk->s_flags); printf("sk.s_cb.cb_active = %d\n", sk->s_cb->cb_active); printf("addr: sk.s_cb.cb_err = %p\n", sk->s_cb->cb_err); } int main() { struct nl_sock *sk = nl_socket_alloc(); print(sk); nl_socket_free(sk); printf("\n"); struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE); sk = nl_socket_alloc_cb(cb); nl_cb_put(cb); print(sk); nl_socket_free(sk); return 0; } // Expected output: // sk.s_local.nl_family = 16 // sk.s_local.nl_pid = 12309 # changes every process, remains same throughout proc. // sk.s_local.nl_groups = 0 // sk.s_peer.nl_family = 16 // sk.s_peer.nl_pid = 0 // sk.s_peer.nl_groups = 0 // sk.s_fd = -1 // sk.s_proto = 0 // sk.s_flags = 0 // sk.s_cb.cb_active = 11 // addr: sk.s_cb.cb_err = (nil) // // sk.s_local.nl_family = 16 // sk.s_local.nl_pid = 12309 # changes every process, remains same throughout proc. // sk.s_local.nl_groups = 0 // sk.s_peer.nl_family = 16 // sk.s_peer.nl_pid = 0 // sk.s_peer.nl_groups = 0 // sk.s_fd = -1 // sk.s_proto = 0 // sk.s_flags = 0 // sk.s_cb.cb_active = 11 // addr: sk.s_cb.cb_err = 0xb6f6eb40 """ sk = nl_socket_alloc() assert 16 == sk.s_local.nl_family assert 0 < sk.s_local.nl_pid assert 0 == sk.s_local.nl_groups assert 16 == sk.s_peer.nl_family assert 0 == sk.s_peer.nl_pid assert 0 == sk.s_peer.nl_groups assert -1 == sk.s_fd assert 0 == sk.s_proto assert 0 == sk.s_flags assert 11 == sk.s_cb.cb_active assert sk.s_cb.cb_err is None nl_socket_free(sk) first_pid = int(sk.s_local.nl_pid) sk = nl_socket_alloc(nl_cb_alloc(NL_CB_VERBOSE)) assert 16 == sk.s_local.nl_family assert first_pid == sk.s_local.nl_pid assert 0 == sk.s_local.nl_groups assert 16 == sk.s_peer.nl_family assert 0 == sk.s_peer.nl_pid assert 0 == sk.s_peer.nl_groups assert -1 == sk.s_fd assert 0 == sk.s_proto assert 0 == sk.s_flags assert 11 == sk.s_cb.cb_active assert sk.s_cb.cb_err is not None nl_socket_free(sk)