Add copies of nfnl_handle, nfnl_subsys_handle & mnl_socket to libnetfilter_queue.c. After calling mnl_socket_open() & mnl_socket_bind(), it fills in the libnfnetlink structs as if nfnl_open() had been called. The rest of the system still uses libnfnetlink functions but they keep working. Where possible, code is copied exactly from libnfnetlink. checkpatch warns about space before tabs but these warnings are addressed in a later commit. Signed-off-by: Duncan Roe <duncan_roe@xxxxxxxxxxxxxxx> --- doxygen/doxygen.cfg.in | 3 ++ src/libnetfilter_queue.c | 88 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 9 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..2aba68d 100644 --- a/src/libnetfilter_queue.c +++ b/src/libnetfilter_queue.c @@ -31,6 +31,7 @@ #include <sys/socket.h> #include <linux/netfilter/nfnetlink_queue.h> +#include <libmnl/libmnl.h> #include <libnfnetlink/libnfnetlink.h> #include <libnetfilter_queue/libnetfilter_queue.h> #include "internal.h" @@ -134,11 +135,43 @@ gcc -g3 -ggdb -Wall -lmnl -lnetfilter_queue -o nf-queue nf-queue.c * burst */ +/* Copy of private libnfnetlink structures */ + +#define NFNL_MAX_SUBSYS 16 + +struct nfnl_subsys_handle { + struct nfnl_handle *nfnlh; + uint32_t subscriptions; + uint8_t subsys_id; + uint8_t cb_count; + struct nfnl_callback *cb; /* array of callbacks */ +}; + +struct nfnl_handle { + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + uint32_t subscriptions; + uint32_t seq; + uint32_t dump; + uint32_t rcv_buffer_size; /* for nfnl_catch */ + uint32_t flags; + struct nlmsghdr *last_nlhdr; + struct nfnl_subsys_handle subsys[NFNL_MAX_SUBSYS+1]; +}; + +/* Copy of private libmnl structure */ +struct mnl_socket { + int fd; + struct sockaddr_nl addr; +}; + struct nfq_handle { struct nfnl_handle *nfnlh; struct nfnl_subsys_handle *nfnlssh; struct nfq_q_handle *qh_list; + struct mnl_socket *nl; }; struct nfq_q_handle @@ -383,20 +416,57 @@ int nfq_fd(struct nfq_handle *h) EXPORT_SYMBOL struct nfq_handle *nfq_open(void) { - struct nfnl_handle *nfnlh = nfnl_open(); - struct nfq_handle *qh; + struct nfnl_callback pkt_cb = { + .call = __nfq_rcv_pkt, + .attr_count = NFQA_MAX, + }; + struct nfq_handle *h = malloc(sizeof(*h)); - if (!nfnlh) + if (!h) return NULL; + memset(h, 0, sizeof(*h)); - /* unset netlink sequence tracking by default */ - nfnl_unset_sequence_tracking(nfnlh); + h->nfnlh = malloc(sizeof(*h->nfnlh)); + if (!h->nfnlh) + goto err_free; + memset(h->nfnlh, 0, sizeof(*h->nfnlh)); + + h->nl = mnl_socket_open(NETLINK_NETFILTER); + if (!h->nl) + goto err_free2; + + if (mnl_socket_bind(h->nl, 0, MNL_SOCKET_AUTOPID) < 0) + goto err_close; + + /* Fill in nfnl handle */ + h->nfnlh->fd = h->nl->fd; + h->nfnlh->local = h->nl->addr; + h->nfnlh->peer.nl_family = AF_NETLINK; + //h->nfnlh->seq = time(NULL); + h->nfnlh->rcv_buffer_size = NFNL_BUFFSIZE; + + /* Fill in nfnl subsys handle with code adapted from libnfnetlink */ + h->nfnlssh = &h->nfnlh->subsys[NFNL_SUBSYS_QUEUE]; + h->nfnlssh->cb = calloc(NFQNL_MSG_MAX, sizeof(*(h->nfnlssh->cb))); + if (!h->nfnlssh->cb) + goto err_close; + + h->nfnlssh->nfnlh = h->nfnlh; + h->nfnlssh->cb_count = NFQNL_MSG_MAX; + h->nfnlssh->subscriptions = 0; + h->nfnlssh->subsys_id = NFNL_SUBSYS_QUEUE; + pkt_cb.data = h; + memcpy(&h->nfnlssh->cb[NFQNL_MSG_PACKET], &pkt_cb, sizeof(pkt_cb)); - qh = nfq_open_nfnl(nfnlh); - if (!qh) - nfnl_close(nfnlh); + return h; - return qh; +err_close: + mnl_socket_close(h->nl); +err_free2: + free(h->nfnlh); +err_free: + free(h); + return NULL; } /** -- 2.35.8