/** * Receive a set of messages from a netlink socket. * @arg sk Netlink socket. * @arg cb set of callbacks to control behaviour. * * Repeatedly calls nl_recv() or the respective replacement if provided * by the application (see nl_cb_overwrite_recv()) and parses the * received data as netlink messages. Stops reading if one of the * callbacks returns NL_STOP or nl_recv returns either 0 or a negative error code. * * A non-blocking sockets causes the function to return immediately if * no data is available. * * @see nl_recvmsgs_report() * * @return 0 on success or a negative error code from nl_recv(). */ int nl_recvmsgs(struct nl_sock *sk, struct nl_cb *cb) { int err; if ((err = nl_recvmsgs_report(sk, cb)) > 0) err = 0; return err; }
int main() { struct nl_sock * sk; int cbarg; // nl_debug = 4; // setup netlink socket sk = nl_socket_alloc(); nl_socket_disable_seq_check(sk); // disable sequence number check genl_connect(sk); int id = genl_ctrl_resolve(sk, DEMO_FAMILY_NAME); struct nl_msg * msg; // create a messgae msg = nlmsg_alloc(); genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, id, 0, // hdrlen 0, // flags DEMO_CMD, // numeric command identifier DEMO_VERSION // interface version ); nla_put_string(msg, DEMO_ATTR1_STRING, "hola"); nla_put_u16(msg, DEMO_ATTR2_UINT16, 0xf1); // send it nl_send_auto(sk, msg); // handle reply struct nl_cb * cb = NULL; cb = nl_cb_alloc(NL_CB_CUSTOM); //nl_cb_set_all(cb, NL_CB_DEBUG, NULL, NULL); nl_cb_set_all(cb, NL_CB_CUSTOM, cb_handler, &cbarg); nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL); int nrecv = nl_recvmsgs_report(sk, cb); printf("cbarg %d nrecv %d\n", cbarg, nrecv); // cleanup nlmsg_free(msg); nl_close(sk); nl_socket_free(sk); return 0; }
/** * Check for event notifications * @arg mngr Cache Manager * @arg timeout Upper limit poll() will block, in milliseconds. * * Causes poll() to be called to check for new event notifications * being available. Calls nl_cache_mngr_data_ready() to process * available data. * * This functionally is ideally called regularly during an idle * period. * * A timeout can be specified in milliseconds to limit the time the * function will wait for updates. * * @see nl_cache_mngr_data_ready() * * @return The number of messages processed or a negative error code. */ int nl_cache_mngr_poll(struct nl_cache_mngr *mngr, int timeout) { int ret; struct pollfd fds = { .fd = nl_socket_get_fd(mngr->cm_sock), .events = POLLIN, }; NL_DBG(3, "Cache manager %p, poll() fd %d\n", mngr, fds.fd); ret = poll(&fds, 1, timeout); NL_DBG(3, "Cache manager %p, poll() returned %d\n", mngr, ret); if (ret < 0) return -nl_syserr2nlerr(errno); /* No events, return */ if (ret == 0) return 0; return nl_cache_mngr_data_ready(mngr); } /** * Receive available event notifications * @arg mngr Cache manager * * This function can be called if the socket associated to the manager * contains updates to be received. This function should only be used * if nl_cache_mngr_poll() is not used. * * The function will process messages until there is no more data to * be read from the socket. * * @see nl_cache_mngr_poll() * * @return The number of messages processed or a negative error code. */ int nl_cache_mngr_data_ready(struct nl_cache_mngr *mngr) { int err, nread = 0; struct nl_cb *cb; NL_DBG(2, "Cache manager %p, reading new data from fd %d\n", mngr, nl_socket_get_fd(mngr->cm_sock)); cb = nl_cb_clone(mngr->cm_sock->s_cb); if (cb == NULL) return -NLE_NOMEM; nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, event_input, mngr); while ((err = nl_recvmsgs_report(mngr->cm_sock, cb)) > 0) { NL_DBG(2, "Cache manager %p, recvmsgs read %d messages\n", mngr, err); nread += err; } nl_cb_put(cb); if (err < 0 && err != -NLE_AGAIN) return err; return nread; }