@@ -13,6 +13,9 @@ EXCLUDE_SYMBOLS = EXPORT_SYMBOL \
nfq_handle \
nfq_data \
nfq_q_handle \
+ nfnl_handle \
+ nfnl_subsys_handle \
+ mnl_socket \
tcp_flag_word
EXAMPLE_PATTERNS =
INPUT_FILTER = "sed 's/EXPORT_SYMBOL//g'"
@@ -31,6 +31,7 @@
#include <sys/socket.h>
#include <linux/netfilter/nfnetlink_queue.h>
+#include <libmnl/libmnl.h>
#include <libnfnetlink/libnfnetlink.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include "internal.h"
@@ -134,11 +135,43 @@ gcc -g3 -ggdb -Wall -lmnl -lnetfilter_queue -o nf-queue nf-queue.c
* burst
*/
+/* Copy of private libnfnetlink structures */
+
+#define NFNL_MAX_SUBSYS 16
+
+struct nfnl_subsys_handle {
+ struct nfnl_handle *nfnlh;
+ uint32_t subscriptions;
+ uint8_t subsys_id;
+ uint8_t cb_count;
+ struct nfnl_callback *cb; /* array of callbacks */
+};
+
+struct nfnl_handle {
+ int fd;
+ struct sockaddr_nl local;
+ struct sockaddr_nl peer;
+ uint32_t subscriptions;
+ uint32_t seq;
+ uint32_t dump;
+ uint32_t rcv_buffer_size; /* for nfnl_catch */
+ uint32_t flags;
+ struct nlmsghdr *last_nlhdr;
+ struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1];
+};
+
+/* Copy of private libmnl structure */
+struct mnl_socket {
+ int fd;
+ struct sockaddr_nl addr;
+};
+
struct nfq_handle
{
struct nfnl_handle *nfnlh;
struct nfnl_subsys_handle *nfnlssh;
struct nfq_q_handle *qh_list;
+ struct mnl_socket *nl;
};
struct nfq_q_handle
@@ -157,6 +190,9 @@ struct nfq_data {
EXPORT_SYMBOL int nfq_errno;
+static struct nfq_handle *__nfq_open_nfnl(struct nfnl_handle *nfnlh,
+ struct nfq_handle *qh);
+
/***********************************************************************
* low level stuff
***********************************************************************/
@@ -383,20 +419,41 @@ int nfq_fd(struct nfq_handle *h)
EXPORT_SYMBOL
struct nfq_handle *nfq_open(void)
{
- struct nfnl_handle *nfnlh = nfnl_open();
struct nfq_handle *qh;
+ struct nfq_handle *h;
- if (!nfnlh)
- return NULL;
-
- /* unset netlink sequence tracking by default */
- nfnl_unset_sequence_tracking(nfnlh);
-
- qh = nfq_open_nfnl(nfnlh);
+ qh = calloc(1, sizeof(*qh));
if (!qh)
- nfnl_close(nfnlh);
+ return NULL;
+ qh->nl = mnl_socket_open(NETLINK_NETFILTER);
+ if (!qh->nl)
+ goto err_free;
+
+ if (mnl_socket_bind(qh->nl, 0, MNL_SOCKET_AUTOPID) < 0)
+ goto err_close;
+
+ /* Manufacture an nfnl handle */
+ qh->nfnlh = calloc(1, sizeof(*qh->nfnlh));
+ if (!qh->nfnlh)
+ goto err_close;
+ qh->nfnlh->fd = qh->nl->fd;
+ qh->nfnlh->local = qh->nl->addr;
+ qh->nfnlh->peer.nl_family = AF_NETLINK;
+ qh->nfnlh->rcv_buffer_size = MNL_SOCKET_BUFFER_SIZE;
+
+ h = __nfq_open_nfnl(qh->nfnlh, qh); /* Will return qh or NULL */
+ if (!h)
+ goto err_free2;
return qh;
+
+err_free2:
+ free(qh->nfnlh);
+err_close:
+ mnl_socket_close(qh->nl);
+err_free:
+ free(qh);
+ return NULL;
}
/**
@@ -415,6 +472,11 @@ struct nfq_handle *nfq_open(void)
*/
EXPORT_SYMBOL
struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
+{
+ return __nfq_open_nfnl(nfnlh, NULL);
+}
+static struct nfq_handle *__nfq_open_nfnl(struct nfnl_handle *nfnlh,
+ struct nfq_handle *qh)
{
struct nfnl_callback pkt_cb = {
.call = __nfq_rcv_pkt,
@@ -423,11 +485,10 @@ struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
struct nfq_handle *h;
int err;
- h = malloc(sizeof(*h));
+ h = qh ? qh : calloc(1, sizeof(*h));
if (!h)
return NULL;
- memset(h, 0, sizeof(*h));
h->nfnlh = nfnlh;
h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE,
@@ -448,7 +509,8 @@ struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
out_close:
nfnl_subsys_close(h->nfnlssh);
out_free:
- free(h);
+ if (!qh)
+ free(h);
return NULL;
}
Add copies of nfnl_handle, nfnl_subsys_handle & mnl_socket to libnetfilter_queue.c. After calling mnl_socket_open() & mnl_socket_bind(), fill in the libnfnetlink structs as if nfnl_open() had been called. Call a static extended version of nfq_open_nfnl(), __nfq_open_nfnl() which can tell how it was called via an extra argument: struct nfq_handle *qh. nfq_open() passes the qh returned by mnl_open(). nfq_open_nfnl() passes NULL. __nfq_open_nfnl() creates and returns a qh if it wasn't given one. Otherwise it returns the qh it was given or NULL on error (but the passed-in qh is not freed). Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au> --- Changes in v3: (none) Changes in v2: - Rather than inline nfnl subsys code, minimally modify nfq_open_nfnl() as per updated commit message - Replace NFNL_BUFFSIZE with MNL_SOCKET_BUFFER_SIZE - Use calloc instead of malloc + memset in new code - Don't rename struct nfq_handle *qh to *h - Fix checkpatch space before tab warnings in lines 143,147,159,165 - Keep nfq_errno doxygen/doxygen.cfg.in | 3 ++ src/libnetfilter_queue.c | 86 ++++++++++++++++++++++++++++++++++------ 2 files changed, 77 insertions(+), 12 deletions(-)