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@xxxxxxxxxxxxxxx> --- Changes in v3: (none) Changes in v2: - Rather than inline nfnl subsys code, minimally modify nfq_open_nfnl() as per updated commit message - Replace NFNL_BUFFSIZE with MNL_SOCKET_BUFFER_SIZE - Use calloc instead of malloc + memset in new code - Don't rename struct nfq_handle *qh to *h - Fix checkpatch space before tab warnings in lines 143,147,159,165 - Keep nfq_errno doxygen/doxygen.cfg.in | 3 ++ src/libnetfilter_queue.c | 86 ++++++++++++++++++++++++++++++++++------ 2 files changed, 77 insertions(+), 12 deletions(-) diff --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