def recvmsgs(sk, cb):
multipart = <NUM_LIT:0><EOL>interrupted = <NUM_LIT:0><EOL>nrecv = <NUM_LIT:0><EOL>buf = bytearray()<EOL>nla = sockaddr_nl()<EOL>creds = ucred()<EOL>while True:  <EOL><INDENT>_LOGGER.debug('<STR_LIT>', id(sk))<EOL>n = c_int(cb.cb_recv_ow(sk, nla, buf, creds) if cb.cb_recv_ow else nl_recv(sk, nla, buf, creds))<EOL>if n.value <= <NUM_LIT:0>:<EOL><INDENT>return n.value<EOL><DEDENT>_LOGGER.debug('<STR_LIT>', id(sk), n.value)<EOL>hdr = nlmsghdr(bytearray_ptr(buf))<EOL>while nlmsg_ok(hdr, n):<EOL><INDENT>_LOGGER.debug('<STR_LIT>', id(sk))<EOL>msg = nlmsg_convert(hdr)<EOL>nlmsg_set_proto(msg, sk.s_proto)<EOL>nlmsg_set_src(msg, nla)<EOL>if creds:<EOL><INDENT>raise NotImplementedError  <EOL><DEDENT>nrecv += <NUM_LIT:1><EOL>if cb.cb_set[NL_CB_MSG_IN]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_MSG_IN, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT>if cb.cb_set[NL_CB_SEQ_CHECK]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_SEQ_CHECK, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT>elif not sk.s_flags & NL_NO_AUTO_ACK:<EOL><INDENT>if hdr.nlmsg_seq != sk.s_seq_expect:<EOL><INDENT>if cb.cb_set[NL_CB_INVALID]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_INVALID, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return -NLE_SEQ_MISMATCH<EOL><DEDENT><DEDENT><DEDENT>if hdr.nlmsg_type in (NLMSG_DONE, NLMSG_ERROR, NLMSG_NOOP, NLMSG_OVERRUN):<EOL><INDENT>sk.s_seq_expect += <NUM_LIT:1><EOL>_LOGGER.debug('<STR_LIT>', id(sk), sk.s_seq_expect)<EOL><DEDENT>if hdr.nlmsg_flags & NLM_F_MULTI:<EOL><INDENT>multipart = <NUM_LIT:1><EOL><DEDENT>if hdr.nlmsg_flags & NLM_F_DUMP_INTR:<EOL><INDENT>if cb.cb_set[NL_CB_DUMP_INTR]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_DUMP_INTR, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>interrupted = <NUM_LIT:1><EOL><DEDENT><DEDENT>if hdr.nlmsg_flags & NLM_F_ACK:<EOL><INDENT>if cb.cb_set[NL_CB_SEND_ACK]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_SEND_ACK, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT><DEDENT>if hdr.nlmsg_type == NLMSG_DONE:<EOL><INDENT>multipart = <NUM_LIT:0><EOL>if cb.cb_set[NL_CB_FINISH]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_FINISH, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT><DEDENT>elif hdr.nlmsg_type == NLMSG_NOOP:<EOL><INDENT>if cb.cb_set[NL_CB_SKIPPED]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_SKIPPED, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT><DEDENT>elif hdr.nlmsg_type == NLMSG_OVERRUN:<EOL><INDENT>if cb.cb_set[NL_CB_OVERRUN]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_OVERRUN, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else -NLE_MSG_OVERFLOW<EOL><DEDENT><DEDENT>elif hdr.nlmsg_type == NLMSG_ERROR:<EOL><INDENT>e = nlmsgerr(nlmsg_data(hdr))<EOL>if hdr.nlmsg_len < nlmsg_size(e.SIZEOF):<EOL><INDENT>if cb.cb_set[NL_CB_INVALID]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_INVALID, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else -NLE_MSG_TRUNC<EOL><DEDENT><DEDENT>elif e.error:<EOL><INDENT>if cb.cb_err:<EOL><INDENT>err = cb.cb_err(nla, e, cb.cb_err_arg)<EOL>if err < <NUM_LIT:0>:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else err<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else -nl_syserr2nlerr(e.error)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else -nl_syserr2nlerr(e.error)<EOL><DEDENT><DEDENT>elif cb.cb_set[NL_CB_ACK]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_ACK, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>if cb.cb_set[NL_CB_VALID]:<EOL><INDENT>err = nl_cb_call(cb, NL_CB_VALID, msg)  <EOL>if err == NL_OK:<EOL><INDENT>pass<EOL><DEDENT>elif err == NL_SKIP:<EOL><INDENT>hdr = nlmsg_next(hdr, n)<EOL>continue<EOL><DEDENT>elif err == NL_STOP:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else nrecv<EOL><DEDENT>else:<EOL><INDENT>return -NLE_DUMP_INTR if interrupted else (err or nrecv)<EOL><DEDENT><DEDENT><DEDENT>hdr = nlmsg_next(hdr, n)<EOL><DEDENT>del buf[:]<EOL>creds = None<EOL>if multipart:<EOL><INDENT>continue<EOL><DEDENT>err = <NUM_LIT:0><EOL>if interrupted:<EOL><INDENT>return -NLE_DUMP_INTR<EOL><DEDENT>if not err:<EOL><INDENT>err = nrecv<EOL><DEDENT>return err<EOL><DEDENT>
https://github.com/thom311/libnl/blob/libnl3_2_25/lib/nl.c#L775.

    This is where callbacks are called.

    Positional arguments:
    sk -- Netlink socket (nl_sock class instance).
    cb -- callbacks (nl_cb class instance).

    Returns:
    Number of bytes received or a negative error code.