summaryrefslogtreecommitdiffstats
path: root/src/libnfnetlink.c
diff options
context:
space:
mode:
author/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2008-01-13 17:58:42 +0000
committer/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org>2008-01-13 17:58:42 +0000
commit800c6646e0f748bad3c52ac7f20e38a1583d8bdb (patch)
tree504e1fca37fa0a73c8da98321a33e82eae5e29e4 /src/libnfnetlink.c
parent318961c76bf2d7c5ab715d8fee4aa005bdcde5e0 (diff)
Introduce nfnl_set_rcv_buffer_size to set the receive buffer size used by
nfnl_catch. This revision changes the behaviour of nfnl_catch which does not perform a peek-and-resize if the buffer size used by nfnl_recv is too small. The only known client which may be affected by this change is libnetfilter_conntrack. However, this library uses nfnl_catch to get conntrack events which are always much smaller than 4096 bytes (default receive buffer size). This change boosts up performance in the receive path since we do only one recv instead of two.
Diffstat (limited to 'src/libnfnetlink.c')
-rw-r--r--src/libnfnetlink.c58
1 files changed, 16 insertions, 42 deletions
diff --git a/src/libnfnetlink.c b/src/libnfnetlink.c
index 4b2a3b3..f9ab87f 100644
--- a/src/libnfnetlink.c
+++ b/src/libnfnetlink.c
@@ -85,6 +85,7 @@ struct nfnl_handle {
u_int32_t subscriptions;
u_int32_t seq;
u_int32_t dump;
+ u_int32_t rcv_buffer_size; /* for nfnl_catch */
struct nlmsghdr *last_nlhdr;
struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1];
};
@@ -184,6 +185,7 @@ struct nfnl_handle *nfnl_open(void)
goto err_close;
}
nfnlh->seq = time(NULL);
+ nfnlh->rcv_buffer_size = NFNL_BUFFSIZE;
/* don't set pid here, only first socket of process has real pid !!!
* binding to pid '0' will default */
@@ -211,6 +213,19 @@ err_free:
}
/**
+ * nfnl_set_rcv_buffer_size - set the size of the receive buffer
+ * @h: libnfnetlink handler
+ * @size: buffer size
+ *
+ * This function sets the size of the receive buffer size, i.e. the size
+ * of the buffer used by nfnl_recv. Default value is 4096 bytes.
+ */
+void nfnl_set_rcv_buffer_size(struct nfnl_handle *h, unsigned int size)
+{
+ h->rcv_buffer_size = size;
+}
+
+/**
* nfnl_subsys_open - open a netlink subsystem
* @nfnlh: libnfnetlink handle
* @subsys_id: which nfnetlink subsystem we are interested in
@@ -1455,52 +1470,11 @@ int nfnl_iterator_next(const struct nfnl_handle *h, struct nfnl_iterator *it)
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];
+ unsigned char buf[h->rcv_buffer_size];
ret = nfnl_recv(h, buf, sizeof(buf));
if (ret == -1) {