Discussion:
[PATCH RFC 1/9] net: rename fp->bpf_func to fp->run_filter
Pablo Neira Ayuso
2014-03-11 09:19:12 UTC
Permalink
This patch is a cleanup / rename for the function that actually
performs the filtering from bpf_func to a generic run_filter. This
change was introduced to generalize the socket filtering
infrastructure.

Signed-off-by: Pablo Neira Ayuso <***@netfilter.org>
---
arch/arm/net/bpf_jit_32.c | 6 +++---
arch/powerpc/net/bpf_jit_comp.c | 6 +++---
arch/s390/net/bpf_jit_comp.c | 6 +++---
arch/sparc/net/bpf_jit_comp.c | 6 +++---
arch/x86/net/bpf_jit_comp.c | 6 +++---
include/linux/filter.h | 6 +++---
net/core/filter.c | 2 +-
7 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 271b5e9..65bd347 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -924,7 +924,7 @@ void bpf_jit_compile(struct sk_filter *fp)
/* there are 2 passes here */
bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);

- fp->bpf_func = (void *)ctx.target;
+ fp->run_filter = (void *)ctx.target;
out:
kfree(ctx.offsets);
return;
@@ -932,7 +932,7 @@ out:

void bpf_jit_free(struct sk_filter *fp)
{
- if (fp->bpf_func != sk_run_filter)
- module_free(NULL, fp->bpf_func);
+ if (fp->run_filter != sk_run_filter)
+ module_free(NULL, fp->run_filter);
kfree(fp);
}
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 555034f..6491d72 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -688,7 +688,7 @@ void bpf_jit_compile(struct sk_filter *fp)
/* Function descriptor nastiness: Address + TOC */
((u64 *)image)[0] = (u64)code_base;
((u64 *)image)[1] = local_paca->kernel_toc;
- fp->bpf_func = (void *)image;
+ fp->run_filter = (void *)image;
}
out:
kfree(addrs);
@@ -697,7 +697,7 @@ out:

void bpf_jit_free(struct sk_filter *fp)
{
- if (fp->bpf_func != sk_run_filter)
- module_free(NULL, fp->bpf_func);
+ if (fp->run_filter != sk_run_filter)
+ module_free(NULL, fp->run_filter);
kfree(fp);
}
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 708d60e..23089df 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -876,7 +876,7 @@ void bpf_jit_compile(struct sk_filter *fp)
}
if (jit.start) {
set_memory_ro((unsigned long)header, header->pages);
- fp->bpf_func = (void *) jit.start;
+ fp->run_filter = (void *) jit.start;
}
out:
kfree(addrs);
@@ -884,10 +884,10 @@ out:

void bpf_jit_free(struct sk_filter *fp)
{
- unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
+ unsigned long addr = (unsigned long)fp->run_filter & PAGE_MASK;
struct bpf_binary_header *header = (void *)addr;

- if (fp->bpf_func == sk_run_filter)
+ if (fp->run_filter == sk_run_filter)
goto free_filter;
set_memory_rw(addr, header->pages);
module_free(NULL, header);
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 01fe994..ee1cd30 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -808,7 +808,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf];

if (image) {
bpf_flush_icache(image, image + proglen);
- fp->bpf_func = (void *)image;
+ fp->run_filter = (void *)image;
}
out:
kfree(addrs);
@@ -817,7 +817,7 @@ out:

