示例#1
0
/**
 * 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;
}
示例#2
0
/**
 * 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);
}