summaryrefslogtreecommitdiffstats
path: root/src/mnl.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2015-04-14 14:59:15 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2015-04-14 20:55:16 +0200
commitfd8a16b8517307514d1a9100c5dfd5098d1a52cb (patch)
treea4439d6360982688b0ddf75ea00a1d759825180e /src/mnl.c
parent3ed296118a065caff5600e60d4f7ef18e137f9a0 (diff)
mnl: use new libnftnl batch API
Each batch page has a size of 320 Kbytes, and the limit has been set to 256 KBytes, so the overrun area is 64 KBytes long to accomodate the largest netlink message (sets). Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/mnl.c')
-rw-r--r--src/mnl.c124
1 files changed, 33 insertions, 91 deletions
diff --git a/src/mnl.c b/src/mnl.c
index 89c2bb5e..76a97140 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -16,6 +16,7 @@
#include <libnftnl/rule.h>
#include <libnftnl/expr.h>
#include <libnftnl/set.h>
+#include <libnftnl/batch.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nf_tables.h>
@@ -126,77 +127,26 @@ static int check_genid(const struct nlmsghdr *nlh)
*/
#define BATCH_PAGE_SIZE getpagesize() * 32
-static struct mnl_nlmsg_batch *mnl_batch_alloc(void)
-{
- static char *buf;
-
- /* libmnl needs higher buffer to handle batch overflows. */
- buf = xmalloc(BATCH_PAGE_SIZE + NFT_NLMSG_MAXSIZE);
- return mnl_nlmsg_batch_start(buf, BATCH_PAGE_SIZE);
-}
-
-static LIST_HEAD(batch_page_list);
-static int batch_num_pages;
-
-struct batch_page {
- struct list_head head;
- struct mnl_nlmsg_batch *batch;
-};
+static struct nft_batch *batch;
void mnl_batch_init(void)
{
- struct batch_page *batch_page;
-
- batch_page = xmalloc(sizeof(struct batch_page));
- batch_page->batch = mnl_batch_alloc();
- batch_num_pages++;
- list_add_tail(&batch_page->head, &batch_page_list);
-}
-
-static struct batch_page *nft_batch_page_current(void)
-{
- return list_entry(batch_page_list.prev, struct batch_page, head);
-}
-
-static void *nft_nlmsg_batch_current(void)
-{
- return mnl_nlmsg_batch_current(nft_batch_page_current()->batch);
-}
-
-static void nft_batch_page_add(void)
-{
- struct nlmsghdr *last_nlh;
-
- /* Get the last message not fitting in the batch */
- last_nlh = nft_nlmsg_batch_current();
- /* Add new batch page */
- mnl_batch_init();
- /* Copy the last message not fitting to the new batch page */
- memcpy(nft_nlmsg_batch_current(), last_nlh, last_nlh->nlmsg_len);
- /* No overflow may happen as this is a new empty batch page */
- mnl_nlmsg_batch_next(nft_batch_page_current()->batch);
-}
-
-static void nft_batch_page_release(struct batch_page *batch_page)
-{
- list_del(&batch_page->head);
- xfree(mnl_nlmsg_batch_head(batch_page->batch));
- mnl_nlmsg_batch_stop(batch_page->batch);
- xfree(batch_page);
- batch_num_pages--;
+ batch = nft_batch_alloc(BATCH_PAGE_SIZE, NFT_NLMSG_MAXSIZE);
+ if (batch == NULL)
+ memory_allocation_error();
}
static void nft_batch_continue(void)
{
- if (!mnl_nlmsg_batch_next(nft_batch_page_current()->batch))
- nft_batch_page_add();
+ if (nft_batch_update(batch) < 0)
+ memory_allocation_error();
}
uint32_t mnl_batch_begin(void)
{
uint32_t seq = mnl_seqnum_alloc();
- nft_batch_begin(nft_nlmsg_batch_current(), seq);
+ nft_batch_begin(nft_batch_buffer(batch), seq);
nft_batch_continue();
return seq;
@@ -204,7 +154,7 @@ uint32_t mnl_batch_begin(void)
void mnl_batch_end(void)
{
- nft_batch_end(nft_nlmsg_batch_current(), mnl_seqnum_alloc());
+ nft_batch_end(nft_batch_buffer(batch), mnl_seqnum_alloc());
nft_batch_continue();
}
@@ -213,16 +163,13 @@ bool mnl_batch_ready(void)
/* Check if the batch only contains the initial and trailing batch
* messages. In that case, the batch is empty.
*/
- return mnl_nlmsg_batch_size(nft_batch_page_current()->batch) !=
- (NLMSG_HDRLEN+sizeof(struct nfgenmsg)) * 2;
+ return nft_batch_buffer_len(batch) !=
+ (NLMSG_HDRLEN + sizeof(struct nfgenmsg)) * 2;
}
void mnl_batch_reset(void)
{
- struct batch_page *batch_page, *next;
-
- list_for_each_entry_safe(batch_page, next, &batch_page_list, head)
- nft_batch_page_release(batch_page);
+ nft_batch_free(batch);
}
static void mnl_err_list_node_add(struct list_head *err_list, int error,
@@ -247,10 +194,10 @@ static void mnl_set_sndbuffer(const struct mnl_socket *nl)
{
int newbuffsiz;
- if (batch_num_pages * BATCH_PAGE_SIZE <= nlbuffsiz)
+ if (nft_batch_iovec_len(batch) * BATCH_PAGE_SIZE <= nlbuffsiz)
return;
- newbuffsiz = batch_num_pages * BATCH_PAGE_SIZE;
+ newbuffsiz = nft_batch_iovec_len(batch) * BATCH_PAGE_SIZE;
/* Rise sender buffer length to avoid hitting -EMSGSIZE */
if (setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_SNDBUFFORCE,
@@ -265,27 +212,26 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nl)
static const struct sockaddr_nl snl = {
.nl_family = AF_NETLINK
};
- struct iovec iov[batch_num_pages];
+ uint32_t iov_len = nft_batch_iovec_len(batch);
+ struct iovec iov[iov_len];
struct msghdr msg = {
.msg_name = (struct sockaddr *) &snl,
.msg_namelen = sizeof(snl),
.msg_iov = iov,
- .msg_iovlen = batch_num_pages,
+ .msg_iovlen = iov_len,
};
- struct batch_page *batch_page;
- int i = 0;
+#ifdef DEBUG
+ uint32_t i;
+#endif
mnl_set_sndbuffer(nl);
+ nft_batch_iovec(batch, iov, iov_len);
- list_for_each_entry(batch_page, &batch_page_list, head) {
- iov[i].iov_base = mnl_nlmsg_batch_head(batch_page->batch);
- iov[i].iov_len = mnl_nlmsg_batch_size(batch_page->batch);
- i++;
#ifdef DEBUG
+ for (i = 0; i < iov_len; i++) {
if (debug_level & DEBUG_MNL) {
mnl_nlmsg_fprintf(stdout,
- mnl_nlmsg_batch_head(batch_page->batch),
- mnl_nlmsg_batch_size(batch_page->batch),
+ iov[i].iov_base, iov[i].iov_len,
sizeof(struct nfgenmsg));
}
#endif
@@ -304,10 +250,6 @@ int mnl_batch_talk(struct mnl_socket *nl, struct list_head *err_list)
.tv_usec = 0
};
- /* Remove last page from the batch if it's empty */
- if (mnl_nlmsg_batch_is_empty(nft_batch_page_current()->batch))
- nft_batch_page_release(nft_batch_page_current());
-
ret = mnl_nft_socket_sendmsg(nl);
if (ret == -1)
return -1;
@@ -347,7 +289,7 @@ int mnl_nft_rule_batch_add(struct nft_rule *nlr, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_rule_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_rule_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_NEWRULE,
nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
NLM_F_CREATE | flags, seqnum);
@@ -363,7 +305,7 @@ int mnl_nft_rule_batch_del(struct nft_rule *nlr, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_rule_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_rule_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_DELRULE,
nft_rule_attr_get_u32(nlr, NFT_RULE_ATTR_FAMILY),
0, seqnum);
@@ -476,7 +418,7 @@ int mnl_nft_chain_batch_add(struct nft_chain *nlc, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_chain_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_chain_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_NEWCHAIN,
nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
NLM_F_CREATE | flags, seqnum);
@@ -505,7 +447,7 @@ int mnl_nft_chain_batch_del(struct nft_chain *nlc, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_chain_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_chain_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_DELCHAIN,
nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_FAMILY),
NLM_F_ACK, seqnum);
@@ -604,7 +546,7 @@ int mnl_nft_table_batch_add(struct nft_table *nlt, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_table_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_table_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_NEWTABLE,
nft_table_attr_get_u32(nlt, NFT_TABLE_ATTR_FAMILY),
flags, seqnum);
@@ -633,7 +575,7 @@ int mnl_nft_table_batch_del(struct nft_table *nlt, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_table_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_table_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_DELTABLE,
nft_table_attr_get_u32(nlt, NFT_TABLE_ATTR_FAMILY),
NLM_F_ACK, seqnum);
@@ -754,7 +696,7 @@ int mnl_nft_set_batch_add(struct nft_set *nls, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_set_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_set_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_NEWSET,
nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
NLM_F_CREATE | flags, seqnum);
@@ -769,7 +711,7 @@ int mnl_nft_set_batch_del(struct nft_set *nls, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_set_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_set_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_DELSET,
nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
flags, seqnum);
@@ -920,7 +862,7 @@ int mnl_nft_setelem_batch_add(struct nft_set *nls, unsigned int flags,
memory_allocation_error();
do {
- nlh = nft_set_elem_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_set_elem_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_NEWSETELEM,
nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
NLM_F_CREATE | flags, seqnum);
@@ -938,7 +880,7 @@ int mnl_nft_setelem_batch_del(struct nft_set *nls, unsigned int flags,
{
struct nlmsghdr *nlh;
- nlh = nft_set_elem_nlmsg_build_hdr(nft_nlmsg_batch_current(),
+ nlh = nft_set_elem_nlmsg_build_hdr(nft_batch_buffer(batch),
NFT_MSG_DELSETELEM,
nft_set_attr_get_u32(nls, NFT_SET_ATTR_FAMILY),
0, seqnum);