void bpf_jit_free(struct sk_filter *fp)
{
- if (fp->bpf_func != sk_run_filter)
- module_free(NULL, fp->bpf_func);
+ if (fp->run_filter != sk_run_filter)
+ module_free(NULL, fp->run_filter);
kfree(fp);
}
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 4ed75dd..bfadd14 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -771,7 +771,7 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
if (image) {
bpf_flush_icache(header, image + proglen);
set_memory_ro((unsigned long)header, header->pages);
- fp->bpf_func = (void *)image;
+ fp->run_filter = (void *)image;
}
out:
kfree(addrs);
@@ -781,7 +781,7 @@ out:
static void bpf_jit_free_deferred(struct work_struct *work)
{
struct sk_filter *fp = container_of(work, struct sk_filter, work);
- unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
+ unsigned long addr = (unsigned long)fp->run_filter & PAGE_MASK;
struct bpf_binary_header *header = (void *)addr;

set_memory_rw(addr, header->pages);
@@ -791,7 +791,7 @@ static void bpf_jit_free_deferred(struct work_struct *work)

void bpf_jit_free(struct sk_filter *fp)
{
- if (fp->bpf_func != sk_run_filter) {
+ if (fp->run_filter != sk_run_filter) {
INIT_WORK(&fp->work, bpf_jit_free_deferred);
schedule_work(&fp->work);
} else {
diff --git a/include/linux/filter.h b/include/linux/filter.h
index e568c8e..6c5d597 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -27,8 +27,8 @@ struct sk_filter
atomic_t refcnt;
unsigned int len; /* Number of filter blocks */
struct rcu_head rcu;
- unsigned int (*bpf_func)(const struct sk_buff *skb,
- const struct sock_filter *filter);
+ unsigned int (*run_filter)(const struct sk_buff *skb,
+ const struct sock_filter *filter);
union {
struct sock_filter insns[0];
struct work_struct work;
@@ -70,7 +70,7 @@ static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
print_hex_dump(KERN_ERR, "JIT code: ", DUMP_PREFIX_OFFSET,
16, 1, image, proglen, false);
}
-#define SK_RUN_FILTER(FILTER, SKB) (*FILTER->bpf_func)(SKB, FILTER->insns)
+#define SK_RUN_FILTER(FILTER, SKB) (*FILTER->run_filter)(SKB, FILTER->insns)
#else
#include <linux/slab.h>
static inline void bpf_jit_compile(struct sk_filter *fp)
diff --git a/net/core/filter.c b/net/core/filter.c
index ad30d62..0f63e67 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -645,7 +645,7 @@ static int __sk_prepare_filter(struct sk_filter *fp)
{
int err;

- fp->bpf_func = sk_run_filter;
+ fp->run_filter = sk_run_filter;

err = sk_chk_filter(fp->insns, fp->len);
if (err)
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso
2014-03-11 09:19:14 UTC
Permalink
This patch adds generic a new callback function to release bytecode
area which depends on the socket filter type. This change prepares
the implementation of new socket filtering approaches.

Signed-off-by: Pablo Neira Ayuso <***@netfilter.org>
---
include/linux/filter.h | 1 +
include/net/sock.h | 4 +---
net/core/filter.c | 4 ++--
3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index ab37714..7cba4c2 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -28,6 +28,7 @@ struct sk_filter {
struct rcu_head rcu;
unsigned int (*run_filter)(const struct sk_buff *skb,
const struct sock_filter *filter);
+ void (*release_rcu)(struct rcu_head *rcu);
union {
struct sock_filter insns[0];
struct work_struct work;
diff --git a/include/net/sock.h b/include/net/sock.h
index 7b9723c..9f9acbf 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1616,8 +1616,6 @@ void sk_common_release(struct sock *sk);
/* Initialise core socket variables */
void sock_init_data(struct socket *sock, struct sock *sk);

-void sk_filter_release_rcu(struct rcu_head *rcu);
-
/**
* sk_filter_release - release a socket filter
* @fp: filter to remove
@@ -1628,7 +1626,7 @@ void sk_filter_release_rcu(struct rcu_head *rcu);
static inline void sk_filter_release(struct sk_filter *fp)
{
if (atomic_dec_and_test(&fp->refcnt))
- call_rcu(&fp->rcu, sk_filter_release_rcu);
+ call_rcu(&fp->rcu, fp->release_rcu);
}

static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
diff --git a/net/core/filter.c b/net/core/filter.c
index 3ea0e7f..826ca63 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -633,19 +633,19 @@ EXPORT_SYMBOL(sk_chk_filter);
* sk_filter_release_rcu - Release a socket filter by rcu_head
* @rcu: rcu_head that contains the sk_filter to free
*/
-void sk_filter_release_rcu(struct rcu_head *rcu)
+static void sk_filter_release_rcu(struct rcu_head *rcu)
{
struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu);

bpf_jit_free(fp);
}
-EXPORT_SYMBOL(sk_filter_release_rcu);

static int __sk_prepare_filter(struct sk_filter *fp)
{
int err;

fp->run_filter = sk_run_filter;
+ fp->release_rcu = sk_filter_release_rcu;

err = sk_chk_filter(fp->insns, sk_bpf_flen(fp));
if (err)
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso
2014-03-11 09:19:15 UTC
Permalink
This function will be used from different classifiers, so make
them inline and move them to the nf_tables_core.h header file.

Signed-off-by: Pablo Neira Ayuso <***@netfilter.org>
---
include/net/netfilter/nf_tables_core.h | 42 ++++++++++++++++++++++++++++++++
net/netfilter/nf_tables_core.c | 40 ------------------------------
2 files changed, 42 insertions(+), 40 deletions(-)

diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index cf2b7ae..004c2aa 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -39,4 +39,46 @@ extern const struct nft_expr_ops nft_payload_fast_ops;
int nft_payload_module_init(void);
void nft_payload_module_exit(void);

+#include <net/netfilter/nf_tables.h>
+
+static inline void nft_cmp_fast_eval(const struct nft_expr *expr,
+ struct nft_data data[NFT_REG_MAX + 1])
+{
+ const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
+ u32 mask;
+
+ mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - priv->len);
+ if ((data[priv->sreg].data[0] & mask) == priv->data)
+ return;
+ data[NFT_REG_VERDICT].verdict = NFT_BREAK;
+}
+
+static inline bool nft_payload_fast_eval(const struct nft_expr *expr,
+ struct nft_data data[NFT_REG_MAX + 1],
+ const struct nft_pktinfo *pkt)
+{
+ const struct nft_payload *priv = nft_expr_priv(expr);
+ const struct sk_buff *skb = pkt->skb;
+ struct nft_data *dest = &data[priv->dreg];
+ unsigned char *ptr;
+
+ if (priv->base == NFT_PAYLOAD_NETWORK_HEADER)
+ ptr = skb_network_header(skb);
+ else
+ ptr = skb_network_header(skb) + pkt->xt.thoff;
+
+ ptr += priv->offset;
+
+ if (unlikely(ptr + priv->len >= skb_tail_pointer(skb)))
+ return false;
+
+ if (priv->len == 2)
+ *(u16 *)dest->data = *(u16 *)ptr;
+ else if (priv->len == 4)
+ *(u32 *)dest->data = *(u32 *)ptr;
+ else
+ *(u8 *)dest->data = *(u8 *)ptr;
+ return true;
+}
+
#endif /* _NET_NF_TABLES_CORE_H */
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 90998a6..d71a0be 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -21,46 +21,6 @@
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_log.h>

-static void nft_cmp_fast_eval(const struct nft_expr *expr,
- struct nft_data data[NFT_REG_MAX + 1])
-{
- const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr);
- u32 mask;
-
- mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - priv->len);
- if ((data[priv->sreg].data[0] & mask) == priv->data)
- return;
- data[NFT_REG_VERDICT].verdict = NFT_BREAK;
-}
-
-static bool nft_payload_fast_eval(const struct nft_expr *expr,
- struct nft_data data[NFT_REG_MAX + 1],
- const struct nft_pktinfo *pkt)
-{
- const struct nft_payload *priv = nft_expr_priv(expr);
- const struct sk_buff *skb = pkt->skb;
- struct nft_data *dest = &data[priv->dreg];
- unsigned char *ptr;
-
- if (priv->base == NFT_PAYLOAD_NETWORK_HEADER)
- ptr = skb_network_header(skb);
- else
- ptr = skb_network_header(skb) + pkt->xt.thoff;
-
- ptr += priv->offset;
-
- if (unlikely(ptr + priv->len >= skb_tail_pointer(skb)))
- return false;
-
- if (priv->len == 2)
- *(u16 *)dest->data = *(u16 *)ptr;
- else if (priv->len == 4)
- *(u32 *)dest->data = *(u32 *)ptr;
- else
- *(u8 *)dest->data = *(u8 *)ptr;
- return true;
-}
-
struct nft_jumpstack {
const struct nft_chain *chain;
const struct nft_rule *rule;
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso
2014-03-11 09:19:17 UTC
Permalink
We didn't find a better file name candidate. The core file will
be used to store built-in kernel nf_tables infrastructure that
is common to new supported classifiers.

Signed-off-by: Pablo Neira Ayuso <***@netfilter.org>
---
net/netfilter/Makefile | 2 +-
net/netfilter/nf_tables_core.c | 233 ----------------------------------------
net/netfilter/nf_tables_nf.c | 233 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 234 insertions(+), 234 deletions(-)
delete mode 100644 net/netfilter/nf_tables_core.c
create mode 100644 net/netfilter/nf_tables_nf.c

diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index bffdad7..bb9970c 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -65,7 +65,7 @@ obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
obj-$(CONFIG_NETFILTER_SYNPROXY) += nf_synproxy_core.o

# nf_tables
-nf_tables-objs += nf_tables_core.o nf_tables_api.o
+nf_tables-objs += nf_tables_nf.o nf_tables_api.o
nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o
nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o

diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
deleted file mode 100644
index d71a0be..0000000
--- a/net/netfilter/nf_tables_core.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 2008 Patrick McHardy <***@trash.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Development of this code funded by Astaro AG (http://www.astaro.com/)
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/rculist.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter/nfnetlink.h>
-#include <linux/netfilter/nf_tables.h>
-#include <net/netfilter/nf_tables_core.h>
-#include <net/netfilter/nf_tables.h>
-#include <net/netfilter/nf_log.h>
-
-struct nft_jumpstack {
- const struct nft_chain *chain;
- const struct nft_rule *rule;
- int rulenum;
-};
-
-static inline void
-nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt,
- struct nft_jumpstack *jumpstack, unsigned int stackptr)
-{
- struct nft_stats __percpu *stats;
- const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this;
-
- rcu_read_lock_bh();
- stats = rcu_dereference(nft_base_chain(chain)->stats);
- __this_cpu_inc(stats->pkts);
- __this_cpu_add(stats->bytes, pkt->skb->len);
- rcu_read_unlock_bh();
-}
-
-enum nft_trace {
- NFT_TRACE_RULE,
- NFT_TRACE_RETURN,
- NFT_TRACE_POLICY,
-};
-
-static const char *const comments[] = {
- [NFT_TRACE_RULE] = "rule",
- [NFT_TRACE_RETURN] = "return",
- [NFT_TRACE_POLICY] = "policy",
-};
-
-static struct nf_loginfo trace_loginfo = {
- .type = NF_LOG_TYPE_LOG,
- .u = {
- .log = {
- .level = 4,
- .logflags = NF_LOG_MASK,
- },
- },
-};
-
-static void nft_trace_packet(const struct nft_pktinfo *pkt,
- const struct nft_chain *chain,
- int rulenum, enum nft_trace type)
-{
- struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
-
- nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in,
- pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
- chain->table->name, chain->name, comments[type],
- rulenum);
-}
-
-unsigned int
-nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
-{
- const struct nft_chain *chain = ops->priv;
- const struct nft_rule *rule;
- const struct nft_expr *expr, *last;
- struct nft_data data[NFT_REG_MAX + 1];
- unsigned int stackptr = 0;
- struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
- int rulenum = 0;
- /*
- * Cache cursor to avoid problems in case that the cursor is updated
- * while traversing the ruleset.
- */
- unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor);
-
-do_chain:
- rule = list_entry(&chain->rules, struct nft_rule, list);
-next_rule:
- data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
- list_for_each_entry_continue_rcu(rule, &chain->rules, list) {
-
- /* This rule is not active, skip. */
- if (unlikely(rule->genmask & (1 << gencursor)))
- continue;
-
- rulenum++;
-
- nft_rule_for_each_expr(expr, last, rule) {
- if (expr->ops == &nft_cmp_fast_ops)
- nft_cmp_fast_eval(expr, data);
- else if (expr->ops != &nft_payload_fast_ops ||
- !nft_payload_fast_eval(expr, data, pkt))
- expr->ops->eval(expr, data, pkt);
-
- if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE)
- break;
- }
-
- switch (data[NFT_REG_VERDICT].verdict) {
- case NFT_BREAK:
- data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
- /* fall through */
- case NFT_CONTINUE:
- continue;
- }
- break;
- }
-
- switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
- case NF_ACCEPT:
- case NF_DROP:
- case NF_QUEUE:
- if (unlikely(pkt->skb->nf_trace))
- nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
-
- return data[NFT_REG_VERDICT].verdict;
- }
-
- switch (data[NFT_REG_VERDICT].verdict) {
- case NFT_JUMP:
- if (unlikely(pkt->skb->nf_trace))
- nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
-
- BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE);
- jumpstack[stackptr].chain = chain;
- jumpstack[stackptr].rule = rule;
- jumpstack[stackptr].rulenum = rulenum;
- stackptr++;
- /* fall through */
- case NFT_GOTO:
- chain = data[NFT_REG_VERDICT].chain;
- goto do_chain;
- case NFT_RETURN:
- if (unlikely(pkt->skb->nf_trace))
- nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
-
- /* fall through */
- case NFT_CONTINUE:
- break;
- default:
- WARN_ON(1);
- }
-
- if (stackptr > 0) {
- if (unlikely(pkt->skb->nf_trace))
- nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
-
- stackptr--;
- chain = jumpstack[stackptr].chain;
- rule = jumpstack[stackptr].rule;
- rulenum = jumpstack[stackptr].rulenum;
- goto next_rule;
- }
- nft_chain_stats(chain, pkt, jumpstack, stackptr);
-
- if (unlikely(pkt->skb->nf_trace))
- nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY);
-
- return nft_base_chain(chain)->policy;
-}
-EXPORT_SYMBOL_GPL(nft_do_chain);
-
-int __init nf_tables_core_module_init(void)
-{
- int err;
-
- err = nft_immediate_module_init();
- if (err < 0)
- goto err1;
-
- err = nft_cmp_module_init();
- if (err < 0)
- goto err2;
-
- err = nft_lookup_module_init();
- if (err < 0)
- goto err3;
-
- err = nft_bitwise_module_init();
- if (err < 0)
- goto err4;
-
- err = nft_byteorder_module_init();
- if (err < 0)
- goto err5;
-
- err = nft_payload_module_init();
- if (err < 0)
- goto err6;
-
- return 0;
-
-err6:
- nft_byteorder_module_exit();
-err5:
- nft_bitwise_module_exit();
-err4:
- nft_lookup_module_exit();
-err3:
- nft_cmp_module_exit();
-err2:
- nft_immediate_module_exit();
-err1:
- return err;
-}
-
-void nf_tables_core_module_exit(void)
-{
- nft_payload_module_exit();
- nft_byteorder_module_exit();
- nft_bitwise_module_exit();
- nft_lookup_module_exit();
- nft_cmp_module_exit();
- nft_immediate_module_exit();
-}
diff --git a/net/netfilter/nf_tables_nf.c b/net/netfilter/nf_tables_nf.c
new file mode 100644
index 0000000..d71a0be
--- /dev/null
+++ b/net/netfilter/nf_tables_nf.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2008 Patrick McHardy <***@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/rculist.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_core.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_log.h>
+
+struct nft_jumpstack {
+ const struct nft_chain *chain;
+ const struct nft_rule *rule;
+ int rulenum;
+};
+
+static inline void
+nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt,
+ struct nft_jumpstack *jumpstack, unsigned int stackptr)
+{
+ struct nft_stats __percpu *stats;
+ const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this;
+
+ rcu_read_lock_bh();
+ stats = rcu_dereference(nft_base_chain(chain)->stats);
+ __this_cpu_inc(stats->pkts);
+ __this_cpu_add(stats->bytes, pkt->skb->len);
+ rcu_read_unlock_bh();
+}
+
+enum nft_trace {
+ NFT_TRACE_RULE,
+ NFT_TRACE_RETURN,
+ NFT_TRACE_POLICY,
+};
+
+static const char *const comments[] = {
+ [NFT_TRACE_RULE] = "rule",
+ [NFT_TRACE_RETURN] = "return",
+ [NFT_TRACE_POLICY] = "policy",
+};
+
+static struct nf_loginfo trace_loginfo = {
+ .type = NF_LOG_TYPE_LOG,
+ .u = {
+ .log = {
+ .level = 4,
+ .logflags = NF_LOG_MASK,
+ },
+ },
+};
+
+static void nft_trace_packet(const struct nft_pktinfo *pkt,
+ const struct nft_chain *chain,
+ int rulenum, enum nft_trace type)
+{
+ struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
+
+ nf_log_packet(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in,
+ pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
+ chain->table->name, chain->name, comments[type],
+ rulenum);
+}
+
+unsigned int
+nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
+{
+ const struct nft_chain *chain = ops->priv;
+ const struct nft_rule *rule;
+ const struct nft_expr *expr, *last;
+ struct nft_data data[NFT_REG_MAX + 1];
+ unsigned int stackptr = 0;
+ struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
+ int rulenum = 0;
+ /*
+ * Cache cursor to avoid problems in case that the cursor is updated
+ * while traversing the ruleset.
+ */
+ unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor);
+
+do_chain:
+ rule = list_entry(&chain->rules, struct nft_rule, list);
+next_rule:
+ data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
+ list_for_each_entry_continue_rcu(rule, &chain->rules, list) {
+
+ /* This rule is not active, skip. */
+ if (unlikely(rule->genmask & (1 << gencursor)))
+ continue;
+
+ rulenum++;
+
+ nft_rule_for_each_expr(expr, last, rule) {
+ if (expr->ops == &nft_cmp_fast_ops)
+ nft_cmp_fast_eval(expr, data);
+ else if (expr->ops != &nft_payload_fast_ops ||
+ !nft_payload_fast_eval(expr, data, pkt))
+ expr->ops->eval(expr, data, pkt);
+
+ if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE)
+ break;
+ }
+
+ switch (data[NFT_REG_VERDICT].verdict) {
+ case NFT_BREAK:
+ data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
+ /* fall through */
+ case NFT_CONTINUE:
+ continue;
+ }
+ break;
+ }
+
+ switch (data[NFT_REG_VERDICT].verdict & NF_VERDICT_MASK) {
+ case NF_ACCEPT:
+ case NF_DROP:
+ case NF_QUEUE:
+ if (unlikely(pkt->skb->nf_trace))
+ nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
+
+ return data[NFT_REG_VERDICT].verdict;
+ }
+
+ switch (data[NFT_REG_VERDICT].verdict) {
+ case NFT_JUMP:
+ if (unlikely(pkt->skb->nf_trace))
+ nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
+
+ BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE);
+ jumpstack[stackptr].chain = chain;
+ jumpstack[stackptr].rule = rule;
+ jumpstack[stackptr].rulenum = rulenum;
+ stackptr++;
+ /* fall through */
+ case NFT_GOTO:
+ chain = data[NFT_REG_VERDICT].chain;
+ goto do_chain;
+ case NFT_RETURN:
+ if (unlikely(pkt->skb->nf_trace))
+ nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
+
+ /* fall through */
+ case NFT_CONTINUE:
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ if (stackptr > 0) {
+ if (unlikely(pkt->skb->nf_trace))
+ nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
+
+ stackptr--;
+ chain = jumpstack[stackptr].chain;
+ rule = jumpstack[stackptr].rule;
+ rulenum = jumpstack[stackptr].rulenum;
+ goto next_rule;
+ }
+ nft_chain_stats(chain