diff mbox series

[libnetfilter_queue,v3,01/15] src: Convert nfq_open() to use libmnl

Message ID 20241012230917.11467-2-duncan_roe@optusnet.com.au
State New
Headers show
Series Convert libnetfilter_queue to not need libnfnetlink | expand

Commit Message

Duncan Roe Oct. 12, 2024, 11:09 p.m. UTC
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(-)
diff mbox series

Patch

diff --git a/doxygen/doxygen.cfg.in b/doxygen/doxygen.cfg.in
index 97174ff..6dd7017 100644
--- a/doxygen/doxygen.cfg.in
+++ b/doxygen/doxygen.cfg.in
@@ -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'"
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index bf67a19..f366198 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -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;
 }