ssize_t ipulog_read(struct ipulog_handle *h, unsigned char *buf, size_t len, int timeout) { /* 'timeout' was never implemented in the original libipulog, * so we don't bother emulating it */ return nfnl_recv(nflog_nfnlh(h->nfulh), buf, len); }
/** * nfnl_catch - get responses from the nfnetlink system and process them * @h: nfnetlink handler * * This function handles the data received from the nfnetlink system. * For example, events generated by one of the subsystems. The message * is passed to the callback registered via callback_register(). Note that * this a replacement of nfnl_listen and its use is recommended. * * On success, 0 is returned. On error, a -1 is returned. If you do not * want to listen to events anymore, then your callback must return * NFNL_CB_STOP. * * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In * that case is possible that the information requested is incomplete. */ int nfnl_catch(struct nfnl_handle *h) { int ret; assert(h); while (1) { unsigned char buf[h->rcv_buffer_size] __attribute__ ((aligned)); ret = nfnl_recv(h, buf, sizeof(buf)); if (ret == -1) { /* interrupted syscall must retry */ if (errno == EINTR) continue; break; } ret = nfnl_process(h, buf, ret); if (ret <= NFNL_CB_STOP) break; } return ret; }
/** * nfnl_catch - get responses from the nfnetlink system and process them * @h: nfnetlink handler * * This function handles the data received from the nfnetlink system. * For example, events generated by one of the subsystems. The message * is passed to the callback registered via callback_register(). Note that * this a replacement of nfnl_listen and its use is recommended. * * On success, 0 is returned. On error, a -1 is returned. If you do not * want to listen to events anymore, then your callback must return * NFNL_CB_STOP. * * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In * that case is possible that the information requested is incomplete. */ int nfnl_catch(struct nfnl_handle *h) { int ret; unsigned int size = NFNL_BUFFSIZE; assert(h); /* * Since nfqueue can send big packets, we don't know how big * must be the buffer that have to store the received data. */ { unsigned char buf[size]; struct sockaddr_nl peer; struct iovec iov = { .iov_len = size, }; struct msghdr msg = { .msg_name = (void *) &peer, .msg_namelen = sizeof(peer), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = NULL, .msg_controllen = 0, .msg_flags = 0 }; memset(&peer, 0, sizeof(peer)); peer.nl_family = AF_NETLINK; iov.iov_base = buf; iov.iov_len = size; retry: ret = recvmsg(h->fd, &msg, MSG_PEEK); if (ret == -1) { /* interrupted syscall must retry */ if (errno == EINTR) goto retry; /* otherwise give up */ return -1; } if (msg.msg_flags & MSG_TRUNC) /* maximum size of data received from netlink */ size = 65535; } /* now, receive data from netlink */ while (1) { unsigned char buf[size]; ret = nfnl_recv(h, buf, sizeof(buf)); if (ret == -1) { /* interrupted syscall must retry */ if (errno == EINTR) continue; break; } ret = nfnl_process(h, buf, ret); if (ret <= NFNL_CB_STOP) break; } return ret; } /** * nfnl_query - request/response communication challenge * @h: nfnetlink handler * @nlh: nfnetlink message to be sent * * This function sends a nfnetlink message to a certain subsystem and * receives the response messages associated, such messages are passed to * the callback registered via register_callback(). Note that this function * is a replacement for nfnl_talk, its use is recommended. * * On success, 0 is returned. On error, a negative is returned. If your * does not want to listen to events anymore, then your callback must * return NFNL_CB_STOP. * * Note that ENOBUFS is returned in case that nfnetlink is exhausted. In * that case is possible that the information requested is incomplete. */ int nfnl_query(struct nfnl_handle *h, struct nlmsghdr *nlh) { assert(h); assert(nlh); if (nfnl_send(h, nlh) == -1) return -1; return nfnl_catch(h); }