From b245e4092c5a7f09729e64868a42e13f48ac5db8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 12 Oct 2010 13:24:08 +0200 Subject: src: allow to use nfct handler for conntrack and expectations at the same time This patch re-works the callback handling to allow the use the same socket to send/receive commands and listen to events of both conntrack and expectation subsystems. Now you can register one callback for conntrack and one for expectation with the same handler with no problems (before this patch, this was not possible, you required two different handlers). Signed-off-by: Pablo Neira Ayuso --- src/conntrack/Makefile.am | 2 +- src/conntrack/api.c | 36 +++++++++++++++---------------- src/conntrack/bsf.c | 30 ++++++++++++++++++++++++++ src/conntrack/callback.c | 55 ----------------------------------------------- 4 files changed, 49 insertions(+), 74 deletions(-) delete mode 100644 src/conntrack/callback.c (limited to 'src/conntrack') diff --git a/src/conntrack/Makefile.am b/src/conntrack/Makefile.am index 68c2d72..34afefb 100644 --- a/src/conntrack/Makefile.am +++ b/src/conntrack/Makefile.am @@ -4,7 +4,7 @@ AM_CFLAGS = -Wall ${LIBNFNETLINK_CFLAGS} noinst_LTLIBRARIES = libnfconntrack.la -libnfconntrack_la_SOURCES = api.c callback.c \ +libnfconntrack_la_SOURCES = api.c \ getter.c setter.c \ parse.c build.c \ snprintf.c \ diff --git a/src/conntrack/api.c b/src/conntrack/api.c index d7f16fe..825afba 100644 --- a/src/conntrack/api.c +++ b/src/conntrack/api.c @@ -226,17 +226,17 @@ int nfct_callback_register(struct nfct_handle *h, container->type = type; container->data = data; - h->nfnl_cb.call = __callback; - h->nfnl_cb.data = container; - h->nfnl_cb.attr_count = CTA_MAX; + h->nfnl_cb_ct.call = __callback; + h->nfnl_cb_ct.data = container; + h->nfnl_cb_ct.attr_count = CTA_MAX; nfnl_callback_register(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW, - &h->nfnl_cb); + &h->nfnl_cb_ct); nfnl_callback_register(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE, - &h->nfnl_cb); + &h->nfnl_cb_ct); return 0; } @@ -253,11 +253,11 @@ void nfct_callback_unregister(struct nfct_handle *h) nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE); h->cb = NULL; - free(h->nfnl_cb.data); + free(h->nfnl_cb_ct.data); - h->nfnl_cb.call = NULL; - h->nfnl_cb.data = NULL; - h->nfnl_cb.attr_count = 0; + h->nfnl_cb_ct.call = NULL; + h->nfnl_cb_ct.data = NULL; + h->nfnl_cb_ct.attr_count = 0; } /** @@ -300,17 +300,17 @@ int nfct_callback_register2(struct nfct_handle *h, container->type = type; container->data = data; - h->nfnl_cb.call = __callback; - h->nfnl_cb.data = container; - h->nfnl_cb.attr_count = CTA_MAX; + h->nfnl_cb_ct.call = __callback; + h->nfnl_cb_ct.data = container; + h->nfnl_cb_ct.attr_count = CTA_MAX; nfnl_callback_register(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW, - &h->nfnl_cb); + &h->nfnl_cb_ct); nfnl_callback_register(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE, - &h->nfnl_cb); + &h->nfnl_cb_ct); return 0; } @@ -327,11 +327,11 @@ void nfct_callback_unregister2(struct nfct_handle *h) nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE); h->cb2 = NULL; - free(h->nfnl_cb.data); + free(h->nfnl_cb_ct.data); - h->nfnl_cb.call = NULL; - h->nfnl_cb.data = NULL; - h->nfnl_cb.attr_count = 0; + h->nfnl_cb_ct.call = NULL; + h->nfnl_cb_ct.data = NULL; + h->nfnl_cb_ct.attr_count = 0; } /** diff --git a/src/conntrack/bsf.c b/src/conntrack/bsf.c index 69a7f14..ae7fa4a 100644 --- a/src/conntrack/bsf.c +++ b/src/conntrack/bsf.c @@ -8,6 +8,7 @@ #include "internal/internal.h" #include "internal/stack.h" #include +#include /* offsetof */ #ifndef SKF_AD_NLATTR #define SKF_AD_NLATTR 12 @@ -214,6 +215,33 @@ nfct_bsf_jump_to(struct sock_filter *this, int line, int pos) return NEW_POS(__code); }; +/* this helps to skip messages coming from the ctnetlink expectation subsys. */ +static int +bsf_cmp_subsys(struct sock_filter *this, int pos, u_int8_t subsys) +{ + struct sock_filter __code[] = { + [0] = { + /* X = offset to nlh->nlmsg_type */ + .code = BPF_LDX|BPF_IMM, + .k = offsetof(struct nlmsghdr, nlmsg_type), + }, + [1] = { + /* A = skb->data[X+k:B] (subsys_id) */ + .code = BPF_LD|BPF_B|BPF_IND, + .k = sizeof(u_int8_t), + }, + [2] = { + /* A == subsys ? jump +1 : accept */ + .code = BPF_JMP|BPF_JEQ|BPF_K, + .k = subsys, + .jt = 1, + .jf = 0, + }, + }; + memcpy(&this[pos], &__code, sizeof(__code)); + return NEW_POS(__code); +} + static int add_state_filter_cta(struct sock_filter *this, unsigned int cta_protoinfo_proto, @@ -584,6 +612,8 @@ int __setup_netlink_socket_filter(int fd, struct nfct_filter *f) memset(bsf, 0, sizeof(bsf)); + j += bsf_cmp_subsys(&bsf[j], j, NFNL_SUBSYS_CTNETLINK); + j += nfct_bsf_ret_verdict(bsf, NFCT_FILTER_ACCEPT, j); j += bsf_add_proto_filter(f, &bsf[j]); j += bsf_add_saddr_ipv4_filter(f, &bsf[j]); j += bsf_add_daddr_ipv4_filter(f, &bsf[j]); diff --git a/src/conntrack/callback.c b/src/conntrack/callback.c deleted file mode 100644 index c83a564..0000000 --- a/src/conntrack/callback.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * (C) 2006 by Pablo Neira Ayuso - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include "internal/internal.h" - -int __callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data) -{ - int ret = NFNL_CB_STOP; - unsigned int type; - struct nf_conntrack *ct; - int len = nlh->nlmsg_len; - struct __data_container *container = data; - - len -= NLMSG_LENGTH(sizeof(struct nfgenmsg)); - if (len < 0) - return NFNL_CB_CONTINUE; - - type = __parse_message_type(nlh); - if (!(type & container->type)) - return NFNL_CB_CONTINUE; - - ct = nfct_new(); - if (!ct) - return NFNL_CB_CONTINUE; - - __parse_conntrack(nlh, nfa, ct); - - if (container->h->cb) - ret = container->h->cb(type, ct, container->data); - else if (container->h->cb2) - ret = container->h->cb2(nlh, type, ct, container->data); - - switch(ret) { - case NFCT_CB_FAILURE: - free(ct); - ret = NFNL_CB_FAILURE; - break; - case NFCT_CB_STOP: - free(ct); - ret = NFNL_CB_STOP; - break; - case NFCT_CB_CONTINUE: - free(ct); - ret = NFNL_CB_CONTINUE; - break; - case NFCT_CB_STOLEN: - ret = NFNL_CB_CONTINUE; - break; - } - return ret; -} -- cgit v1.2.3