* [PATCH libnetfilter_queue v2 01/15] src: Convert nfq_open() to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 02/15] src: Convert nfq_open_nfnl() " Duncan Roe
` (13 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
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 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 --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;
}
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 02/15] src: Convert nfq_open_nfnl() to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 01/15] src: Convert nfq_open() to use libmnl Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 03/15] src: Convert nfq_close() " Duncan Roe
` (12 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
__nfq_open_nfnl() manufactures a libmnl handle if called by
nfq_open_nfnl().
Replace calls to nfnl_subsys_open() and nfnl_callback_register() with
inline code.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- Pretty much re-written as per updated commit message. In particular:
- Don't clear message sequencing - original didn't do that.
- Don't close the socket in any error path since it was open on entry.
src/libnetfilter_queue.c | 56 ++++++++++++++++++++++++++++++++--------
1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index f366198..bfb6482 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -484,33 +484,67 @@ static struct nfq_handle *__nfq_open_nfnl(struct nfnl_handle *nfnlh,
};
struct nfq_handle *h;
int err;
+ int i;
+ uint32_t new_subscriptions;
h = qh ? qh : calloc(1, sizeof(*h));
if (!h)
return NULL;
+ if (!qh) {
+ /* Manufacture the libmnl handle */
+ h->nl = calloc(1, sizeof(*h->nl));
+ if (!h->nl)
+ goto out_free;
+ h->nl->fd = nfnlh->fd;
+ h->nl->addr = nfnlh->local;
+ }
h->nfnlh = nfnlh;
- h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE,
- NFQNL_MSG_MAX, 0);
- if (!h->nfnlssh) {
+ /* Replace nfnl_subsys_open() with code adapted from libnfnetlink */
+ h->nfnlssh = &h->nfnlh->subsys[NFNL_SUBSYS_QUEUE];
+ if (h->nfnlssh->cb) {
+ errno = EBUSY;
+ goto out_free;
+ }
+ h->nfnlssh->cb = calloc(NFQNL_MSG_MAX, sizeof(*(h->nfnlssh->cb)));
+ if (!h->nfnlssh->cb) {
/* FIXME: nfq_errno */
goto out_free;
}
+ h->nfnlssh->nfnlh = h->nfnlh;
+ h->nfnlssh->cb_count = NFQNL_MSG_MAX;
+ h->nfnlssh->subsys_id = NFNL_SUBSYS_QUEUE;
+
+ /* Replacement code for recalc_rebind_subscriptions() */
+ new_subscriptions = nfnlh->subscriptions;
+ for (i = 0; i < NFNL_MAX_SUBSYS; i++)
+ new_subscriptions |= nfnlh->subsys[i].subscriptions;
+ nfnlh->local.nl_groups = new_subscriptions;
+ err = bind(nfnlh->fd, (struct sockaddr *)&nfnlh->local,
+ sizeof(nfnlh->local));
+ if (err == -1) {
+ free(h->nfnlssh->cb);
+ h->nfnlssh->cb = NULL;
+ goto out_free;
+ }
+ h->nfnlssh->subscriptions = new_subscriptions;
pkt_cb.data = h;
- err = nfnl_callback_register(h->nfnlssh, NFQNL_MSG_PACKET, &pkt_cb);
- if (err < 0) {
- nfq_errno = err;
- goto out_close;
- }
+ /* Replacement code for nfnl_callback_register()
+ * The only error return from nfnl_callback_register() is not possible
+ * here: NFQNL_MSG_PACKET (= 0) will be less than h->nfnlssh->cb_count
+ * (set to NFQNL_MSG_MAX (= 4) a few lines back).
+ */
+ memcpy(&h->nfnlssh->cb[NFQNL_MSG_PACKET], &pkt_cb, sizeof(pkt_cb));
return h;
-out_close:
- nfnl_subsys_close(h->nfnlssh);
out_free:
- if (!qh)
+ if (!qh) {
+ if (h->nl)
+ free(h->nl);
free(h);
+ }
return NULL;
}
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 03/15] src: Convert nfq_close() to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 01/15] src: Convert nfq_open() to use libmnl Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 02/15] src: Convert nfq_open_nfnl() " Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 04/15] src: Convert nfq_create_queue(), nfq_bind_pf() & nfq_unbind_pf() " Duncan Roe
` (11 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
Use mnl_close() and clean up the NFNL_SUBSYS_QUEUE subsystem as
nfnl_close() would have done
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- Propogate return from mnl_socket_close()
- Don't free callbacks in the qh_list since nfq_close() didn't
(reported as a bug)
- Do a complete emulation of nfnl_close()
- Add explanatory comments
src/libnetfilter_queue.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index bfb6482..0483780 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -577,8 +577,30 @@ EXPORT_SYMBOL
int nfq_close(struct nfq_handle *h)
{
int ret;
+ int i;
+
+ ret = mnl_socket_close(h->nl);
+ h->nl = NULL; /* mnl_socket_close() always frees it */
+
+ /* Replacement code for nfnl_close().
+ * It seems unlikely that we need to go through all 16 subsystems
+ * instead of only subsys[NFNL_SUBSYS_QUEUE] which h->nfnlssh
+ * conveniently points to, but better safe than sorry.
+ */
+ for (i = 0; i < NFNL_MAX_SUBSYS; i++) {
+ h->nfnlh->subsys[i].subscriptions = 0;
+ h->nfnlh->subsys[i].cb_count = 0;
+ if (h->nfnlh->subsys[i].cb) {
+ free(h->nfnlh->subsys[i].cb);
+ h->nfnlh->subsys[i].cb = NULL;
+ }
+ }
+ if (ret == 0)
+ free(h->nfnlh);
- ret = nfnl_close(h->nfnlh);
+ /* nfnl_close() didn't free nfnlh if close() returned an error.
+ * Presumably that's why nfq_close() doesn't free h in that case.
+ */
if (ret == 0)
free(h);
return ret;
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 04/15] src: Convert nfq_create_queue(), nfq_bind_pf() & nfq_unbind_pf() to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (2 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 03/15] src: Convert nfq_close() " Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 05/15] src: Convert nfq_set_queue_flags(), nfq_set_queue_maxlen() & nfq_set_mode() " Duncan Roe
` (10 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
Convert static function __build_send_cfg_msg() to use libmnl.
This by itself converts the 3 public functions.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- Rename nfq_query to __nfq_query so as not to pollute Posix namespace
- rebase to account for updated patches 1 - 3
src/libnetfilter_queue.c | 32 +++++++++++++++++++-------------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index 0483780..b64f14a 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -230,27 +230,33 @@ static struct nfq_q_handle *find_qh(struct nfq_handle *h, uint16_t id)
return NULL;
}
+static int __nfq_query(struct nfq_handle *h, struct nlmsghdr *nlh, char *buf,
+ size_t bufsiz)
+{
+ int ret;
+
+ ret = mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len);
+ if (ret != -1)
+ ret = mnl_socket_recvfrom(h->nl, buf, bufsiz);
+ if (ret != -1)
+ ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(h->nl),
+ NULL, NULL);
+ return ret;
+}
+
/* build a NFQNL_MSG_CONFIG message */
static int
__build_send_cfg_msg(struct nfq_handle *h, uint8_t command,
uint16_t queuenum, uint16_t pf)
{
- union {
- char buf[NFNL_HEADER_LEN
- +NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
- struct nlmsghdr nmh;
- } u;
- struct nfqnl_msg_config_cmd cmd;
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
- nfnl_fill_hdr(h->nfnlssh, &u.nmh, 0, AF_UNSPEC, queuenum,
- NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+ nlh = nfq_nlmsg_put2(buf, NFQNL_MSG_CONFIG, queuenum, NLM_F_ACK);
- cmd._pad = 0;
- cmd.command = command;
- cmd.pf = htons(pf);
- nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_CMD, &cmd, sizeof(cmd));
+ nfq_nlmsg_cfg_put_cmd(nlh, AF_UNSPEC, command);
- return nfnl_query(h->nfnlh, &u.nmh);
+ return __nfq_query(h, nlh, buf, sizeof(buf));
}
static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 05/15] src: Convert nfq_set_queue_flags(), nfq_set_queue_maxlen() & nfq_set_mode() to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (3 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 04/15] src: Convert nfq_create_queue(), nfq_bind_pf() & nfq_unbind_pf() " Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 06/15] src: Convert nfq_handle_packet(), nfq_get_secctx(), nfq_get_payload() and all the nfq_get_ functions " Duncan Roe
` (9 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
Use a buffer of MNL_SOCKET_BUFFER_SIZE; no union required.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- Rename nfq_query to __nfq_query so as not to pollute Posix namespace
- Also convert nfq_set_mode() here because of using the same strategy
- rebase to account for updated patches 1 - 3
src/libnetfilter_queue.c | 58 ++++++++++++++++------------------------
1 file changed, 23 insertions(+), 35 deletions(-)
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index b64f14a..0ef3bd3 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -782,22 +782,21 @@ int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
EXPORT_SYMBOL
int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range)
{
- union {
- char buf[NFNL_HEADER_LEN
- +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
- struct nlmsghdr nmh;
- } u;
- struct nfqnl_msg_config_params params;
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
+ int ret;
- nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
- NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+ nlh = nfq_nlmsg_put2(buf, NFQNL_MSG_CONFIG, qh->id, NLM_F_ACK);
- params.copy_range = htonl(range);
- params.copy_mode = mode;
- nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_PARAMS, ¶ms,
- sizeof(params));
+ nfq_nlmsg_cfg_put_params(nlh, mode, range);
- return nfnl_query(qh->h->nfnlh, &u.nmh);
+ ret = mnl_socket_sendto(qh->h->nl, nlh, nlh->nlmsg_len);
+ if (ret != -1)
+ ret = mnl_socket_recvfrom(qh->h->nl, buf, sizeof(buf));
+ if (ret != -1)
+ ret = mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(qh->h->nl),
+ NULL, NULL);
+ return ret;
}
/**
@@ -871,23 +870,18 @@ int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range)
EXPORT_SYMBOL
int nfq_set_queue_flags(struct nfq_q_handle *qh, uint32_t mask, uint32_t flags)
{
- union {
- char buf[NFNL_HEADER_LEN
- +NFA_LENGTH(sizeof(mask)
- +NFA_LENGTH(sizeof(flags)))];
- struct nlmsghdr nmh;
- } u;
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
mask = htonl(mask);
flags = htonl(flags);
- nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
- NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+ nlh = nfq_nlmsg_put2(buf, NFQNL_MSG_CONFIG, qh->id, NLM_F_ACK);
- nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_FLAGS, flags);
- nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_MASK, mask);
+ mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, flags);
+ mnl_attr_put_u32(nlh, NFQA_CFG_MASK, mask);
- return nfnl_query(qh->h->nfnlh, &u.nmh);
+ return __nfq_query(qh->h, nlh, buf, sizeof(buf));
}
/**
@@ -904,20 +898,14 @@ int nfq_set_queue_flags(struct nfq_q_handle *qh, uint32_t mask, uint32_t flags)
EXPORT_SYMBOL
int nfq_set_queue_maxlen(struct nfq_q_handle *qh, uint32_t queuelen)
{
- union {
- char buf[NFNL_HEADER_LEN
- +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
- struct nlmsghdr nmh;
- } u;
- uint32_t queue_maxlen = htonl(queuelen);
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
- nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
- NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
+ nlh = nfq_nlmsg_put2(buf, NFQNL_MSG_CONFIG, qh->id, NLM_F_ACK);
- nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_QUEUE_MAXLEN, &queue_maxlen,
- sizeof(queue_maxlen));
+ mnl_attr_put_u32(nlh, NFQA_CFG_QUEUE_MAXLEN, htonl(queuelen));
- return nfnl_query(qh->h->nfnlh, &u.nmh);
+ return __nfq_query(qh->h, nlh, buf, sizeof(buf));
}
/**
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 06/15] src: Convert nfq_handle_packet(), nfq_get_secctx(), nfq_get_payload() and all the nfq_get_ functions to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (4 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 05/15] src: Convert nfq_set_queue_flags(), nfq_set_queue_maxlen() & nfq_set_mode() " Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 07/15] src: Convert nfq_set_verdict() and nfq_set_verdict2() to use libmnl if there is no data Duncan Roe
` (8 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
The opaque struct nfq_data is now an array of struct nlattr instead of
struct nfattr.
Because of using mnl_attr_parse(), the first array element is for
attribute 0 instead of attribute 1 as previously. Because of this,
all the nfq_get_ functions have to be converted for this commit.
Functions now using libmnl exclusively: nfq_get_msg_packet_hdr(),
nfq_get_nfmark(), nfq_get_timestamp(), nfq_get_indev(),
nfq_get_physindev(), nfq_get_outdev(), nfq_get_physoutdev(),
nfqnl_msg_packet_hw(), nfq_get_uid() & nfq_get_gid().
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- Fix spelling error in commit message
- Fix checkpatch warning re space before __nfq_handle_msg declaration
- rebase to account for updated patches
doxygen/doxygen.cfg.in | 1 +
src/libnetfilter_queue.c | 124 ++++++++++++++++++++++++++++-----------
2 files changed, 92 insertions(+), 33 deletions(-)
diff --git a/doxygen/doxygen.cfg.in b/doxygen/doxygen.cfg.in
index 6dd7017..fcfc045 100644
--- a/doxygen/doxygen.cfg.in
+++ b/doxygen/doxygen.cfg.in
@@ -16,6 +16,7 @@ EXCLUDE_SYMBOLS = EXPORT_SYMBOL \
nfnl_handle \
nfnl_subsys_handle \
mnl_socket \
+ nfnl_callback2 \
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 0ef3bd3..6500fec 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -32,6 +32,13 @@
#include <linux/netfilter/nfnetlink_queue.h>
#include <libmnl/libmnl.h>
+
+/* Use the real header since libnfnetlink is going away. */
+/* nfq_pkt_parse_attr_cb only knows attribates up to NFQA_SECCTX */
+/* so won't try to validate higher-numbered attrs but will store them. */
+/* mnl API programs will then be able to access them. */
+#include <linux/netfilter/nfnetlink.h>
+
#include <libnfnetlink/libnfnetlink.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include "internal.h"
@@ -144,7 +151,7 @@ struct nfnl_subsys_handle {
uint32_t subscriptions;
uint8_t subsys_id;
uint8_t cb_count;
- struct nfnl_callback *cb; /* array of callbacks */
+ struct nfnl_callback2 *cb; /* array of callbacks with struct nlattr* */
};
struct nfnl_handle {
@@ -166,6 +173,13 @@ struct mnl_socket {
struct sockaddr_nl addr;
};
+/* Amended callback prototype */
+struct nfnl_callback2 {
+ int (*call)(struct nlmsghdr *nlh, struct nlattr *nfa[], void *data);
+ void *data;
+ uint16_t attr_count;
+};
+
struct nfq_handle
{
struct nfnl_handle *nfnlh;
@@ -185,7 +199,7 @@ struct nfq_q_handle
};
struct nfq_data {
- struct nfattr **data;
+ struct nlattr **data;
};
EXPORT_SYMBOL int nfq_errno;
@@ -259,7 +273,7 @@ __build_send_cfg_msg(struct nfq_handle *h, uint8_t command,
return __nfq_query(h, nlh, buf, sizeof(buf));
}
-static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
+static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nlattr *nfa[],
void *data)
{
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
@@ -484,7 +498,7 @@ struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
static struct nfq_handle *__nfq_open_nfnl(struct nfnl_handle *nfnlh,
struct nfq_handle *qh)
{
- struct nfnl_callback pkt_cb = {
+ struct nfnl_callback2 pkt_cb = {
.call = __nfq_rcv_pkt,
.attr_count = NFQA_MAX,
};
@@ -650,6 +664,25 @@ int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf)
* @}
*/
+static int __nfq_handle_msg(const struct nlmsghdr *nlh, void *data)
+{
+ struct nfq_handle *h = data;
+ struct nfq_q_handle *qh;
+ struct nlattr *nfa[NFQA_MAX + 1] = {};
+ struct nfq_data nfad = {nfa};
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+
+ if (nfq_nlmsg_parse(nlh, nfa) < 0)
+ return MNL_CB_ERROR;
+
+ /* Find our queue handler (to get CB fn) */
+ qh = find_qh(h, ntohs(nfmsg->res_id));
+ if (!qh)
+ return MNL_CB_ERROR;
+
+ return qh->cb(qh, nfmsg, &nfad, qh->data);
+}
+
/**
* \addtogroup Queue
* @{
@@ -761,7 +794,8 @@ int nfq_destroy_queue(struct nfq_q_handle *qh)
EXPORT_SYMBOL
int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
{
- return nfnl_handle_packet(h->nfnlh, buf, len);
+ return mnl_cb_run(buf, len, 0, mnl_socket_get_portid(h->nl),
+ __nfq_handle_msg, h);
}
/**
@@ -930,7 +964,7 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
/* This must be declared here (and not inside the data
* handling block) because the iovec points to this. */
- struct nfattr data_attr;
+ struct nlattr data_attr;
memset(iov, 0, sizeof(iov));
@@ -951,15 +985,17 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
nvecs = 1;
if (data_len) {
- /* The typecast here is to cast away data's const-ness: */
- nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
- data_len, (unsigned char *) data);
+ /* Temporary cast until we get rid of nfnl_build_nfa_iovec() */
+ nfnl_build_nfa_iovec(&iov[1], (struct nfattr *)&data_attr,
+ //nfnl_build_nfa_iovec(&iov[1], &data_attr,
+ NFQA_PAYLOAD, data_len,
+ (unsigned char *) data);
nvecs += 2;
/* Add the length of the appended data to the message
* header. The size of the attribute is given in the
- * nfa_len field and is set in the nfnl_build_nfa_iovec()
+ * nla_len field and is set in the nfnl_build_nfa_iovec()
* function. */
- u.nmh.nlmsg_len += data_attr.nfa_len;
+ u.nmh.nlmsg_len += data_attr.nla_len;
}
return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0);
@@ -1123,8 +1159,10 @@ int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id,
EXPORT_SYMBOL
struct nfqnl_msg_packet_hdr *nfq_get_msg_packet_hdr(struct nfq_data *nfad)
{
- return nfnl_get_pointer_to_data(nfad->data, NFQA_PACKET_HDR,
- struct nfqnl_msg_packet_hdr);
+ if (!nfad->data[NFQA_PACKET_HDR])
+ return NULL;
+
+ return mnl_attr_get_payload(nfad->data[NFQA_PACKET_HDR]);
}
/**
@@ -1136,6 +1174,10 @@ struct nfqnl_msg_packet_hdr *nfq_get_msg_packet_hdr(struct nfq_data *nfad)
EXPORT_SYMBOL
uint32_t nfq_get_nfmark(struct nfq_data *nfad)
{
+ if (!nfad->data[NFQA_MARK])
+ return 0;
+
+ return ntohl(mnl_attr_get_u32(nfad->data[NFQA_MARK]));
return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t));
}
@@ -1152,11 +1194,12 @@ EXPORT_SYMBOL
int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv)
{
struct nfqnl_msg_packet_timestamp *qpt;
- qpt = nfnl_get_pointer_to_data(nfad->data, NFQA_TIMESTAMP,
- struct nfqnl_msg_packet_timestamp);
- if (!qpt)
+
+ if (!nfad->data[NFQA_TIMESTAMP])
return -1;
+ qpt = mnl_attr_get_payload(nfad->data[NFQA_TIMESTAMP]);
+
tv->tv_sec = __be64_to_cpu(qpt->sec);
tv->tv_usec = __be64_to_cpu(qpt->usec);
@@ -1177,7 +1220,10 @@ int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv)
EXPORT_SYMBOL
uint32_t nfq_get_indev(struct nfq_data *nfad)
{
- return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, uint32_t));
+ if (!nfad->data[NFQA_IFINDEX_INDEV])
+ return 0;
+
+ return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_INDEV]));
}
/**
@@ -1191,7 +1237,10 @@ uint32_t nfq_get_indev(struct nfq_data *nfad)
EXPORT_SYMBOL
uint32_t nfq_get_physindev(struct nfq_data *nfad)
{
- return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, uint32_t));
+ if (!nfad->data[NFQA_IFINDEX_PHYSINDEV])
+ return 0;
+
+ return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_PHYSINDEV]));
}
/**
@@ -1205,7 +1254,10 @@ uint32_t nfq_get_physindev(struct nfq_data *nfad)
EXPORT_SYMBOL
uint32_t nfq_get_outdev(struct nfq_data *nfad)
{
- return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, uint32_t));
+ if (!nfad->data[NFQA_IFINDEX_OUTDEV])
+ return 0;
+
+ return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_OUTDEV]));
}
/**
@@ -1221,7 +1273,10 @@ uint32_t nfq_get_outdev(struct nfq_data *nfad)
EXPORT_SYMBOL
uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
{
- return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, uint32_t));
+ if (!nfad->data[NFQA_IFINDEX_PHYSOUTDEV])
+ return 0;
+
+ return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_PHYSOUTDEV]));
}
/**
@@ -1356,8 +1411,10 @@ int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle,
EXPORT_SYMBOL
struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad)
{
- return nfnl_get_pointer_to_data(nfad->data, NFQA_HWADDR,
- struct nfqnl_msg_packet_hw);
+ if (!nfad->data[NFQA_HWADDR])
+ return NULL;
+
+ return mnl_attr_get_payload(nfad->data[NFQA_HWADDR]);
}
/**
@@ -1405,10 +1462,10 @@ uint32_t nfq_get_skbinfo(struct nfq_data *nfad)
EXPORT_SYMBOL
int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
{
- if (!nfnl_attr_present(nfad->data, NFQA_UID))
+ if (!nfad->data[NFQA_UID])
return 0;
- *uid = ntohl(nfnl_get_data(nfad->data, NFQA_UID, uint32_t));
+ *uid = ntohl(mnl_attr_get_u32(nfad->data[NFQA_UID]));
return 1;
}
@@ -1426,10 +1483,10 @@ int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
EXPORT_SYMBOL
int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid)
{
- if (!nfnl_attr_present(nfad->data, NFQA_GID))
+ if (!nfad->data[NFQA_GID])
return 0;
- *gid = ntohl(nfnl_get_data(nfad->data, NFQA_GID, uint32_t));
+ *gid = ntohl(mnl_attr_get_u32(nfad->data[NFQA_GID]));
return 1;
}
@@ -1447,14 +1504,13 @@ int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid)
EXPORT_SYMBOL
int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata)
{
- if (!nfnl_attr_present(nfad->data, NFQA_SECCTX))
+ if (!nfad->data[NFQA_SECCTX])
return -1;
- *secdata = (unsigned char *)nfnl_get_pointer_to_data(nfad->data,
- NFQA_SECCTX, char);
+ *secdata = mnl_attr_get_payload(nfad->data[NFQA_SECCTX]);
if (*secdata)
- return NFA_PAYLOAD(nfad->data[NFQA_SECCTX-1]);
+ return mnl_attr_get_payload_len(nfad->data[NFQA_SECCTX]);
return 0;
}
@@ -1473,10 +1529,12 @@ int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata)
EXPORT_SYMBOL
int nfq_get_payload(struct nfq_data *nfad, unsigned char **data)
{
- *data = (unsigned char *)
- nfnl_get_pointer_to_data(nfad->data, NFQA_PAYLOAD, char);
+ if (!nfad->data[NFQA_PAYLOAD])
+ return -1;
+
+ *data = mnl_attr_get_payload(nfad->data[NFQA_PAYLOAD]);
if (*data)
- return NFA_PAYLOAD(nfad->data[NFQA_PAYLOAD-1]);
+ return mnl_attr_get_payload_len(nfad->data[NFQA_PAYLOAD]);
return -1;
}
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 07/15] src: Convert nfq_set_verdict() and nfq_set_verdict2() to use libmnl if there is no data
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (5 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 06/15] src: Convert nfq_handle_packet(), nfq_get_secctx(), nfq_get_payload() and all the nfq_get_ functions " Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 08/15] src: Incorporate nfnl_rcvbufsiz() in libnetfilter_queue Duncan Roe
` (7 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
static __set_verdict() uses mnl-API calls in enough places that the path
for no (mangled) data doesn't use any nfnl-API functions.
With no data, __set_verdict() uses sendto() (faster than sendmsg()).
nfq_set_verdict2() must not use htonl() on the packet mark.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
v2:
- rebase to account for updated patches 1 - 3
- fix checkpatch warning re block comment termination
src/libnetfilter_queue.c | 36 +++++++++++++++++-------------------
1 file changed, 17 insertions(+), 19 deletions(-)
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index 6500fec..3fa8d2d 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -38,8 +38,8 @@
/* so won't try to validate higher-numbered attrs but will store them. */
/* mnl API programs will then be able to access them. */
#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_compat.h>
-#include <libnfnetlink/libnfnetlink.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include "internal.h"
@@ -951,13 +951,8 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
uint32_t data_len, const unsigned char *data,
enum nfqnl_msg_types type)
{
- struct nfqnl_msg_verdict_hdr vh;
- union {
- char buf[NFNL_HEADER_LEN
- +NFA_LENGTH(sizeof(mark))
- +NFA_LENGTH(sizeof(vh))];
- struct nlmsghdr nmh;
- } u;
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
struct iovec iov[3];
int nvecs;
@@ -968,20 +963,23 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
memset(iov, 0, sizeof(iov));
- vh.verdict = htonl(verdict);
- vh.id = htonl(id);
-
- nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
- type, NLM_F_REQUEST);
+ nlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, qh->id);
/* add verdict header */
- nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_VERDICT_HDR, &vh, sizeof(vh));
+ nfq_nlmsg_verdict_put(nlh, id, verdict);
if (set_mark)
- nfnl_addattr32(&u.nmh, sizeof(u), NFQA_MARK, mark);
+ nfq_nlmsg_verdict_put_mark(nlh, mark);
+
+ /* Efficiency gain: when there is only 1 iov,
+ * sendto() is faster than sendmsg() because the kernel only has
+ * 1 userspace address to validate instead of 2.
+ */
+ if (!data_len)
+ return mnl_socket_sendto(qh->h->nl, nlh, nlh->nlmsg_len);
- iov[0].iov_base = &u.nmh;
- iov[0].iov_len = NLMSG_TAIL(&u.nmh) - (void *)&u.nmh;
+ iov[0].iov_base = nlh;
+ iov[0].iov_len = NLMSG_TAIL(nlh) - (void *)nlh;
nvecs = 1;
if (data_len) {
@@ -995,7 +993,7 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
* header. The size of the attribute is given in the
* nla_len field and is set in the nfnl_build_nfa_iovec()
* function. */
- u.nmh.nlmsg_len += data_attr.nla_len;
+ nlh->nlmsg_len += data_attr.nla_len;
}
return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0);
@@ -1052,7 +1050,7 @@ int nfq_set_verdict2(struct nfq_q_handle *qh, uint32_t id,
uint32_t verdict, uint32_t mark,
uint32_t data_len, const unsigned char *buf)
{
- return __set_verdict(qh, id, verdict, htonl(mark), 1, data_len,
+ return __set_verdict(qh, id, verdict, mark, 1, data_len,
buf, NFQNL_MSG_VERDICT);
}
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 08/15] src: Incorporate nfnl_rcvbufsiz() in libnetfilter_queue
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (6 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 07/15] src: Convert nfq_set_verdict() and nfq_set_verdict2() to use libmnl if there is no data Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 09/15] src: Convert nfq_fd() to use libmnl Duncan Roe
` (6 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
nfnl_rcvbufsiz() is the first bullet point in the Performance section
of the libnetfilter_queue HTML main page.
We have to assume people have used it,
so supply a version that uses libmnl.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
v2: rebase to account for updated patches
.../libnetfilter_queue/libnetfilter_queue.h | 2 ++
src/libnetfilter_queue.c | 36 +++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/include/libnetfilter_queue/libnetfilter_queue.h b/include/libnetfilter_queue/libnetfilter_queue.h
index f7e68d8..9327f8c 100644
--- a/include/libnetfilter_queue/libnetfilter_queue.h
+++ b/include/libnetfilter_queue/libnetfilter_queue.h
@@ -35,6 +35,8 @@ typedef int nfq_callback(struct nfq_q_handle *gh, struct nfgenmsg *nfmsg,
struct nfq_data *nfad, void *data);
+extern unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h,
+ unsigned int size);
extern struct nfq_handle *nfq_open(void);
extern struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh);
extern int nfq_close(struct nfq_handle *h);
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index 3fa8d2d..f26b65f 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -585,6 +585,42 @@ out_free:
* @{
*/
+/**
+ * nfnl_rcvbufsiz - set the socket buffer size
+ * \param h nfnetlink connection handle obtained via call to \b nfq_nfnlh()
+ * \param size size of the buffer we want to set
+ *
+ * This nfnl-API function sets the new size of the socket buffer.
+ * Use this setting
+ * to increase the socket buffer size if your system is reporting ENOBUFS
+ * errors.
+ *
+ * \return new size of kernel socket buffer
+ */
+
+EXPORT_SYMBOL
+unsigned int nfnl_rcvbufsiz(const struct nfnl_handle *h, unsigned int size)
+{
+ int status;
+ socklen_t socklen = sizeof(size);
+ unsigned int read_size = 0;
+
+ /* first we try the FORCE option, which is introduced in kernel
+ * 2.6.14 to give "root" the ability to override the system wide
+ * maximum
+ */
+ status = setsockopt(h->fd, SOL_SOCKET, SO_RCVBUFFORCE, &size, socklen);
+ if (status < 0) {
+ /* if this didn't work, we try at least to get the system
+ * wide maximum (or whatever the user requested)
+ */
+ setsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &size, socklen);
+ }
+ getsockopt(h->fd, SOL_SOCKET, SO_RCVBUF, &read_size, &socklen);
+
+ return read_size;
+}
+
/**
* nfq_close - close a nfqueue handler
* \param h Netfilter queue connection handle obtained via call to nfq_open()
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 09/15] src: Convert nfq_fd() to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (7 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 08/15] src: Incorporate nfnl_rcvbufsiz() in libnetfilter_queue Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 10/15] src: Convert remaining nfq_* functions " Duncan Roe
` (5 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
struct nfq_handle has a struct mnl_socket * now, use that.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
v2: rebase to account for updated patches
src/libnetfilter_queue.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index f26b65f..8a11f41 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -384,7 +384,7 @@ struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h)
EXPORT_SYMBOL
int nfq_fd(struct nfq_handle *h)
{
- return nfnl_fd(nfq_nfnlh(h));
+ return mnl_socket_get_fd(h->nl);
}
/**
* @}
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 10/15] src: Convert remaining nfq_* functions to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (8 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 09/15] src: Convert nfq_fd() to use libmnl Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 11/15] src: Copy nlif-related files from libnfnetlink Duncan Roe
` (4 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
Converted: nfq_set_verdict2(), nfq_set_verdict_batch2(),
nfq_set_verdict_mark(), nfq_get_nfmark() [again] &
nfq_get_skbinfo()
We only use 2 iovecs instead of 3
by tacking the data attribute onto the end of the first iovec buffer.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- Move nfq_set_mode() conversion to patch 5
- Rebase to account for updated patches
src/libnetfilter_queue.c | 67 +++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index 8a11f41..ecdd144 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -989,17 +989,9 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
+ static struct sockaddr_nl snl = {.nl_family = AF_NETLINK };
- struct iovec iov[3];
- int nvecs;
-
- /* This must be declared here (and not inside the data
- * handling block) because the iovec points to this. */
- struct nlattr data_attr;
-
- memset(iov, 0, sizeof(iov));
-
- nlh = nfq_nlmsg_put(buf, NFQNL_MSG_VERDICT, qh->id);
+ nlh = nfq_nlmsg_put(buf, type, qh->id);
/* add verdict header */
nfq_nlmsg_verdict_put(nlh, id, verdict);
@@ -1013,26 +1005,38 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
*/
if (!data_len)
return mnl_socket_sendto(qh->h->nl, nlh, nlh->nlmsg_len);
+ {
+ struct iovec iov[2];
+ struct nlattr *data_attr = mnl_nlmsg_get_payload_tail(nlh);
+ const struct msghdr msg = {
+ .msg_name = &snl,
+ .msg_namelen = sizeof(snl),
+ .msg_iov = iov,
+ .msg_iovlen = 2,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0,
+ };
+
+ mnl_attr_put(nlh, NFQA_PAYLOAD, 0, NULL);
+
+ iov[0].iov_base = nlh;
+ iov[0].iov_len = nlh->nlmsg_len;
+ /* The typecast here is to cast away data's const-ness: */
+ iov[1].iov_base = (unsigned char *)data;
+ iov[1].iov_len = data_len;
- iov[0].iov_base = nlh;
- iov[0].iov_len = NLMSG_TAIL(nlh) - (void *)nlh;
- nvecs = 1;
-
- if (data_len) {
- /* Temporary cast until we get rid of nfnl_build_nfa_iovec() */
- nfnl_build_nfa_iovec(&iov[1], (struct nfattr *)&data_attr,
- //nfnl_build_nfa_iovec(&iov[1], &data_attr,
- NFQA_PAYLOAD, data_len,
- (unsigned char *) data);
- nvecs += 2;
/* Add the length of the appended data to the message
- * header. The size of the attribute is given in the
- * nla_len field and is set in the nfnl_build_nfa_iovec()
- * function. */
- nlh->nlmsg_len += data_attr.nla_len;
- }
+ * header and attribute length.
+ * No padding is needed: this is the end of the message.
+ */
+
+ nlh->nlmsg_len += data_len;
- return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0);
+ data_attr->nla_len += data_len;
+
+ return sendmsg(qh->h->nfnlh->fd, &msg, 0);
+ }
}
/**
@@ -1121,7 +1125,7 @@ EXPORT_SYMBOL
int nfq_set_verdict_batch2(struct nfq_q_handle *qh, uint32_t id,
uint32_t verdict, uint32_t mark)
{
- return __set_verdict(qh, id, verdict, htonl(mark), 1, 0,
+ return __set_verdict(qh, id, verdict, mark, 1, 0,
NULL, NFQNL_MSG_VERDICT_BATCH);
}
@@ -1144,7 +1148,7 @@ int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id,
uint32_t verdict, uint32_t mark,
uint32_t data_len, const unsigned char *buf)
{
- return __set_verdict(qh, id, verdict, mark, 1, data_len, buf,
+ return __set_verdict(qh, id, verdict, ntohl(mark), 1, data_len, buf,
NFQNL_MSG_VERDICT);
}
@@ -1212,7 +1216,6 @@ uint32_t nfq_get_nfmark(struct nfq_data *nfad)
return 0;
return ntohl(mnl_attr_get_u32(nfad->data[NFQA_MARK]));
- return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t));
}
/**
@@ -1476,10 +1479,10 @@ struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad)
EXPORT_SYMBOL
uint32_t nfq_get_skbinfo(struct nfq_data *nfad)
{
- if (!nfnl_attr_present(nfad->data, NFQA_SKB_INFO))
+ if (!nfad->data[NFQA_SKB_INFO])
return 0;
- return ntohl(nfnl_get_data(nfad->data, NFQA_SKB_INFO, uint32_t));
+ return ntohl(mnl_attr_get_u32(nfad->data[NFQA_SKB_INFO]));
}
/**
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 11/15] src: Copy nlif-related files from libnfnetlink
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (9 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 10/15] src: Convert remaining nfq_* functions " Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 12/15] doc: Add iftable.c to the doxygen system Duncan Roe
` (3 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
Introduce include/libnetfilter_queue/linux_list.h and src/iftable.c.
These are not exact copies: all tractable checkpatch errors are fixed.
Also complete iftable.c kerneldoc to doxygen translation.
This commit doesn't actually do anything with the new files.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- This was originally patch 12 of 32
- Update commit message
- Don't copy src/rtnl.c since it's not kept
- Fix checkpatch errors on the fly.
- Finish kerneldoc xlation on the fly (was patch 16 of 32).
include/libnetfilter_queue/linux_list.h | 730 ++++++++++++++++++++++++
src/iftable.c | 355 ++++++++++++
2 files changed, 1085 insertions(+)
create mode 100644 include/libnetfilter_queue/linux_list.h
create mode 100644 src/iftable.c
diff --git a/include/libnetfilter_queue/linux_list.h b/include/libnetfilter_queue/linux_list.h
new file mode 100644
index 0000000..68637c3
--- /dev/null
+++ b/include/libnetfilter_queue/linux_list.h
@@ -0,0 +1,730 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#include <stddef.h>
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ *
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ typeof(((type *)0)->member) *__mptr = (ptr); \
+ (type *)((char *)__mptr - offsetof(type, member)); })
+
+/*
+ * Check at compile time that something is of a particular type.
+ * Always evaluates to 1 so you may use it easily in comparisons.
+ */
+#define typecheck(type, x) \
+({ type __dummy; \
+ typeof(x) __dummy2; \
+ (void)(&__dummy == &__dummy2); \
+ 1; \
+})
+
+#define prefetch(x) ((void)0)
+
+/* empty define to make this work in userspace -HW */
+#ifndef smp_wmb
+#define smp_wmb() /* Comment to placate checkpatch */
+#endif
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x00100100)
+#define LIST_POISON2 ((void *) 0x00200200)
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+ (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add_rcu(struct list_head *new,
+ struct list_head *prev, struct list_head *next)
+{
+ new->next = next;
+ new->prev = prev;
+ smp_wmb(); /* Comment to placate checkpatch */
+ next->prev = new;
+ prev->next = new;
+}
+
+/**
+ * list_add_rcu - add a new entry to rcu-protected list
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as list_add_rcu()
+ * or list_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * list_for_each_entry_rcu().
+ */
+static inline void list_add_rcu(struct list_head *new, struct list_head *head)
+{
+ __list_add_rcu(new, head, head->next);
+}
+
+/**
+ * list_add_tail_rcu - add a new entry to rcu-protected list
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as list_add_tail_rcu()
+ * or list_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * list_for_each_entry_rcu().
+ */
+static inline void list_add_tail_rcu(struct list_head *new,
+ struct list_head *head)
+{
+ __list_add_rcu(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_del_rcu - deletes entry from list without re-initialization
+ * @entry: the element to delete from the list.
+ *
+ * Note: list_empty on entry does not return true after this,
+ * the entry is in an undefined state. It is useful for RCU based
+ * lockfree traversal.
+ *
+ * In particular, it means that we can not poison the forward
+ * pointers that may still be used for walking the list.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as list_del_rcu()
+ * or list_add_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * list_for_each_entry_rcu().
+ *
+ * Note that the caller is not permitted to immediately free
+ * the newly deleted entry. Instead, either synchronize_kernel()
+ * or call_rcu() must be used to defer freeing until an RCU
+ * grace period has elapsed.
+ */
+static inline void list_del_rcu(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is
+ * empty _and_ checks that no other CPU might be
+ * in the process of still modifying either member
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ *
+ * @head: the list to test.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+
+ return (next == head) && (next == head->prev);
+}
+
+static inline void __list_splice(struct list_head *list,
+ struct list_head *head)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+
+ first->prev = head;
+ head->next = first;
+
+ last->next = at;
+ at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, prefetch(pos->next))
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
+ pos = pos->prev, prefetch(pos->prev))
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ prefetch(pos->member.prev); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member), \
+ prefetch(pos->member.prev))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use as a start point in
+ * list_for_each_entry_continue
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - iterate over list of given type
+ * continuing after existing point
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ prefetch(pos->member.next))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop counter.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_rcu - iterate over an rcu-protected list
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+#define list_for_each_rcu(pos, head) \
+ for (pos = (head)->next, prefetch(pos->next); pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0; }), prefetch(pos->next))
+
+#define __list_for_each_rcu(pos, head) \
+ for (pos = (head)->next; pos != (head); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0; }))
+
+/**
+ * list_for_each_safe_rcu - iterate over an rcu-protected list safe
+ * against removal of list entry
+ * @pos: the &struct list_head to use as a loop counter.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+#define list_for_each_safe_rcu(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, ({ smp_read_barrier_depends(); 0; }), n = pos->next)
+
+/**
+ * list_for_each_entry_rcu - iterate over rcu list of given type
+ * @pos: the type * to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+#define list_for_each_entry_rcu(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ prefetch(pos->member.next); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member), \
+ ({ smp_read_barrier_depends(); 0; }), \
+ prefetch(pos->member.next))
+
+
+/**
+ * list_for_each_continue_rcu - iterate over an rcu-protected list
+ * continuing after existing point.
+ * @pos: the &struct list_head to use as a loop counter.
+ * @head: the head for your list.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+#define list_for_each_continue_rcu(pos, head) \
+ for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
+ (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0; }), prefetch((pos)->next))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = LIST_POISON1;
+ n->pprev = LIST_POISON2;
+}
+
+/**
+ * hlist_del_rcu - deletes entry from hash list without re-initialization
+ * @n: the element to delete from the hash list.
+ *
+ * Note: list_unhashed() on entry does not return true after this,
+ * the entry is in an undefined state. It is useful for RCU based
+ * lockfree traversal.
+ *
+ * In particular, it means that we can not poison the forward
+ * pointers that may still be used for walking the hash list.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as hlist_add_head_rcu()
+ * or hlist_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * hlist_for_each_entry().
+ */
+static inline void hlist_del_rcu(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->pprev = LIST_POISON2;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+ if (n->pprev) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
+}
+
+#define hlist_del_rcu_init hlist_del_init
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+
+/**
+ * hlist_add_head_rcu - adds the specified element to the specified hlist,
+ * while permitting racing traversals.
+ * @n: the element to add to the hash list.
+ * @h: the list to add to.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as hlist_add_head_rcu()
+ * or hlist_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * hlist_for_each_entry(), but only if smp_read_barrier_depends()
+ * is used to prevent memory-consistency problems on Alpha CPUs.
+ * Regardless of the type of CPU, the list-traversal primitive
+ * must be guarded by rcu_read_lock().
+ *
+ * OK, so why don't we have an hlist_for_each_entry_rcu()???
+ */
+static inline void hlist_add_head_rcu(struct hlist_node *n,
+ struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+
+ n->next = first;
+ n->pprev = &h->first;
+ smp_wmb(); /* Comment to placate checkpatch */
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+}
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ next->next = n->next;
+ n->next = next;
+ next->pprev = &n->next;
+
+ if (next->next)
+ next->next->pprev = &next->next;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr, type, member)
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+ pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ prefetch(pos->next); 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; \
+ pos && ({ prefetch(pos->next); 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from existing point
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && ({ prefetch(pos->next); 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
+ pos = n)
+
+/**
+ * hlist_for_each_entry_rcu - iterate over rcu list of given type
+ * @pos: the type * to use as a loop counter.
+ * @pos: the &struct hlist_node to use as a loop counter.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as hlist_add_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+#define hlist_for_each_entry_rcu(tpos, pos, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ prefetch(pos->next); 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
+ pos = pos->next, ({ smp_read_barrier_depends(); 0; }))
+
+#endif
diff --git a/src/iftable.c b/src/iftable.c
new file mode 100644
index 0000000..4673001
--- /dev/null
+++ b/src/iftable.c
@@ -0,0 +1,355 @@
+/* iftable - table of network interfaces
+ *
+ * (C) 2004 by Astaro AG, written by Harald Welte <hwelte@astaro.com>
+ * (C) 2008 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2024 by Duncan Roe <duncan_roe@optusnet.com.au>
+ *
+ * This software is Free Software and licensed under GNU GPLv2+.
+ */
+
+/* IFINDEX handling */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <linux/netdevice.h>
+
+#include <libnfnetlink/libnfnetlink.h>
+#include "rtnl.h"
+#include "linux_list.h"
+
+/**
+ * \defgroup iftable Functions to manage a table of network interfaces
+ * These functions maintain a database of the name and flags of each
+ * network interface.
+ * @{
+ */
+
+struct ifindex_node {
+ struct list_head head;
+
+ uint32_t index;
+ uint32_t type;
+ uint32_t alen;
+ uint32_t flags;
+ char addr[8];
+ char name[16];
+};
+
+struct nlif_handle {
+ struct list_head ifindex_hash[16];
+ struct rtnl_handle *rtnl_handle;
+ struct rtnl_handler ifadd_handler;
+ struct rtnl_handler ifdel_handler;
+};
+
+/* iftable_add - Add/Update an entry to/in the interface table
+ * \param n: netlink message header of a RTM_NEWLINK message
+ * \param arg: not used
+ *
+ * This function adds/updates an entry in the intrface table.
+ * Returns -1 on error, 1 on success.
+ */
+static int iftable_add(struct nlmsghdr *n, void *arg)
+{
+ unsigned int hash, found = 0;
+ struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
+ struct ifindex_node *this;
+ struct rtattr *cb[IFLA_MAX+1];
+ struct nlif_handle *h = arg;
+
+ if (n->nlmsg_type != RTM_NEWLINK)
+ return -1;
+
+ if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi_msg)))
+ return -1;
+
+ rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));
+
+ if (!cb[IFLA_IFNAME])
+ return -1;
+
+ hash = ifi_msg->ifi_index & 0xF;
+ list_for_each_entry(this, &h->ifindex_hash[hash], head) {
+ if (this->index == ifi_msg->ifi_index) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ this = malloc(sizeof(*this));
+ if (!this)
+ return -1;
+
+ this->index = ifi_msg->ifi_index;
+ }
+
+ this->type = ifi_msg->ifi_type;
+ this->flags = ifi_msg->ifi_flags;
+ if (cb[IFLA_ADDRESS]) {
+ unsigned int alen;
+
+ this->alen = alen = RTA_PAYLOAD(cb[IFLA_ADDRESS]);
+ if (alen > sizeof(this->addr))
+ alen = sizeof(this->addr);
+ memcpy(this->addr, RTA_DATA(cb[IFLA_ADDRESS]), alen);
+ } else {
+ this->alen = 0;
+ memset(this->addr, 0, sizeof(this->addr));
+ }
+ strcpy(this->name, RTA_DATA(cb[IFLA_IFNAME]));
+
+ if (!found)
+ list_add(&this->head, &h->ifindex_hash[hash]);
+
+ return 1;
+}
+
+/* iftable_del - Delete an entry from the interface table
+ * \param n: netlink message header of a RTM_DELLINK nlmsg
+ * \param arg: not used
+ *
+ * Delete an entry from the interface table.
+ * Returns -1 on error, 0 if no matching entry was found or 1 on success.
+ */
+static int iftable_del(struct nlmsghdr *n, void *arg)
+{
+ struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
+ struct rtattr *cb[IFLA_MAX+1];
+ struct nlif_handle *h = arg;
+ struct ifindex_node *this, *tmp;
+ unsigned int hash;
+
+ if (n->nlmsg_type != RTM_DELLINK)
+ return -1;
+
+ if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi_msg)))
+ return -1;
+
+ rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));
+
+ hash = ifi_msg->ifi_index & 0xF;
+ list_for_each_entry_safe(this, tmp, &h->ifindex_hash[hash], head) {
+ if (this->index == ifi_msg->ifi_index) {
+ list_del(&this->head);
+ free(this);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * nlif_index2name - get the name for an ifindex
+ *
+ * \param h pointer to nlif_handle created by nlif_open()
+ * \param index ifindex to be resolved
+ * \param name interface name, pass a buffer of IFNAMSIZ size
+ * \return -1 on error, 1 on success
+ */
+int nlif_index2name(struct nlif_handle *h,
+ unsigned int index,
+ char *name)
+{
+ unsigned int hash;
+ struct ifindex_node *this;
+
+ assert(h != NULL);
+ assert(name != NULL);
+
+ if (index == 0) {
+ strcpy(name, "*");
+ return 1;
+ }
+
+ hash = index & 0xF;
+ list_for_each_entry(this, &h->ifindex_hash[hash], head) {
+ if (this->index == index) {
+ strcpy(name, this->name);
+ return 1;
+ }
+ }
+
+ errno = ENOENT;
+ return -1;
+}
+
+/**
+ * nlif_get_ifflags - get the flags for an ifindex
+ *
+ * \param h pointer to nlif_handle created by nlif_open()
+ * \param index ifindex to be resolved
+ * \param flags pointer to variable used to store the interface flags
+ * \return -1 on error, 1 on success
+ */
+int nlif_get_ifflags(const struct nlif_handle *h,
+ unsigned int index,
+ unsigned int *flags)
+{
+ unsigned int hash;
+ struct ifindex_node *this;
+
+ assert(h != NULL);
+ assert(flags != NULL);
+
+ if (index == 0) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ hash = index & 0xF;
+ list_for_each_entry(this, &h->ifindex_hash[hash], head) {
+ if (this->index == index) {
+ *flags = this->flags;
+ return 1;
+ }
+ }
+ errno = ENOENT;
+ return -1;
+}
+
+/**
+ * nlif_open - initialize interface table
+ *
+ * Initialize rtnl interface and interface table
+ * Call this before any nlif_* function
+ *
+ * \return file descriptor to netlink socket
+ */
+struct nlif_handle *nlif_open(void)
+{
+ int i;
+ struct nlif_handle *h;
+
+ h = calloc(1, sizeof(struct nlif_handle));
+ if (h == NULL)
+ goto err;
+
+ for (i = 0; i < 16; i++)
+ INIT_LIST_HEAD(&h->ifindex_hash[i]);
+
+ h->ifadd_handler.nlmsg_type = RTM_NEWLINK;
+ h->ifadd_handler.handlefn = iftable_add;
+ h->ifadd_handler.arg = h;
+ h->ifdel_handler.nlmsg_type = RTM_DELLINK;
+ h->ifdel_handler.handlefn = iftable_del;
+ h->ifdel_handler.arg = h;
+
+ h->rtnl_handle = rtnl_open();
+ if (h->rtnl_handle == NULL)
+ goto err;
+
+ if (rtnl_handler_register(h->rtnl_handle, &h->ifadd_handler) < 0)
+ goto err_close;
+
+ if (rtnl_handler_register(h->rtnl_handle, &h->ifdel_handler) < 0)
+ goto err_unregister;
+
+ return h;
+
+err_unregister:
+ rtnl_handler_unregister(h->rtnl_handle, &h->ifadd_handler);
+err_close:
+ rtnl_close(h->rtnl_handle);
+ free(h);
+err:
+ return NULL;
+}
+
+/**
+ * nlif_close - free all resources associated with the interface table
+ *
+ * \param h pointer to nlif_handle created by nlif_open()
+ */
+void nlif_close(struct nlif_handle *h)
+{
+ int i;
+ struct ifindex_node *this, *tmp;
+
+ assert(h != NULL);
+
+ rtnl_handler_unregister(h->rtnl_handle, &h->ifadd_handler);
+ rtnl_handler_unregister(h->rtnl_handle, &h->ifdel_handler);
+ rtnl_close(h->rtnl_handle);
+
+ for (i = 0; i < 16; i++) {
+ list_for_each_entry_safe(this, tmp, &h->ifindex_hash[i], head) {
+ list_del(&this->head);
+ free(this);
+ }
+ }
+
+ free(h);
+ h = NULL; /* bugtrap */
+}
+
+/**
+ * nlif_catch - receive message from netlink and update interface table
+ *
+ * FIXME - elaborate a bit
+ *
+ * \param h pointer to nlif_handle created by nlif_open()
+ * \return 0 if OK
+ */
+int nlif_catch(struct nlif_handle *h)
+{
+ assert(h != NULL);
+
+ if (h->rtnl_handle)
+ return rtnl_receive(h->rtnl_handle);
+
+ return -1;
+}
+
+static int nlif_catch_multi(struct nlif_handle *h)
+{
+ assert(h != NULL);
+
+ if (h->rtnl_handle)
+ return rtnl_receive_multi(h->rtnl_handle);
+
+ return -1;
+}
+
+/**
+ * nlif_query - request a dump of interfaces available in the system
+ * \param h: pointer to a valid nlif_handler
+ */
+int nlif_query(struct nlif_handle *h)
+{
+ assert(h != NULL);
+
+ if (rtnl_dump_type(h->rtnl_handle, RTM_GETLINK) < 0)
+ return -1;
+
+ return nlif_catch_multi(h);
+}
+
+/**
+ * nlif_fd - get file descriptor for the netlink socket
+ *
+ * \param h pointer to nlif_handle created by nlif_open()
+ * \return The fd or -1 if there's an error
+ */
+int nlif_fd(struct nlif_handle *h)
+{
+ assert(h != NULL);
+
+ if (h->rtnl_handle)
+ return h->rtnl_handle->rtnl_fd;
+
+ return -1;
+}
+
+/**
+ * @}
+ */
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 12/15] doc: Add iftable.c to the doxygen system
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (10 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 11/15] src: Copy nlif-related files from libnfnetlink Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 13/15] src: Convert all nlif_* functions to use libmnl Duncan Roe
` (2 subsequent siblings)
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
iftable.c has a usage description (moved from libnetfilter_queue.c),
but is not yet converted to use libmnl.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
v2: Created from patches 14/32 & 16/32
doxygen/Makefile.am | 1 +
doxygen/doxygen.cfg.in | 2 ++
src/iftable.c | 49 ++++++++++++++++++++++++++++++++++++++++
src/libnetfilter_queue.c | 38 ++++---------------------------
4 files changed, 56 insertions(+), 34 deletions(-)
diff --git a/doxygen/Makefile.am b/doxygen/Makefile.am
index 68be963..a6cd83a 100644
--- a/doxygen/Makefile.am
+++ b/doxygen/Makefile.am
@@ -2,6 +2,7 @@ if HAVE_DOXYGEN
doc_srcs = $(top_srcdir)/src/libnetfilter_queue.c\
$(top_srcdir)/src/nlmsg.c\
+ $(top_srcdir)/src/iftable.c\
$(top_srcdir)/src/extra/checksum.c\
$(top_srcdir)/src/extra/ipv4.c\
$(top_srcdir)/src/extra/pktbuff.c\
diff --git a/doxygen/doxygen.cfg.in b/doxygen/doxygen.cfg.in
index fcfc045..bf6cba8 100644
--- a/doxygen/doxygen.cfg.in
+++ b/doxygen/doxygen.cfg.in
@@ -16,6 +16,8 @@ EXCLUDE_SYMBOLS = EXPORT_SYMBOL \
nfnl_handle \
nfnl_subsys_handle \
mnl_socket \
+ ifindex_node \
+ nlif_handle \
nfnl_callback2 \
tcp_flag_word
EXAMPLE_PATTERNS =
diff --git a/src/iftable.c b/src/iftable.c
index 4673001..9884a52 100644
--- a/src/iftable.c
+++ b/src/iftable.c
@@ -29,6 +29,55 @@
* \defgroup iftable Functions to manage a table of network interfaces
* These functions maintain a database of the name and flags of each
* network interface.
+ *
+ * Programs access an nlif database through an opaque __struct nlif_handle__
+ * interface resolving handle. Call nlif_open() to get a handle:
+ * \verbatim
+ h = nlif_open();
+ if (h == NULL) {
+ perror("nlif_open");
+ exit(EXIT_FAILURE);
+ }
+\endverbatim
+ * Once the handler is open, you need to fetch the interface table at a
+ * whole via a call to nlif_query.
+ * \verbatim
+ nlif_query(h);
+\endverbatim
+ * libnetfilter_queue is able to update the interface mapping
+ * when a new interface appears.
+ * To do so, you need to call nlif_catch() on the handler after each
+ * interface related event. The simplest way to get and treat event is to run
+ * a **select()** or **poll()** against the nlif and netilter_queue
+ * file descriptors.
+ * E.g. use nlif_fd() to get the nlif file descriptor, then give this fd to
+ * **poll()** as in this code snippet (error-checking removed):
+ * \verbatim
+ if_fd = nlif_fd(h);
+ qfd = mnl_socket_get_fd(nl); // For mnl API or ...
+ qfd = nfq_fd(qh); // For nfnl API
+ . . .
+ fds[0].fd = ifd;
+ fds[0].events = POLLIN;
+ fds[1].fd = qfd;
+ fds[1].events = POLLIN;
+ for(;;)
+ {
+ poll((struct pollfd *)&fds, 2, -1);
+ if (fds[0].revents & POLLIN)
+ nlif_catch(h);
+\endverbatim
+ * Don't forget to close the handler when you don't need the feature anymore:
+ * \verbatim
+ nlif_close(h);
+\endverbatim
+ *
+ * \manonly
+.SH SYNOPSIS
+.nf
+\fB
+#include <libnetfilter_queue/libnetfilter_queue.h>
+\endmanonly
* @{
*/
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c
index ecdd144..970aea2 100644
--- a/src/libnetfilter_queue.c
+++ b/src/libnetfilter_queue.c
@@ -1324,34 +1324,7 @@ uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
* \param name pointer to the buffer to receive the interface name;
* not more than \c IFNAMSIZ bytes will be copied to it.
* \return -1 in case of error, >0 if it succeed.
- *
- * To use a nlif_handle, You need first to call nlif_open() and to open
- * an handler. Don't forget to store the result as it will be used
- * during all your program life:
- * \verbatim
- h = nlif_open();
- if (h == NULL) {
- perror("nlif_open");
- exit(EXIT_FAILURE);
- }
-\endverbatim
- * Once the handler is open, you need to fetch the interface table at a
- * whole via a call to nlif_query.
- * \verbatim
- nlif_query(h);
-\endverbatim
- * libnfnetlink is able to update the interface mapping when a new interface
- * appears. To do so, you need to call nlif_catch() on the handler after each
- * interface related event. The simplest way to get and treat event is to run
- * a select() or poll() against the nlif file descriptor. To get this file
- * descriptor, you need to use nlif_fd:
- * \verbatim
- if_fd = nlif_fd(h);
-\endverbatim
- * Don't forget to close the handler when you don't need the feature anymore:
- * \verbatim
- nlif_close(h);
-\endverbatim
+ * \sa __nlif_open__(3)
*
*/
EXPORT_SYMBOL
@@ -1370,9 +1343,8 @@ int nfq_get_indev_name(struct nlif_handle *nlif_handle,
* \param name pointer to the buffer to receive the interface name;
* not more than \c IFNAMSIZ bytes will be copied to it.
*
- * See nfq_get_indev_name() documentation for nlif_handle usage.
- *
* \return -1 in case of error, > 0 if it succeed.
+ * \sa __nlif_open__(3)
*/
EXPORT_SYMBOL
int nfq_get_physindev_name(struct nlif_handle *nlif_handle,
@@ -1390,9 +1362,8 @@ int nfq_get_physindev_name(struct nlif_handle *nlif_handle,
* \param name pointer to the buffer to receive the interface name;
* not more than \c IFNAMSIZ bytes will be copied to it.
*
- * See nfq_get_indev_name() documentation for nlif_handle usage.
- *
* \return -1 in case of error, > 0 if it succeed.
+ * \sa __nlif_open__(3)
*/
EXPORT_SYMBOL
int nfq_get_outdev_name(struct nlif_handle *nlif_handle,
@@ -1410,9 +1381,8 @@ int nfq_get_outdev_name(struct nlif_handle *nlif_handle,
* \param name pointer to the buffer to receive the interface name;
* not more than \c IFNAMSIZ bytes will be copied to it.
*
- * See nfq_get_indev_name() documentation for nlif_handle usage.
- *
* \return -1 in case of error, > 0 if it succeed.
+ * \sa __nlif_open__(3)
*/
EXPORT_SYMBOL
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 13/15] src: Convert all nlif_* functions to use libmnl
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (11 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 12/15] doc: Add iftable.c to the doxygen system Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 14/15] include: Use libmnl.h instead of libnfnetlink.h Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 15/15] build: Remove libnfnetlink from the build Duncan Roe
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
In iftable.c, replace calls to functions in rtnetlink.c with inline code
(converted to use libmnl instead of libnfnetlink).
It is essential to offer *all* functions originally provided by
libnfnetlink so that a built program will either take its nlif_*()
functions from libnetfilter_queue or libnfnetlink (depending on the
build-time order in LIBS).
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
v2: created from patches 19/32 & (some of) 32/32
src/Makefile.am | 1 +
src/iftable.c | 311 ++++++++++++++++++++++--------------------------
2 files changed, 141 insertions(+), 171 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index 079853e..a6813e8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,6 +30,7 @@ libnetfilter_queue_la_LDFLAGS = -Wc,-nostartfiles \
-version-info $(LIBVERSION)
libnetfilter_queue_la_SOURCES = libnetfilter_queue.c \
nlmsg.c \
+ iftable.c \
extra/checksum.c \
extra/icmp.c \
extra/ipv6.c \
diff --git a/src/iftable.c b/src/iftable.c
index 9884a52..54364b3 100644
--- a/src/iftable.c
+++ b/src/iftable.c
@@ -11,19 +11,29 @@
#include <unistd.h>
#include <stdlib.h>
+#include <time.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
-#include <assert.h>
#include <linux/netdevice.h>
-#include <libnfnetlink/libnfnetlink.h>
-#include "rtnl.h"
-#include "linux_list.h"
+#include <libmnl/libmnl.h>
+#include <linux/rtnetlink.h>
+#include <libnetfilter_queue/linux_list.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+#include <libnetfilter_queue/libnetfilter_queue.h>
+
+#include "internal.h"
+
+#define NUM_NLIF_BITS 4
+#define NUM_NLIF_ENTRIES (1 << NUM_NLIF_BITS)
+#define NLIF_ENTRY_MASK (NUM_NLIF_ENTRIES - 1)
+
+static int data_cb(const struct nlmsghdr *nlh, void *data);
/**
* \defgroup iftable Functions to manage a table of network interfaces
@@ -86,117 +96,15 @@ struct ifindex_node {
uint32_t index;
uint32_t type;
- uint32_t alen;
uint32_t flags;
- char addr[8];
- char name[16];
+ char name[IFNAMSIZ];
};
struct nlif_handle {
- struct list_head ifindex_hash[16];
- struct rtnl_handle *rtnl_handle;
- struct rtnl_handler ifadd_handler;
- struct rtnl_handler ifdel_handler;
+ struct list_head ifindex_hash[NUM_NLIF_ENTRIES];
+ struct mnl_socket *nl;
};
-/* iftable_add - Add/Update an entry to/in the interface table
- * \param n: netlink message header of a RTM_NEWLINK message
- * \param arg: not used
- *
- * This function adds/updates an entry in the intrface table.
- * Returns -1 on error, 1 on success.
- */
-static int iftable_add(struct nlmsghdr *n, void *arg)
-{
- unsigned int hash, found = 0;
- struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
- struct ifindex_node *this;
- struct rtattr *cb[IFLA_MAX+1];
- struct nlif_handle *h = arg;
-
- if (n->nlmsg_type != RTM_NEWLINK)
- return -1;
-
- if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi_msg)))
- return -1;
-
- rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));
-
- if (!cb[IFLA_IFNAME])
- return -1;
-
- hash = ifi_msg->ifi_index & 0xF;
- list_for_each_entry(this, &h->ifindex_hash[hash], head) {
- if (this->index == ifi_msg->ifi_index) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- this = malloc(sizeof(*this));
- if (!this)
- return -1;
-
- this->index = ifi_msg->ifi_index;
- }
-
- this->type = ifi_msg->ifi_type;
- this->flags = ifi_msg->ifi_flags;
- if (cb[IFLA_ADDRESS]) {
- unsigned int alen;
-
- this->alen = alen = RTA_PAYLOAD(cb[IFLA_ADDRESS]);
- if (alen > sizeof(this->addr))
- alen = sizeof(this->addr);
- memcpy(this->addr, RTA_DATA(cb[IFLA_ADDRESS]), alen);
- } else {
- this->alen = 0;
- memset(this->addr, 0, sizeof(this->addr));
- }
- strcpy(this->name, RTA_DATA(cb[IFLA_IFNAME]));
-
- if (!found)
- list_add(&this->head, &h->ifindex_hash[hash]);
-
- return 1;
-}
-
-/* iftable_del - Delete an entry from the interface table
- * \param n: netlink message header of a RTM_DELLINK nlmsg
- * \param arg: not used
- *
- * Delete an entry from the interface table.
- * Returns -1 on error, 0 if no matching entry was found or 1 on success.
- */
-static int iftable_del(struct nlmsghdr *n, void *arg)
-{
- struct ifinfomsg *ifi_msg = NLMSG_DATA(n);
- struct rtattr *cb[IFLA_MAX+1];
- struct nlif_handle *h = arg;
- struct ifindex_node *this, *tmp;
- unsigned int hash;
-
- if (n->nlmsg_type != RTM_DELLINK)
- return -1;
-
- if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi_msg)))
- return -1;
-
- rtnl_parse_rtattr(cb, IFLA_MAX, IFLA_RTA(ifi_msg), IFLA_PAYLOAD(n));
-
- hash = ifi_msg->ifi_index & 0xF;
- list_for_each_entry_safe(this, tmp, &h->ifindex_hash[hash], head) {
- if (this->index == ifi_msg->ifi_index) {
- list_del(&this->head);
- free(this);
- return 1;
- }
- }
-
- return 0;
-}
-
/**
* nlif_index2name - get the name for an ifindex
*
@@ -205,6 +113,7 @@ static int iftable_del(struct nlmsghdr *n, void *arg)
* \param name interface name, pass a buffer of IFNAMSIZ size
* \return -1 on error, 1 on success
*/
+EXPORT_SYMBOL
int nlif_index2name(struct nlif_handle *h,
unsigned int index,
char *name)
@@ -212,9 +121,6 @@ int nlif_index2name(struct nlif_handle *h,
unsigned int hash;
struct ifindex_node *this;
- assert(h != NULL);
- assert(name != NULL);
-
if (index == 0) {
strcpy(name, "*");
return 1;
@@ -240,6 +146,7 @@ int nlif_index2name(struct nlif_handle *h,
* \param flags pointer to variable used to store the interface flags
* \return -1 on error, 1 on success
*/
+EXPORT_SYMBOL
int nlif_get_ifflags(const struct nlif_handle *h,
unsigned int index,
unsigned int *flags)
@@ -247,9 +154,6 @@ int nlif_get_ifflags(const struct nlif_handle *h,
unsigned int hash;
struct ifindex_node *this;
- assert(h != NULL);
- assert(flags != NULL);
-
if (index == 0) {
errno = ENOENT;
return -1;
@@ -269,11 +173,12 @@ int nlif_get_ifflags(const struct nlif_handle *h,
/**
* nlif_open - initialize interface table
*
- * Initialize rtnl interface and interface table
- * Call this before any nlif_* function
+ * Open a netlink socket and initialize interface table
+ * Call this before any other nlif_* function
*
- * \return file descriptor to netlink socket
+ * \return NULL on error, else valid pointer to an nlif_handle structure
*/
+EXPORT_SYMBOL
struct nlif_handle *nlif_open(void)
{
int i;
@@ -283,32 +188,21 @@ struct nlif_handle *nlif_open(void)
if (h == NULL)
goto err;
- for (i = 0; i < 16; i++)
+ for (i = 0; i < NUM_NLIF_ENTRIES; i++)
INIT_LIST_HEAD(&h->ifindex_hash[i]);
- h->ifadd_handler.nlmsg_type = RTM_NEWLINK;
- h->ifadd_handler.handlefn = iftable_add;
- h->ifadd_handler.arg = h;
- h->ifdel_handler.nlmsg_type = RTM_DELLINK;
- h->ifdel_handler.handlefn = iftable_del;
- h->ifdel_handler.arg = h;
+ h->nl = mnl_socket_open(NETLINK_ROUTE);
+ if (!h->nl)
+ goto err_free;
- h->rtnl_handle = rtnl_open();
- if (h->rtnl_handle == NULL)
- goto err;
-
- if (rtnl_handler_register(h->rtnl_handle, &h->ifadd_handler) < 0)
+ if (mnl_socket_bind(h->nl, RTMGRP_LINK, MNL_SOCKET_AUTOPID) < 0)
goto err_close;
- if (rtnl_handler_register(h->rtnl_handle, &h->ifdel_handler) < 0)
- goto err_unregister;
-
return h;
-err_unregister:
- rtnl_handler_unregister(h->rtnl_handle, &h->ifadd_handler);
err_close:
- rtnl_close(h->rtnl_handle);
+ mnl_socket_close(h->nl);
+err_free:
free(h);
err:
return NULL;
@@ -319,18 +213,15 @@ err:
*
* \param h pointer to nlif_handle created by nlif_open()
*/
+EXPORT_SYMBOL
void nlif_close(struct nlif_handle *h)
{
int i;
struct ifindex_node *this, *tmp;
- assert(h != NULL);
+ mnl_socket_close(h->nl);
- rtnl_handler_unregister(h->rtnl_handle, &h->ifadd_handler);
- rtnl_handler_unregister(h->rtnl_handle, &h->ifdel_handler);
- rtnl_close(h->rtnl_handle);
-
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < NUM_NLIF_ENTRIES; i++) {
list_for_each_entry_safe(this, tmp, &h->ifindex_hash[i], head) {
list_del(&this->head);
free(this);
@@ -344,61 +235,139 @@ void nlif_close(struct nlif_handle *h)
/**
* nlif_catch - receive message from netlink and update interface table
*
- * FIXME - elaborate a bit
- *
* \param h pointer to nlif_handle created by nlif_open()
* \return 0 if OK
*/
+EXPORT_SYMBOL
int nlif_catch(struct nlif_handle *h)
{
- assert(h != NULL);
-
- if (h->rtnl_handle)
- return rtnl_receive(h->rtnl_handle);
-
- return -1;
-}
-
-static int nlif_catch_multi(struct nlif_handle *h)
-{
- assert(h != NULL);
-
- if (h->rtnl_handle)
- return rtnl_receive_multi(h->rtnl_handle);
+ /*
+ * Use MNL_SOCKET_BUFFER_SIZE instead of MNL_SOCKET_DUMP_SIZE
+ * to keep memory footprint same as it was.
+ */
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ int ret;
+
+ if (!h->nl) /* The old library had this test */
+ return -1;
- return -1;
+ ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
+ if (ret == -1)
+ return -1;
+ return mnl_cb_run(buf, ret, 0, mnl_socket_get_portid(h->nl),
+ data_cb, h) == -1 ? -1 : 0;
}
/**
* nlif_query - request a dump of interfaces available in the system
* \param h: pointer to a valid nlif_handler
+ * \return -1 on error with errno set, else >=0
*/
+EXPORT_SYMBOL
int nlif_query(struct nlif_handle *h)
{
- assert(h != NULL);
-
- if (rtnl_dump_type(h->rtnl_handle, RTM_GETLINK) < 0)
+ char buf[MNL_SOCKET_BUFFER_SIZE];
+ struct nlmsghdr *nlh;
+ uint32_t seq;
+ int ret;
+ struct rtgenmsg *rt;
+
+ nlh = mnl_nlmsg_put_header(buf);
+ nlh->nlmsg_type = RTM_GETLINK;
+ nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ nlh->nlmsg_seq = seq = time(NULL);
+ rt = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtgenmsg));
+ rt->rtgen_family = AF_PACKET;
+ if (mnl_socket_sendto(h->nl, nlh, nlh->nlmsg_len) < 0)
return -1;
-
- return nlif_catch_multi(h);
+ ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
+ while (ret > 0) {
+ ret = mnl_cb_run(buf, ret, seq, mnl_socket_get_portid(h->nl),
+ data_cb, h);
+ if (ret <= MNL_CB_STOP)
+ break;
+ ret = mnl_socket_recvfrom(h->nl, buf, sizeof(buf));
+ }
+ return ret;
}
/**
* nlif_fd - get file descriptor for the netlink socket
*
* \param h pointer to nlif_handle created by nlif_open()
- * \return The fd or -1 if there's an error
+ * \return socket fd or -1 on error
*/
+EXPORT_SYMBOL
int nlif_fd(struct nlif_handle *h)
{
- assert(h != NULL);
-
- if (h->rtnl_handle)
- return h->rtnl_handle->rtnl_fd;
-
- return -1;
+ return h->nl ? mnl_socket_get_fd(h->nl) : -1;
}
/**
* @}
*/
+
+/*
+ * data_cb - callback for rtnetlink messages
+ * caller will put nlif_handle in data
+ */
+
+static int data_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct ifinfomsg *ifi_msg = mnl_nlmsg_get_payload(nlh);
+ struct nlif_handle *h = data;
+ struct nlattr *attr;
+ uint32_t hash;
+ struct ifindex_node *this, *tmp;
+
+ if (nlh->nlmsg_type != RTM_NEWLINK && nlh->nlmsg_type != RTM_DELLINK) {
+ errno = EPROTO;
+ return MNL_CB_ERROR;
+ }
+ hash = ifi_msg->ifi_index & NLIF_ENTRY_MASK;
+
+ /* RTM_DELLINK is simple, do it first for less indenting */
+ if (nlh->nlmsg_type == RTM_DELLINK) {
+ /*
+ * The original code used list_for_each_entry_safe when deleting
+ * and list_for_each_entry when adding.
+ * The code is only ever going to delete one entry
+ * so what does the safe variant achieve?
+ * In a multi-threaded app,
+ * I'd suggest a pthread rwlock on all nlif accesses.
+ */
+ list_for_each_entry_safe(this, tmp, &h->ifindex_hash[hash],
+ head) {
+ if (this->index == ifi_msg->ifi_index) {
+ list_del(&this->head);
+ free(this);
+ }
+ }
+ return MNL_CB_OK;
+ }
+
+ list_for_each_entry(this, &h->ifindex_hash[hash], head) {
+ if (this->index == ifi_msg->ifi_index)
+ goto found;
+ }
+ this = calloc(1, sizeof(*this));
+ if (!this)
+ return MNL_CB_ERROR;
+ this->index = ifi_msg->ifi_index;
+ this->type = ifi_msg->ifi_type;
+ this->flags = ifi_msg->ifi_flags;
+ list_add(&this->head, &h->ifindex_hash[hash]);
+found:
+ mnl_attr_for_each(attr, nlh, sizeof(*ifi_msg)) {
+ /* All we want is the interface name */
+ if (mnl_attr_get_type(attr) == IFLA_IFNAME) {
+ if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
+ perror("mnl_attr_validate");
+ return MNL_CB_ERROR;
+ }
+ strcpy(this->name, mnl_attr_get_str(attr));
+ break;
+ }
+ }
+ return MNL_CB_OK;
+}
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 14/15] include: Use libmnl.h instead of libnfnetlink.h
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (12 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 13/15] src: Convert all nlif_* functions to use libmnl Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 15/15] build: Remove libnfnetlink from the build Duncan Roe
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
Add nlif_* prototypes and 64-bit converters to libnetfilter_queue.h.
Update (deprecated) include/libnetfilter_queue/linux_nfnetlink_queue.h
to use /usr/include/linux/nfnetlink.h
instead of libnfnetlink/linux_nfnetlink.h
As an aside, everything compiles fine with this line removed
(i.e library, utils and examples all compile),
so maybe we can do without it.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
Changes in v2:
- This was patch 18 v1
- Update commit message:
- libnetfilter_queue.c has no libnfnetlink.h references
(removed in patch 6 v2).
- Incorporate patch 22 v1
.../libnetfilter_queue/libnetfilter_queue.h | 36 ++++++++++++++++++-
.../linux_nfnetlink_queue.h | 3 +-
2 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/include/libnetfilter_queue/libnetfilter_queue.h b/include/libnetfilter_queue/libnetfilter_queue.h
index 9327f8c..46289f2 100644
--- a/include/libnetfilter_queue/libnetfilter_queue.h
+++ b/include/libnetfilter_queue/libnetfilter_queue.h
@@ -14,7 +14,7 @@
#define __LIBCTNETLINK_H
#include <sys/time.h>
-#include <libnfnetlink/libnfnetlink.h>
+#include <libmnl/libmnl.h>
#include <libnetfilter_queue/linux_nfnetlink_queue.h>
@@ -25,6 +25,7 @@ extern "C" {
struct nfq_handle;
struct nfq_q_handle;
struct nfq_data;
+struct nlif_handle;
extern int nfq_errno;
@@ -155,8 +156,41 @@ int nfq_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr **attr);
struct nlmsghdr *nfq_nlmsg_put(char *buf, int type, uint32_t queue_num);
struct nlmsghdr *nfq_nlmsg_put2(char *buf, int type, uint32_t queue_num, uint16_t flags);
+/*
+ * Network Interface Table API
+ */
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+
+struct nlif_handle *nlif_open(void);
+void nlif_close(struct nlif_handle *orig);
+int nlif_fd(struct nlif_handle *nlif_handle);
+int nlif_query(struct nlif_handle *nlif_handle);
+int nlif_catch(struct nlif_handle *nlif_handle);
+int nlif_index2name(struct nlif_handle *nlif_handle, unsigned int if_index, char *name);
+int nlif_get_ifflags(const struct nlif_handle *h, unsigned int index, unsigned int *flags);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
+/*
+ * __be46 stuff - should be in libmnl.h maybe?
+ */
+
+#include <byteswap.h>
+#if __BYTE_ORDER == __BIG_ENDIAN
+# ifndef __be64_to_cpu
+# define __be64_to_cpu(x) (x)
+# endif
+# else
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# ifndef __be64_to_cpu
+# define __be64_to_cpu(x) __bswap_64(x)
+# endif
+# endif
+#endif
+
#endif /* __LIBNFQNETLINK_H */
diff --git a/include/libnetfilter_queue/linux_nfnetlink_queue.h b/include/libnetfilter_queue/linux_nfnetlink_queue.h
index 6844270..82d8ece 100644
--- a/include/libnetfilter_queue/linux_nfnetlink_queue.h
+++ b/include/libnetfilter_queue/linux_nfnetlink_queue.h
@@ -8,7 +8,8 @@
#endif
#include <linux/types.h>
-#include <libnfnetlink/linux_nfnetlink.h>
+/* Use the real header since libnfnetlink is going away. */
+#include <linux/nfnetlink.h>
enum nfqnl_msg_types {
NFQNL_MSG_PACKET, /* packet from kernel to userspace */
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH libnetfilter_queue v2 15/15] build: Remove libnfnetlink from the build
2024-05-24 5:37 [PATCH libnetfilter_queue v2 00/15] Convert libnetfilter_queue to not need libnfnetlink Duncan Roe
` (13 preceding siblings ...)
2024-05-24 5:37 ` [PATCH libnetfilter_queue v2 14/15] include: Use libmnl.h instead of libnfnetlink.h Duncan Roe
@ 2024-05-24 5:37 ` Duncan Roe
14 siblings, 0 replies; 16+ messages in thread
From: Duncan Roe @ 2024-05-24 5:37 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
libnfnetlink was a "private library" - always loaded whether user apps
used it or not. Remove it now it is no longer needed.
Signed-off-by: Duncan Roe <duncan_roe@optusnet.com.au>
---
v2: This was patch 21/32. No changes.
Make_global.am | 2 +-
configure.ac | 1 -
libnetfilter_queue.pc.in | 2 --
src/Makefile.am | 2 +-
4 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/Make_global.am b/Make_global.am
index 91da5da..4d8a58e 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -1,2 +1,2 @@
-AM_CPPFLAGS = -I${top_srcdir}/include ${LIBNFNETLINK_CFLAGS} ${LIBMNL_CFLAGS}
+AM_CPPFLAGS = -I${top_srcdir}/include ${LIBMNL_CFLAGS}
AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN}
diff --git a/configure.ac b/configure.ac
index 7359fba..ba7b15f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,7 +42,6 @@ case "$host" in
esac
dnl Dependencies
-PKG_CHECK_MODULES([LIBNFNETLINK], [libnfnetlink >= 0.0.41])
PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.3])
AS_IF([test "$enable_man_pages" = no -a "$enable_html_doc" = no],
diff --git a/libnetfilter_queue.pc.in b/libnetfilter_queue.pc.in
index 9c6c2c4..1927a8a 100644
--- a/libnetfilter_queue.pc.in
+++ b/libnetfilter_queue.pc.in
@@ -9,8 +9,6 @@ Name: libnetfilter_queue
Description: netfilter userspace packet queueing library
URL: http://netfilter.org/projects/libnetfilter_queue/
Version: @VERSION@
-Requires: libnfnetlink
Conflicts:
Libs: -L${libdir} -lnetfilter_queue
-Libs.private: @LIBNFNETLINK_LIBS@
Cflags: -I${includedir}
diff --git a/src/Makefile.am b/src/Makefile.am
index a6813e8..e5e1d66 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,4 +39,4 @@ libnetfilter_queue_la_SOURCES = libnetfilter_queue.c \
extra/pktbuff.c \
extra/udp.c
-libnetfilter_queue_la_LIBADD = ${LIBNFNETLINK_LIBS} ${LIBMNL_LIBS}
+libnetfilter_queue_la_LIBADD = ${LIBMNL_LIBS}
--
2.35.8
^ permalink raw reply related [flat|nested] 16+ messages in thread