diff mbox series

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

Message ID 20240315073347.22628-2-duncan_roe@optusnet.com.au
State New
Headers show
Series [libnetfilter_queue,01/32] src: Convert nfq_open() to use libmnl | expand

Commit Message

Duncan Roe March 15, 2024, 7:33 a.m. UTC
Add copies of nfnl_handle, nfnl_subsys_handle & mnl_socket to
libnetfilter_queue.c. After calling mnl_socket_open() & mnl_socket_bind(),
it fills in the libnfnetlink structs as if nfnl_open() had been called.
The rest of the system still uses libnfnetlink functions but they keep
working.
Where possible, code is copied exactly from libnfnetlink. checkpatch
warns about space before tabs but these warnings are addressed in a
later commit.

Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
 doxygen/doxygen.cfg.in   |  3 ++
 src/libnetfilter_queue.c | 88 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 82 insertions(+), 9 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..2aba68d 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
@@ -383,20 +416,57 @@  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 nfnl_callback pkt_cb = {
+		.call		= __nfq_rcv_pkt,
+		.attr_count	= NFQA_MAX,
+	};
+	struct nfq_handle *h = malloc(sizeof(*h));
 
-	if (!nfnlh)
+	if (!h)
 		return NULL;
+	memset(h, 0, sizeof(*h));
 
-	/* unset netlink sequence tracking by default */
-	nfnl_unset_sequence_tracking(nfnlh);
+	h->nfnlh = malloc(sizeof(*h->nfnlh));
+	if (!h->nfnlh)
+		goto err_free;
+	memset(h->nfnlh, 0, sizeof(*h->nfnlh));
+
+	h->nl = mnl_socket_open(NETLINK_NETFILTER);
+	if (!h->nl)
+		goto err_free2;
+
+	if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0)
+		goto err_close;
+
+	/* Fill in nfnl handle */
+	h->nfnlh->fd = h->nl->fd;
+	h->nfnlh->local = h->nl->addr;
+	h->nfnlh->peer.nl_family = AF_NETLINK;
+	//h->nfnlh->seq = time(NULL);
+	h->nfnlh->rcv_buffer_size = NFNL_BUFFSIZE;
+
+	/* Fill in nfnl subsys handle with code adapted from libnfnetlink */
+	h->nfnlssh = &h->nfnlh->subsys[NFNL_SUBSYS_QUEUE];
+	h->nfnlssh->cb = calloc(NFQNL_MSG_MAX, sizeof(*(h->nfnlssh->cb)));
+	if (!h->nfnlssh->cb)
+		goto err_close;
+
+	h->nfnlssh->nfnlh = h->nfnlh;
+	h->nfnlssh->cb_count = NFQNL_MSG_MAX;
+	h->nfnlssh->subscriptions = 0;
+	h->nfnlssh->subsys_id = NFNL_SUBSYS_QUEUE;
+	pkt_cb.data = h;
+	memcpy(&h->nfnlssh->cb[NFQNL_MSG_PACKET], &pkt_cb, sizeof(pkt_cb));
 
-	qh = nfq_open_nfnl(nfnlh);
-	if (!qh)
-		nfnl_close(nfnlh);
+	return h;
 
-	return qh;
+err_close:
+	mnl_socket_close(h->nl);
+err_free2:
+	free(h->nfnlh);
+err_free:
+	free(h);
+	return NULL;
 }
 
 /**