/**
 * nflog_set_flags - set the nflog flags for this group
 * \param gh Netfilter log handle obtained by call to nflog_bind_group().
 * \param flags Flags that you want to set
 *
 * There are two existing flags:
 *
 *	- NFULNL_CFG_F_SEQ: This enables local nflog sequence numbering.
 *	- NFULNL_CFG_F_SEQ_GLOBAL: This enables global nflog sequence numbering.
 *
 * \return -1 in case of error and errno is explicity set.
 */
int nflog_set_flags(struct nflog_g_handle *gh, uint16_t flags)
{
	union {
		char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(uint16_t))];
		struct nlmsghdr nmh;
	} u;

	nfnl_fill_hdr(gh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, gh->id,
		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);

	nfnl_addattr16(&u.nmh, sizeof(u), NFULA_CFG_FLAGS, htons(flags));

	return nfnl_query(gh->h->nfnlh, &u.nmh);
}
/**
 * nflog_set_qthresh - set the maximum amount of logs in buffer for this group
 * \param gh Netfilter log handle obtained by call to nflog_bind_group().
 * \param qthresh Maximum number of log entries
 *
 * This function determines the maximum number of log entries in the buffer
 * until it is pushed to userspace.
 *
 * \return -1 in case of error and errno is explicity set.
 */
int nflog_set_qthresh(struct nflog_g_handle *gh, uint32_t qthresh)
{
	union {
		char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(uint32_t))];
		struct nlmsghdr nmh;
	} u;

	nfnl_fill_hdr(gh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, gh->id,
		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);

	nfnl_addattr32(&u.nmh, sizeof(u), NFULA_CFG_QTHRESH, htonl(qthresh));

	return nfnl_query(gh->h->nfnlh, &u.nmh);
}
/**
 * nfexp_query - send a query to ctnetlink
 * \param h library handler
 * \param qt query type
 * \param data data required to send the query
 *
 * On error, -1 is returned and errno is explicitely set. On success, 0
 * is returned.
 */
int nfexp_query(struct nfct_handle *h,
	        const enum nf_conntrack_query qt,
	        const void *data)
{
	const size_t size = 4096;	/* enough for now */
	union {
		char buffer[size];
		struct nfnlhdr req;
	} u;

	assert(h != NULL);
	assert(data != NULL);

	if (__build_query_exp(h->nfnlssh_exp, qt, data, &u.req, size) == -1)
		return -1;

	return nfnl_query(h->nfnlh, &u.req.nlh);
}
/* build a NFULNL_MSG_CONFIG message */
static int
__build_send_cfg_msg(struct nflog_handle *h, uint8_t command,
		     uint16_t groupnum, uint8_t pf)
{
	union {
		char buf[NFNL_HEADER_LEN
			+NFA_LENGTH(sizeof(struct nfulnl_msg_config_cmd))];
		struct nlmsghdr nmh;
	} u;
	struct nfulnl_msg_config_cmd cmd;

	nfnl_fill_hdr(h->nfnlssh, &u.nmh, 0, pf, groupnum,
		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);

	cmd.command = command;
	nfnl_addattr_l(&u.nmh, sizeof(u), NFULA_CFG_CMD, &cmd, sizeof(cmd));

	return nfnl_query(h->nfnlh, &u.nmh);
}
/**
 * nflog_set_mode - set the amount of packet data that nflog copies to userspace
 * \param qh Netfilter log handle obtained by call to nflog_bind_group().
 * \param mode the part of the packet that we are interested in
 * \param range size of the packet that we want to get
 *
 * Sets the amount of data to be copied to userspace for each packet logged
 * to the given group.
 *
 * - NFULNL_COPY_NONE - do not copy any data
 * - NFULNL_COPY_META - copy only packet metadata
 * - NFULNL_COPY_PACKET - copy entire packet
 *
 * \return -1 on error; >= otherwise.
 */
int nflog_set_mode(struct nflog_g_handle *gh,
		   uint8_t mode, uint32_t range)
{
	union {
		char buf[NFNL_HEADER_LEN
			+NFA_LENGTH(sizeof(struct nfulnl_msg_config_mode))];
		struct nlmsghdr nmh;
	} u;
	struct nfulnl_msg_config_mode params;

	nfnl_fill_hdr(gh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, gh->id,
		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);

	params.copy_range = htonl(range);	/* copy_range is short */
	params.copy_mode = mode;
	nfnl_addattr_l(&u.nmh, sizeof(u), NFULA_CFG_MODE, &params,
		       sizeof(params));

	return nfnl_query(gh->h->nfnlh, &u.nmh);
}
/**
 * nflog_set_nlbufsiz - set the size of the nflog buffer for this group
 * \param gh Netfilter log handle obtained by call to nflog_bind_group().
 * \param nlbufsiz Size of the nflog buffer
 *
 * This function sets the size (in bytes) of the buffer that is used to
 * stack log messages in nflog.
 *
 * NOTE: The use of this function is strongly discouraged. The default
 * buffer size (which is one memory page) provides the optimum results
 * in terms of performance. Do not use this function in your applications.
 *
 * \return -1 in case of error and errno is explicity set.
 */
int nflog_set_nlbufsiz(struct nflog_g_handle *gh, uint32_t nlbufsiz)
{
	union {
		char buf[NFNL_HEADER_LEN+NFA_LENGTH(sizeof(uint32_t))];
		struct nlmsghdr nmh;
	} u;
	int status;

	nfnl_fill_hdr(gh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, gh->id,
		      NFULNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);

	nfnl_addattr32(&u.nmh, sizeof(u), NFULA_CFG_NLBUFSIZ, htonl(nlbufsiz));

	status = nfnl_query(gh->h->nfnlh, &u.nmh);

	/* we try to have space for at least 10 messages in the socket buffer */
	if (status >= 0)
		nfnl_rcvbufsiz(gh->h->nfnlh, 10*nlbufsiz);

	return status;
}