* [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support
@ 2014-01-03 12:16 Patrick McHardy
2014-01-03 12:16 ` [PATCH 1/6] netfilter: nf_tables: make chain types override the default AF functions Patrick McHardy
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-03 12:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
The following patches add support for mixed IPv4/IPv6 tables to nftables.
The first patch fixes the chain type override logic so chain types override
the AF defaults instead of the other way around. The second patch adds a
pointer to the nf_hook_ops struct to nft_pktinfo for a later patch which
uses ops->pf to match the actual AF of the packet instead of the dummy
NFPROTO_INET value. The third patch changes the chain and hook registration
logic to support multiple hook registrations. The nf_tables AF modules can
provide a callback function to override defaults. The fourth patch finally
adds a new "inet" family, which basically only initializes the hook
functions to the IPv4 and IPv6 specific ones and registers a dummy filter
chain type for NFPROTO_INET. Patches 5 and 6 add support for matching on
the netfilter hook family and the L4 protocol number to the meta match.
With all this in place, we can create AF-specific rules and AF-independant
rules that only match on the L4 protocol header and above in the inet table:
table inet filter {
chain input {
type filter hook input priority 0;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0;
ip protocol tcp tcp dport 1234 counter packets 2 bytes 120
ip6 nexthdr tcp tcp dport 1234 counter packets 2 bytes 160
tcp dport 1234 counter packets 4 bytes 280
}
}
Userspace needs a bit of polishing but will most likely follow in a few
hours.
Comments welcome.
Patrick McHardy (6):
netfilter: nf_tables: make chain types override the default AF functions
netfilter: nf_tables: add hook ops to struct nft_pktinfo
netfilter: nf_tables: add support for multi family tables
netfilter: nf_tables: add "inet" table for IPv4/IPv6
netfilter: nf_tables: add nfproto support to meta expression
netfilter: nft_meta: add l4proto support
include/net/netfilter/nf_tables.h | 15 ++++-
include/net/netfilter/nf_tables_ipv4.h | 5 +-
include/net/netfilter/nf_tables_ipv6.h | 3 +
include/net/netns/nftables.h | 1 +
include/uapi/linux/netfilter.h | 1 +
include/uapi/linux/netfilter/nf_tables.h | 4 ++
net/bridge/netfilter/nf_tables_bridge.c | 39 ++++++-------
net/ipv4/netfilter/nf_tables_arp.c | 39 ++++++-------
net/ipv4/netfilter/nf_tables_ipv4.c | 47 +++++++---------
net/ipv6/netfilter/nf_tables_ipv6.c | 52 ++++++++---------
net/netfilter/Kconfig | 8 +++
net/netfilter/Makefile | 1 +
net/netfilter/nf_tables_api.c | 53 +++++++++--------
net/netfilter/nf_tables_core.c | 2 +-
net/netfilter/nf_tables_inet.c | 97 ++++++++++++++++++++++++++++++++
net/netfilter/nft_compat.c | 8 +--
net/netfilter/nft_log.c | 2 +-
net/netfilter/nft_meta.c | 8 +++
18 files changed, 260 insertions(+), 125 deletions(-)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/6] netfilter: nf_tables: make chain types override the default AF functions
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
@ 2014-01-03 12:16 ` Patrick McHardy
2014-01-03 12:16 ` [PATCH 2/6] netfilter: nf_tables: add hook ops to struct nft_pktinfo Patrick McHardy
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-03 12:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Currently the AF-specific hook functions override the chain-type specific
hook functions. That doesn't make too much sense since the chain types
are a special case of the AF-specific hooks.
Make the AF-specific hook functions the default and make the optional
chain type hooks override them.
As a side effect, the necessary code restructuring reduces the code size,
f.i. in case of nf_tables_ipv4.o:
nf_tables_ipv4_init_net | -24
nft_do_chain_ipv4 | -113
2 functions changed, 137 bytes removed, diff: -137
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/bridge/netfilter/nf_tables_bridge.c | 38 +++++++++++++-------------
net/ipv4/netfilter/nf_tables_arp.c | 38 +++++++++++++-------------
net/ipv4/netfilter/nf_tables_ipv4.c | 43 +++++++++++++----------------
net/ipv6/netfilter/nf_tables_ipv6.c | 48 ++++++++++++++-------------------
net/netfilter/nf_tables_api.c | 10 +++----
5 files changed, 81 insertions(+), 96 deletions(-)
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index cf54b22..c5fdd9a 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -14,10 +14,29 @@
#include <linux/netfilter_bridge.h>
#include <net/netfilter/nf_tables.h>
+static unsigned int
+nft_do_chain_bridge(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct nft_pktinfo pkt;
+
+ nft_set_pktinfo(&pkt, ops, skb, in, out);
+
+ return nft_do_chain_pktinfo(&pkt, ops);
+}
+
static struct nft_af_info nft_af_bridge __read_mostly = {
.family = NFPROTO_BRIDGE,
.nhooks = NF_BR_NUMHOOKS,
.owner = THIS_MODULE,
+ .hooks = {
+ [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
+ [NF_BR_FORWARD] = nft_do_chain_bridge,
+ [NF_BR_LOCAL_OUT] = nft_do_chain_bridge,
+ },
};
static int nf_tables_bridge_init_net(struct net *net)
@@ -48,20 +67,6 @@ static struct pernet_operations nf_tables_bridge_net_ops = {
.exit = nf_tables_bridge_exit_net,
};
-static unsigned int
-nft_do_chain_bridge(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- struct nft_pktinfo pkt;
-
- nft_set_pktinfo(&pkt, ops, skb, in, out);
-
- return nft_do_chain_pktinfo(&pkt, ops);
-}
-
static struct nf_chain_type filter_bridge = {
.family = NFPROTO_BRIDGE,
.name = "filter",
@@ -69,11 +74,6 @@ static struct nf_chain_type filter_bridge = {
.hook_mask = (1 << NF_BR_LOCAL_IN) |
(1 << NF_BR_FORWARD) |
(1 << NF_BR_LOCAL_OUT),
- .fn = {
- [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
- [NF_BR_FORWARD] = nft_do_chain_bridge,
- [NF_BR_LOCAL_OUT] = nft_do_chain_bridge,
- },
};
static int __init nf_tables_bridge_init(void)
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c
index 3e67ef1..31bb778 100644
--- a/net/ipv4/netfilter/nf_tables_arp.c
+++ b/net/ipv4/netfilter/nf_tables_arp.c
@@ -14,10 +14,29 @@
#include <linux/netfilter_arp.h>
#include <net/netfilter/nf_tables.h>
+static unsigned int
+nft_do_chain_arp(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct nft_pktinfo pkt;
+
+ nft_set_pktinfo(&pkt, ops, skb, in, out);
+
+ return nft_do_chain_pktinfo(&pkt, ops);
+}
+
static struct nft_af_info nft_af_arp __read_mostly = {
.family = NFPROTO_ARP,
.nhooks = NF_ARP_NUMHOOKS,
.owner = THIS_MODULE,
+ .hooks = {
+ [NF_ARP_IN] = nft_do_chain_arp,
+ [NF_ARP_OUT] = nft_do_chain_arp,
+ [NF_ARP_FORWARD] = nft_do_chain_arp,
+ },
};
static int nf_tables_arp_init_net(struct net *net)
@@ -48,20 +67,6 @@ static struct pernet_operations nf_tables_arp_net_ops = {
.exit = nf_tables_arp_exit_net,
};
-static unsigned int
-nft_do_chain_arp(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- struct nft_pktinfo pkt;
-
- nft_set_pktinfo(&pkt, ops, skb, in, out);
-
- return nft_do_chain_pktinfo(&pkt, ops);
-}
-
static struct nf_chain_type filter_arp = {
.family = NFPROTO_ARP,
.name = "filter",
@@ -69,11 +74,6 @@ static struct nf_chain_type filter_arp = {
.hook_mask = (1 << NF_ARP_IN) |
(1 << NF_ARP_OUT) |
(1 << NF_ARP_FORWARD),
- .fn = {
- [NF_ARP_IN] = nft_do_chain_arp,
- [NF_ARP_OUT] = nft_do_chain_arp,
- [NF_ARP_FORWARD] = nft_do_chain_arp,
- },
};
static int __init nf_tables_arp_init(void)
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index 0f4cbfe..ed7e15a 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -18,14 +18,25 @@
#include <net/ip.h>
#include <net/netfilter/nf_tables_ipv4.h>
+static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct nft_pktinfo pkt;
+
+ nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
+
+ return nft_do_chain_pktinfo(&pkt, ops);
+}
+
static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct nft_pktinfo pkt;
-
if (unlikely(skb->len < sizeof(struct iphdr) ||
ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
if (net_ratelimit())
@@ -33,9 +44,8 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
"packet\n");
return NF_ACCEPT;
}
- nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
- return nft_do_chain_pktinfo(&pkt, ops);
+ return nft_do_chain_ipv4(ops, skb, in, out, okfn);
}
static struct nft_af_info nft_af_ipv4 __read_mostly = {
@@ -43,7 +53,11 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
.nhooks = NF_INET_NUMHOOKS,
.owner = THIS_MODULE,
.hooks = {
+ [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
[NF_INET_LOCAL_OUT] = nft_ipv4_output,
+ [NF_INET_FORWARD] = nft_do_chain_ipv4,
+ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
+ [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
},
};
@@ -75,20 +89,6 @@ static struct pernet_operations nf_tables_ipv4_net_ops = {
.exit = nf_tables_ipv4_exit_net,
};
-static unsigned int
-nft_do_chain_ipv4(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- struct nft_pktinfo pkt;
-
- nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
-
- return nft_do_chain_pktinfo(&pkt, ops);
-}
-
static struct nf_chain_type filter_ipv4 = {
.family = NFPROTO_IPV4,
.name = "filter",
@@ -98,13 +98,6 @@ static struct nf_chain_type filter_ipv4 = {
(1 << NF_INET_FORWARD) |
(1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_POST_ROUTING),
- .fn = {
- [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
- [NF_INET_LOCAL_OUT] = nft_ipv4_output,
- [NF_INET_FORWARD] = nft_do_chain_ipv4,
- [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
- [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
- },
};
static int __init nf_tables_ipv4_init(void)
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c
index d77db8a..54a2bcd 100644
--- a/net/ipv6/netfilter/nf_tables_ipv6.c
+++ b/net/ipv6/netfilter/nf_tables_ipv6.c
@@ -16,24 +16,35 @@
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_ipv6.h>
+static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct nft_pktinfo pkt;
+
+ /* malformed packet, drop it */
+ if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
+ return NF_DROP;
+
+ return nft_do_chain_pktinfo(&pkt, ops);
+}
+
static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct nft_pktinfo pkt;
-
if (unlikely(skb->len < sizeof(struct ipv6hdr))) {
if (net_ratelimit())
pr_info("nf_tables_ipv6: ignoring short SOCK_RAW "
"packet\n");
return NF_ACCEPT;
}
- if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
- return NF_DROP;
- return nft_do_chain_pktinfo(&pkt, ops);
+ return nft_do_chain_ipv6(ops, skb, in, out, okfn);
}
static struct nft_af_info nft_af_ipv6 __read_mostly = {
@@ -41,7 +52,11 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = {
.nhooks = NF_INET_NUMHOOKS,
.owner = THIS_MODULE,
.hooks = {
+ [NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
[NF_INET_LOCAL_OUT] = nft_ipv6_output,
+ [NF_INET_FORWARD] = nft_do_chain_ipv6,
+ [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6,
+ [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
},
};
@@ -73,22 +88,6 @@ static struct pernet_operations nf_tables_ipv6_net_ops = {
.exit = nf_tables_ipv6_exit_net,
};
-static unsigned int
-nft_do_chain_ipv6(const struct nf_hook_ops *ops,
- struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *))
-{
- struct nft_pktinfo pkt;
-
- /* malformed packet, drop it */
- if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
- return NF_DROP;
-
- return nft_do_chain_pktinfo(&pkt, ops);
-}
-
static struct nf_chain_type filter_ipv6 = {
.family = NFPROTO_IPV6,
.name = "filter",
@@ -98,13 +97,6 @@ static struct nf_chain_type filter_ipv6 = {
(1 << NF_INET_FORWARD) |
(1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_POST_ROUTING),
- .fn = {
- [NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
- [NF_INET_LOCAL_OUT] = nft_ipv6_output,
- [NF_INET_FORWARD] = nft_do_chain_ipv6,
- [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6,
- [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
- },
};
static int __init nf_tables_ipv6_init(void)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 71a9f49..0dda328 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -926,9 +926,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
if (hooknum >= afi->nhooks)
return -EINVAL;
- hookfn = chain_type[family][type]->fn[hooknum];
- if (hookfn == NULL)
+ if (!(chain_type[family][type]->hook_mask & (1 << hooknum)))
return -EOPNOTSUPP;
+ hookfn = chain_type[family][type]->fn[hooknum];
basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
if (basechain == NULL)
@@ -943,9 +943,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
ops->hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
ops->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
ops->priv = chain;
- ops->hook = hookfn;
- if (afi->hooks[ops->hooknum])
- ops->hook = afi->hooks[ops->hooknum];
+ ops->hook = afi->hooks[ops->hooknum];
+ if (hookfn)
+ ops->hook = hookfn;
chain->flags |= NFT_BASE_CHAIN;
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/6] netfilter: nf_tables: add hook ops to struct nft_pktinfo
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
2014-01-03 12:16 ` [PATCH 1/6] netfilter: nf_tables: make chain types override the default AF functions Patrick McHardy
@ 2014-01-03 12:16 ` Patrick McHardy
2014-01-03 12:16 ` [PATCH 3/6] netfilter: nf_tables: add support for multi family tables Patrick McHardy
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-03 12:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Multi-family tables need the AF from the hook ops. Add a pointer to the
hook ops and replace usage of the hooknum member in struct nft_pktinfo.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/net/netfilter/nf_tables.h | 5 +++--
net/netfilter/nf_tables_core.c | 2 +-
net/netfilter/nft_log.c | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 5a91abf..c9e6316 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -13,7 +13,7 @@ struct nft_pktinfo {
struct sk_buff *skb;
const struct net_device *in;
const struct net_device *out;
- u8 hooknum;
+ const struct nf_hook_ops *ops;
u8 nhoff;
u8 thoff;
/* for x_tables compatibility */
@@ -29,7 +29,8 @@ static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
pkt->skb = skb;
pkt->in = pkt->xt.in = in;
pkt->out = pkt->xt.out = out;
- pkt->hooknum = pkt->xt.hooknum = ops->hooknum;
+ pkt->ops = ops;
+ pkt->xt.hooknum = ops->hooknum;
pkt->xt.family = ops->pf;
}
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index cb9e685..eb6a157 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -109,7 +109,7 @@ static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
{
struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
- nf_log_packet(net, pkt->xt.family, pkt->hooknum, pkt->skb, pkt->in,
+ 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);
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 57cad07..5af7901 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -33,7 +33,7 @@ static void nft_log_eval(const struct nft_expr *expr,
const struct nft_log *priv = nft_expr_priv(expr);
struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
- nf_log_packet(net, priv->family, pkt->hooknum, pkt->skb, pkt->in,
+ nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in,
pkt->out, &priv->loginfo, "%s", priv->prefix);
}
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/6] netfilter: nf_tables: add support for multi family tables
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
2014-01-03 12:16 ` [PATCH 1/6] netfilter: nf_tables: make chain types override the default AF functions Patrick McHardy
2014-01-03 12:16 ` [PATCH 2/6] netfilter: nf_tables: add hook ops to struct nft_pktinfo Patrick McHardy
@ 2014-01-03 12:16 ` Patrick McHardy
2014-01-03 12:16 ` [PATCH 4/6] netfilter: nf_tables: add "inet" table for IPv4/IPv6 Patrick McHardy
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-03 12:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Add support to register chains to multiple hooks for different address
families for mixed IPv4/IPv6 tables.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/net/netfilter/nf_tables.h | 9 +++++-
net/bridge/netfilter/nf_tables_bridge.c | 1 +
net/ipv4/netfilter/nf_tables_arp.c | 1 +
net/ipv4/netfilter/nf_tables_ipv4.c | 1 +
net/ipv6/netfilter/nf_tables_ipv6.c | 1 +
net/netfilter/nf_tables_api.c | 49 +++++++++++++++++++--------------
net/netfilter/nft_compat.c | 8 +++---
7 files changed, 45 insertions(+), 25 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index c9e6316..f066f25 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -422,6 +422,8 @@ struct nft_stats {
u64 pkts;
};
+#define NFT_HOOK_OPS_MAX 2
+
/**
* struct nft_base_chain - nf_tables base chain
*
@@ -432,7 +434,7 @@ struct nft_stats {
* @chain: the chain
*/
struct nft_base_chain {
- struct nf_hook_ops ops;
+ struct nf_hook_ops ops[NFT_HOOK_OPS_MAX];
enum nft_chain_type type;
u8 policy;
struct nft_stats __percpu *stats;
@@ -476,6 +478,8 @@ struct nft_table {
* @nhooks: number of hooks in this family
* @owner: module owner
* @tables: used internally
+ * @nops: number of hook ops in this family
+ * @hook_ops_init: initialization function for chain hook ops
* @hooks: hookfn overrides for packet validation
*/
struct nft_af_info {
@@ -484,6 +488,9 @@ struct nft_af_info {
unsigned int nhooks;
struct module *owner;
struct list_head tables;
+ unsigned int nops;
+ void (*hook_ops_init)(struct nf_hook_ops *,
+ unsigned int);
nf_hookfn *hooks[NF_MAX_HOOKS];
};
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index c5fdd9a..003c1e9 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -32,6 +32,7 @@ static struct nft_af_info nft_af_bridge __read_mostly = {
.family = NFPROTO_BRIDGE,
.nhooks = NF_BR_NUMHOOKS,
.owner = THIS_MODULE,
+ .nops = 1,
.hooks = {
[NF_BR_LOCAL_IN] = nft_do_chain_bridge,
[NF_BR_FORWARD] = nft_do_chain_bridge,
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c
index 31bb778..36d27fc 100644
--- a/net/ipv4/netfilter/nf_tables_arp.c
+++ b/net/ipv4/netfilter/nf_tables_arp.c
@@ -32,6 +32,7 @@ static struct nft_af_info nft_af_arp __read_mostly = {
.family = NFPROTO_ARP,
.nhooks = NF_ARP_NUMHOOKS,
.owner = THIS_MODULE,
+ .nops = 1,
.hooks = {
[NF_ARP_IN] = nft_do_chain_arp,
[NF_ARP_OUT] = nft_do_chain_arp,
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index ed7e15a..177c3bc 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -52,6 +52,7 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
.family = NFPROTO_IPV4,
.nhooks = NF_INET_NUMHOOKS,
.owner = THIS_MODULE,
+ .nops = 1,
.hooks = {
[NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
[NF_INET_LOCAL_OUT] = nft_ipv4_output,
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c
index 54a2bcd..642280e 100644
--- a/net/ipv6/netfilter/nf_tables_ipv6.c
+++ b/net/ipv6/netfilter/nf_tables_ipv6.c
@@ -51,6 +51,7 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = {
.family = NFPROTO_IPV6,
.nhooks = NF_INET_NUMHOOKS,
.owner = THIS_MODULE,
+ .nops = 1,
.hooks = {
[NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
[NF_INET_LOCAL_OUT] = nft_ipv6_output,
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 0dda328..e4c4089 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -306,7 +306,8 @@ err:
return err;
}
-static int nf_tables_table_enable(struct nft_table *table)
+static int nf_tables_table_enable(const struct nft_af_info *afi,
+ struct nft_table *table)
{
struct nft_chain *chain;
int err, i = 0;
@@ -315,7 +316,7 @@ static int nf_tables_table_enable(struct nft_table *table)
if (!(chain->flags & NFT_BASE_CHAIN))
continue;
- err = nf_register_hook(&nft_base_chain(chain)->ops);
+ err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
if (err < 0)
goto err;
@@ -330,18 +331,20 @@ err:
if (i-- <= 0)
break;
- nf_unregister_hook(&nft_base_chain(chain)->ops);
+ nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops);
}
return err;
}
-static int nf_tables_table_disable(struct nft_table *table)
+static int nf_tables_table_disable(const struct nft_af_info *afi,
+ struct nft_table *table)
{
struct nft_chain *chain;
list_for_each_entry(chain, &table->chains, list) {
if (chain->flags & NFT_BASE_CHAIN)
- nf_unregister_hook(&nft_base_chain(chain)->ops);
+ nf_unregister_hooks(nft_base_chain(chain)->ops,
+ afi->nops);
}
return 0;
@@ -364,12 +367,12 @@ static int nf_tables_updtable(struct sock *nlsk, struct sk_buff *skb,
if ((flags & NFT_TABLE_F_DORMANT) &&
!(table->flags & NFT_TABLE_F_DORMANT)) {
- ret = nf_tables_table_disable(table);
+ ret = nf_tables_table_disable(afi, table);
if (ret >= 0)
table->flags |= NFT_TABLE_F_DORMANT;
} else if (!(flags & NFT_TABLE_F_DORMANT) &&
table->flags & NFT_TABLE_F_DORMANT) {
- ret = nf_tables_table_enable(table);
+ ret = nf_tables_table_enable(afi, table);
if (ret >= 0)
table->flags &= ~NFT_TABLE_F_DORMANT;
}
@@ -597,7 +600,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq,
if (chain->flags & NFT_BASE_CHAIN) {
const struct nft_base_chain *basechain = nft_base_chain(chain);
- const struct nf_hook_ops *ops = &basechain->ops;
+ const struct nf_hook_ops *ops = &basechain->ops[0];
struct nlattr *nest;
nest = nla_nest_start(skb, NFTA_CHAIN_HOOK);
@@ -831,6 +834,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
struct net *net = sock_net(skb->sk);
int family = nfmsg->nfgen_family;
u64 handle = 0;
+ unsigned int i;
int err;
bool create;
@@ -903,7 +907,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
if (nla[NFTA_CHAIN_HOOK]) {
struct nf_hook_ops *ops;
nf_hookfn *hookfn;
- u32 hooknum;
+ u32 hooknum, priority;
int type = NFT_CHAIN_T_DEFAULT;
if (nla[NFTA_CHAIN_TYPE]) {
@@ -925,6 +929,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
if (hooknum >= afi->nhooks)
return -EINVAL;
+ priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
if (!(chain_type[family][type]->hook_mask & (1 << hooknum)))
return -EOPNOTSUPP;
@@ -937,15 +942,19 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
basechain->type = type;
chain = &basechain->chain;
- ops = &basechain->ops;
- ops->pf = family;
- ops->owner = afi->owner;
- ops->hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
- ops->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
- ops->priv = chain;
- ops->hook = afi->hooks[ops->hooknum];
- if (hookfn)
- ops->hook = hookfn;
+ for (i = 0; i < afi->nops; i++) {
+ ops = &basechain->ops[i];
+ ops->pf = family;
+ ops->owner = afi->owner;
+ ops->hooknum = hooknum;
+ ops->priority = priority;
+ ops->priv = chain;
+ ops->hook = afi->hooks[ops->hooknum];
+ if (hookfn)
+ ops->hook = hookfn;
+ if (afi->hook_ops_init)
+ afi->hook_ops_init(ops, i);
+ }
chain->flags |= NFT_BASE_CHAIN;
@@ -992,7 +1001,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
if (!(table->flags & NFT_TABLE_F_DORMANT) &&
chain->flags & NFT_BASE_CHAIN) {
- err = nf_register_hook(&nft_base_chain(chain)->ops);
+ err = nf_register_hooks(nft_base_chain(chain)->ops, afi->nops);
if (err < 0) {
free_percpu(basechain->stats);
kfree(basechain);
@@ -1051,7 +1060,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
if (!(table->flags & NFT_TABLE_F_DORMANT) &&
chain->flags & NFT_BASE_CHAIN)
- nf_unregister_hook(&nft_base_chain(chain)->ops);
+ nf_unregister_hooks(nft_base_chain(chain)->ops, afi->nops);
nf_tables_chain_notify(skb, nlh, table, chain, NFT_MSG_DELCHAIN,
family);
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index da0c1f4..82cb823 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -92,7 +92,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
if (ctx->chain->flags & NFT_BASE_CHAIN) {
const struct nft_base_chain *basechain =
nft_base_chain(ctx->chain);
- const struct nf_hook_ops *ops = &basechain->ops;
+ const struct nf_hook_ops *ops = &basechain->ops[0];
par->hook_mask = 1 << ops->hooknum;
}
@@ -253,7 +253,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
if (ctx->chain->flags & NFT_BASE_CHAIN) {
const struct nft_base_chain *basechain =
nft_base_chain(ctx->chain);
- const struct nf_hook_ops *ops = &basechain->ops;
+ const struct nf_hook_ops *ops = &basechain->ops[0];
hook_mask = 1 << ops->hooknum;
if (hook_mask & target->hooks)
@@ -323,7 +323,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
if (ctx->chain->flags & NFT_BASE_CHAIN) {
const struct nft_base_chain *basechain =
nft_base_chain(ctx->chain);
- const struct nf_hook_ops *ops = &basechain->ops;
+ const struct nf_hook_ops *ops = &basechain->ops[0];
par->hook_mask = 1 << ops->hooknum;
}
@@ -449,7 +449,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
if (ctx->chain->flags & NFT_BASE_CHAIN) {
const struct nft_base_chain *basechain =
nft_base_chain(ctx->chain);
- const struct nf_hook_ops *ops = &basechain->ops;
+ const struct nf_hook_ops *ops = &basechain->ops[0];
hook_mask = 1 << ops->hooknum;
if (hook_mask & match->hooks)
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/6] netfilter: nf_tables: add "inet" table for IPv4/IPv6
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
` (2 preceding siblings ...)
2014-01-03 12:16 ` [PATCH 3/6] netfilter: nf_tables: add support for multi family tables Patrick McHardy
@ 2014-01-03 12:16 ` Patrick McHardy
2014-01-03 12:16 ` [PATCH 5/6] netfilter: nf_tables: add nfproto support to meta expression Patrick McHardy
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-03 12:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/net/netfilter/nf_tables_ipv4.h | 2 +
include/net/netfilter/nf_tables_ipv6.h | 2 +
include/net/netns/nftables.h | 1 +
include/uapi/linux/netfilter.h | 1 +
net/ipv4/netfilter/nf_tables_ipv4.c | 3 +-
net/ipv6/netfilter/nf_tables_ipv6.c | 3 +-
net/netfilter/Kconfig | 8 +++
net/netfilter/Makefile | 1 +
net/netfilter/nf_tables_inet.c | 97 ++++++++++++++++++++++++++++++++++
9 files changed, 116 insertions(+), 2 deletions(-)
create mode 100644 net/netfilter/nf_tables_inet.c
diff --git a/include/net/netfilter/nf_tables_ipv4.h b/include/net/netfilter/nf_tables_ipv4.h
index 1be1c2c..f7b3a66 100644
--- a/include/net/netfilter/nf_tables_ipv4.h
+++ b/include/net/netfilter/nf_tables_ipv4.h
@@ -20,4 +20,6 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
}
+extern struct nft_af_info nft_af_ipv4;
+
#endif
diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h
index 4a9b88a..3d8ae48 100644
--- a/include/net/netfilter/nf_tables_ipv6.h
+++ b/include/net/netfilter/nf_tables_ipv6.h
@@ -27,4 +27,6 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
return 0;
}
+extern struct nft_af_info nft_af_ipv6;
+
#endif
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
index 15d056d..26a394c 100644
--- a/include/net/netns/nftables.h
+++ b/include/net/netns/nftables.h
@@ -10,6 +10,7 @@ struct netns_nftables {
struct list_head commit_list;
struct nft_af_info *ipv4;
struct nft_af_info *ipv6;
+ struct nft_af_info *inet;
struct nft_af_info *arp;
struct nft_af_info *bridge;
u8 gencursor;
diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h
index f7dc0eb..ef1b1f8 100644
--- a/include/uapi/linux/netfilter.h
+++ b/include/uapi/linux/netfilter.h
@@ -53,6 +53,7 @@ enum nf_inet_hooks {
enum {
NFPROTO_UNSPEC = 0,
+ NFPROTO_INET = 1,
NFPROTO_IPV4 = 2,
NFPROTO_ARP = 3,
NFPROTO_BRIDGE = 7,
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index 177c3bc..da927dc 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -48,7 +48,7 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
return nft_do_chain_ipv4(ops, skb, in, out, okfn);
}
-static struct nft_af_info nft_af_ipv4 __read_mostly = {
+struct nft_af_info nft_af_ipv4 __read_mostly = {
.family = NFPROTO_IPV4,
.nhooks = NF_INET_NUMHOOKS,
.owner = THIS_MODULE,
@@ -61,6 +61,7 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
[NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
},
};
+EXPORT_SYMBOL_GPL(nft_af_ipv4);
static int nf_tables_ipv4_init_net(struct net *net)
{
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c
index 642280e..025e7f4 100644
--- a/net/ipv6/netfilter/nf_tables_ipv6.c
+++ b/net/ipv6/netfilter/nf_tables_ipv6.c
@@ -47,7 +47,7 @@ static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops,
return nft_do_chain_ipv6(ops, skb, in, out, okfn);
}
-static struct nft_af_info nft_af_ipv6 __read_mostly = {
+struct nft_af_info nft_af_ipv6 __read_mostly = {
.family = NFPROTO_IPV6,
.nhooks = NF_INET_NUMHOOKS,
.owner = THIS_MODULE,
@@ -60,6 +60,7 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = {
[NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
},
};
+EXPORT_SYMBOL_GPL(nft_af_ipv6);
static int nf_tables_ipv6_init_net(struct net *net)
{
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index c3398cd..bd93136 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -417,6 +417,14 @@ config NF_TABLES
depends on NETFILTER_NETLINK
tristate "Netfilter nf_tables support"
+config NF_TABLES_INET
+ depends on NF_TABLES
+ select NF_TABLES_IPV4
+ select NF_TABLES_IPV6
+ tristate "Netfilter nf_tables mixed IPv4/IPv6 tables support"
+ help
+ This option enables support for a mixed IPv4/IPv6 "inet" table.
+
config NFT_EXTHDR
depends on NF_TABLES
tristate "Netfilter nf_tables IPv6 exthdr module"
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 394483b..017da0b 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -70,6 +70,7 @@ nf_tables-objs += nft_immediate.o nft_cmp.o nft_lookup.o
nf_tables-objs += nft_bitwise.o nft_byteorder.o nft_payload.o
obj-$(CONFIG_NF_TABLES) += nf_tables.o
+obj-$(CONFIG_NF_TABLES_INET) += nf_tables_inet.o
obj-$(CONFIG_NFT_COMPAT) += nft_compat.o
obj-$(CONFIG_NFT_EXTHDR) += nft_exthdr.o
obj-$(CONFIG_NFT_META) += nft_meta.o
diff --git a/net/netfilter/nf_tables_inet.c b/net/netfilter/nf_tables_inet.c
new file mode 100644
index 0000000..ac0edcb
--- /dev/null
+++ b/net/netfilter/nf_tables_inet.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012-2014 Patrick McHardy <kaber@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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/nf_tables.h>
+#include <net/netfilter/nf_tables_ipv4.h>
+#include <net/netfilter/nf_tables_ipv6.h>
+#include <net/ip.h>
+
+static void nft_inet_hook_ops_init(struct nf_hook_ops *ops, unsigned int n)
+{
+ struct nft_af_info *afi;
+
+ if (n == 1)
+ afi = &nft_af_ipv4;
+ else
+ afi = &nft_af_ipv6;
+
+ ops->pf = afi->family;
+ if (afi->hooks[ops->hooknum])
+ ops->hook = afi->hooks[ops->hooknum];
+}
+
+static struct nft_af_info nft_af_inet __read_mostly = {
+ .family = NFPROTO_INET,
+ .nhooks = NF_INET_NUMHOOKS,
+ .owner = THIS_MODULE,
+ .nops = 2,
+ .hook_ops_init = nft_inet_hook_ops_init,
+};
+
+static int __net_init nf_tables_inet_init_net(struct net *net)
+{
+ net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
+ if (net->nft.inet == NULL)
+ return -ENOMEM;
+ memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet));
+
+ if (nft_register_afinfo(net, net->nft.inet) < 0)
+ goto err;
+
+ return 0;
+
+err:
+ kfree(net->nft.inet);
+ return -ENOMEM;
+}
+
+static void __net_exit nf_tables_inet_exit_net(struct net *net)
+{
+ nft_unregister_afinfo(net->nft.inet);
+ kfree(net->nft.inet);
+}
+
+static struct pernet_operations nf_tables_inet_net_ops = {
+ .init = nf_tables_inet_init_net,
+ .exit = nf_tables_inet_exit_net,
+};
+
+static struct nf_chain_type filter_inet = {
+ .family = NFPROTO_INET,
+ .name = "filter",
+ .type = NFT_CHAIN_T_DEFAULT,
+ .hook_mask = (1 << NF_INET_LOCAL_IN) |
+ (1 << NF_INET_LOCAL_OUT) |
+ (1 << NF_INET_FORWARD) |
+ (1 << NF_INET_PRE_ROUTING) |
+ (1 << NF_INET_POST_ROUTING),
+};
+
+static int __init nf_tables_inet_init(void)
+{
+ nft_register_chain_type(&filter_inet);
+ return register_pernet_subsys(&nf_tables_inet_net_ops);
+}
+
+static void __exit nf_tables_inet_exit(void)
+{
+ unregister_pernet_subsys(&nf_tables_inet_net_ops);
+ nft_unregister_chain_type(&filter_inet);
+}
+
+module_init(nf_tables_inet_init);
+module_exit(nf_tables_inet_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_ALIAS_NFT_FAMILY(1);
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/6] netfilter: nf_tables: add nfproto support to meta expression
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
` (3 preceding siblings ...)
2014-01-03 12:16 ` [PATCH 4/6] netfilter: nf_tables: add "inet" table for IPv4/IPv6 Patrick McHardy
@ 2014-01-03 12:16 ` Patrick McHardy
2014-01-03 12:16 ` [PATCH 6/6] netfilter: nft_meta: add l4proto support Patrick McHardy
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-03 12:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Needed by multi-family tables to distinguish IPv4 and IPv6 packets.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/uapi/linux/netfilter/nf_tables.h | 2 ++
net/netfilter/nft_meta.c | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index fbfd229..7ec92a9 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -529,6 +529,7 @@ enum nft_exthdr_attributes {
* @NFT_META_NFTRACE: packet nftrace bit
* @NFT_META_RTCLASSID: realm value of packet's route (skb->dst->tclassid)
* @NFT_META_SECMARK: packet secmark (skb->secmark)
+ * @NFT_META_NFPROTO: netfilter protocol
*/
enum nft_meta_keys {
NFT_META_LEN,
@@ -546,6 +547,7 @@ enum nft_meta_keys {
NFT_META_NFTRACE,
NFT_META_RTCLASSID,
NFT_META_SECMARK,
+ NFT_META_NFPROTO,
};
/**
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 8c28220..06a4f30 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -40,6 +40,9 @@ static void nft_meta_eval(const struct nft_expr *expr,
case NFT_META_PROTOCOL:
*(__be16 *)dest->data = skb->protocol;
break;
+ case NFT_META_NFPROTO:
+ dest->data[0] = pkt->ops->pf;
+ break;
case NFT_META_PRIORITY:
dest->data[0] = skb->priority;
break;
@@ -151,6 +154,7 @@ static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
switch (priv->key) {
case NFT_META_LEN:
case NFT_META_PROTOCOL:
+ case NFT_META_NFPROTO:
case NFT_META_PRIORITY:
case NFT_META_MARK:
case NFT_META_IIF:
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/6] netfilter: nft_meta: add l4proto support
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
` (4 preceding siblings ...)
2014-01-03 12:16 ` [PATCH 5/6] netfilter: nf_tables: add nfproto support to meta expression Patrick McHardy
@ 2014-01-03 12:16 ` Patrick McHardy
2014-01-05 20:39 ` [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Pablo Neira Ayuso
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-03 12:16 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
For L3-proto independant rules we need to get at the L4 protocol value
directly. Add it to the nft_pktinfo struct and use the meta expression
to retrieve it.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/net/netfilter/nf_tables.h | 1 +
include/net/netfilter/nf_tables_ipv4.h | 3 ++-
include/net/netfilter/nf_tables_ipv6.h | 1 +
include/uapi/linux/netfilter/nf_tables.h | 2 ++
net/netfilter/nft_meta.c | 4 ++++
5 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index f066f25..5d2b703 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -16,6 +16,7 @@ struct nft_pktinfo {
const struct nf_hook_ops *ops;
u8 nhoff;
u8 thoff;
+ u8 tprot;
/* for x_tables compatibility */
struct xt_action_param xt;
};
diff --git a/include/net/netfilter/nf_tables_ipv4.h b/include/net/netfilter/nf_tables_ipv4.h
index f7b3a66..cba143f 100644
--- a/include/net/netfilter/nf_tables_ipv4.h
+++ b/include/net/netfilter/nf_tables_ipv4.h
@@ -15,8 +15,9 @@ nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
nft_set_pktinfo(pkt, ops, skb, in, out);
- pkt->xt.thoff = ip_hdrlen(pkt->skb);
ip = ip_hdr(pkt->skb);
+ pkt->tprot = ip->protocol;
+ pkt->xt.thoff = ip_hdrlen(pkt->skb);
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
}
diff --git a/include/net/netfilter/nf_tables_ipv6.h b/include/net/netfilter/nf_tables_ipv6.h
index 3d8ae48..74d9761 100644
--- a/include/net/netfilter/nf_tables_ipv6.h
+++ b/include/net/netfilter/nf_tables_ipv6.h
@@ -21,6 +21,7 @@ nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
if (protohdr < 0)
return -1;
+ pkt->tprot = protohdr;
pkt->xt.thoff = thoff;
pkt->xt.fragoff = frag_off;
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 7ec92a9..d557a2c 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -530,6 +530,7 @@ enum nft_exthdr_attributes {
* @NFT_META_RTCLASSID: realm value of packet's route (skb->dst->tclassid)
* @NFT_META_SECMARK: packet secmark (skb->secmark)
* @NFT_META_NFPROTO: netfilter protocol
+ * @NFT_META_L4PROTO: layer 4 protocol number
*/
enum nft_meta_keys {
NFT_META_LEN,
@@ -548,6 +549,7 @@ enum nft_meta_keys {
NFT_META_RTCLASSID,
NFT_META_SECMARK,
NFT_META_NFPROTO,
+ NFT_META_L4PROTO,
};
/**
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 06a4f30..62d8de3 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -43,6 +43,9 @@ static void nft_meta_eval(const struct nft_expr *expr,
case NFT_META_NFPROTO:
dest->data[0] = pkt->ops->pf;
break;
+ case NFT_META_L4PROTO:
+ dest->data[0] = pkt->tprot;
+ break;
case NFT_META_PRIORITY:
dest->data[0] = skb->priority;
break;
@@ -155,6 +158,7 @@ static int nft_meta_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
case NFT_META_LEN:
case NFT_META_PROTOCOL:
case NFT_META_NFPROTO:
+ case NFT_META_L4PROTO:
case NFT_META_PRIORITY:
case NFT_META_MARK:
case NFT_META_IIF:
--
1.8.4.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
` (5 preceding siblings ...)
2014-01-03 12:16 ` [PATCH 6/6] netfilter: nft_meta: add l4proto support Patrick McHardy
@ 2014-01-05 20:39 ` Pablo Neira Ayuso
2014-01-05 21:02 ` Patrick McHardy
2014-01-06 18:09 ` [PATCH 7/6] netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET Patrick McHardy
2014-01-07 23:03 ` [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Pablo Neira Ayuso
8 siblings, 1 reply; 12+ messages in thread
From: Pablo Neira Ayuso @ 2014-01-05 20:39 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel
Hi Patrick!
On Fri, Jan 03, 2014 at 12:16:12PM +0000, Patrick McHardy wrote:
> The following patches add support for mixed IPv4/IPv6 tables to nftables.
>
> The first patch fixes the chain type override logic so chain types override
> the AF defaults instead of the other way around. The second patch adds a
> pointer to the nf_hook_ops struct to nft_pktinfo for a later patch which
> uses ops->pf to match the actual AF of the packet instead of the dummy
> NFPROTO_INET value. The third patch changes the chain and hook registration
> logic to support multiple hook registrations. The nf_tables AF modules can
> provide a callback function to override defaults. The fourth patch finally
> adds a new "inet" family, which basically only initializes the hook
> functions to the IPv4 and IPv6 specific ones and registers a dummy filter
> chain type for NFPROTO_INET. Patches 5 and 6 add support for matching on
> the netfilter hook family and the L4 protocol number to the meta match.
>
> With all this in place, we can create AF-specific rules and AF-independant
> rules that only match on the L4 protocol header and above in the inet table:
>
> table inet filter {
> chain input {
> type filter hook input priority 0;
> }
>
> chain forward {
> type filter hook forward priority 0;
> }
>
> chain output {
> type filter hook output priority 0;
> ip protocol tcp tcp dport 1234 counter packets 2 bytes 120
> ip6 nexthdr tcp tcp dport 1234 counter packets 2 bytes 160
> tcp dport 1234 counter packets 4 bytes 280
> }
> }
>
> Userspace needs a bit of polishing but will most likely follow in a few
> hours.
>
> Comments welcome.
This patchset looks pretty good, I think there is some clashing with
recent Arturo's work to set meta information, please see this patch.
http://git.kernel.org/cgit/linux/kernel/git/pablo/nftables.git/commit/?id=e035b77ac7be430a5fef8c9c23f60b6b50ec81c5
But that I can manually resolve that.
We'll also need route and mangle chains for the new inet family type,
but that's also easy to add.
Let me know if I can give you a hand with the userspace patch, you can
post a tentative RFC before polishing if you like.
Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support
2014-01-05 20:39 ` [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Pablo Neira Ayuso
@ 2014-01-05 21:02 ` Patrick McHardy
0 siblings, 0 replies; 12+ messages in thread
From: Patrick McHardy @ 2014-01-05 21:02 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: netfilter-devel
On Sun, Jan 05, 2014 at 09:39:25PM +0100, Pablo Neira Ayuso wrote:
> Hi Patrick!
>
> On Fri, Jan 03, 2014 at 12:16:12PM +0000, Patrick McHardy wrote:
> > The following patches add support for mixed IPv4/IPv6 tables to nftables.
> >
> > The first patch fixes the chain type override logic so chain types override
> > the AF defaults instead of the other way around. The second patch adds a
> > pointer to the nf_hook_ops struct to nft_pktinfo for a later patch which
> > uses ops->pf to match the actual AF of the packet instead of the dummy
> > NFPROTO_INET value. The third patch changes the chain and hook registration
> > logic to support multiple hook registrations. The nf_tables AF modules can
> > provide a callback function to override defaults. The fourth patch finally
> > adds a new "inet" family, which basically only initializes the hook
> > functions to the IPv4 and IPv6 specific ones and registers a dummy filter
> > chain type for NFPROTO_INET. Patches 5 and 6 add support for matching on
> > the netfilter hook family and the L4 protocol number to the meta match.
> >
> > With all this in place, we can create AF-specific rules and AF-independant
> > rules that only match on the L4 protocol header and above in the inet table:
> >
> > table inet filter {
> > chain input {
> > type filter hook input priority 0;
> > }
> >
> > chain forward {
> > type filter hook forward priority 0;
> > }
> >
> > chain output {
> > type filter hook output priority 0;
> > ip protocol tcp tcp dport 1234 counter packets 2 bytes 120
> > ip6 nexthdr tcp tcp dport 1234 counter packets 2 bytes 160
> > tcp dport 1234 counter packets 4 bytes 280
> > }
> > }
> >
> > Userspace needs a bit of polishing but will most likely follow in a few
> > hours.
> >
> > Comments welcome.
>
> This patchset looks pretty good, I think there is some clashing with
> recent Arturo's work to set meta information, please see this patch.
>
> http://git.kernel.org/cgit/linux/kernel/git/pablo/nftables.git/commit/?id=e035b77ac7be430a5fef8c9c23f60b6b50ec81c5
>
> But that I can manually resolve that.
>
> We'll also need route and mangle chains for the new inet family type,
> but that's also easy to add.
Well, route is certainly fine. If you mean nat (we don't have mangle),
I'll leave that to the future since the AF-specific stuff still needs a
bit of thought.
> Let me know if I can give you a hand with the userspace patch, you can
> post a tentative RFC before polishing if you like.
Actually its already finished, I just generalized it a bit to solve a
couple of related problems wrt. protocol contexts. Final patchsets will
come tommorrow.
Cheers,
Patrick
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 7/6] netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
` (6 preceding siblings ...)
2014-01-05 20:39 ` [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Pablo Neira Ayuso
@ 2014-01-06 18:09 ` Patrick McHardy
2014-01-07 23:03 ` Pablo Neira Ayuso
2014-01-07 23:03 ` [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Pablo Neira Ayuso
8 siblings, 1 reply; 12+ messages in thread
From: Patrick McHardy @ 2014-01-06 18:09 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
commit 71bcc5bde767f1a6da04391b0d9595f30e3f720b
Author: Patrick McHardy <kaber@trash.net>
Date: Mon Jan 6 17:58:02 2014 +0000
netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET
The ct expression can currently not be used in the inet family since
we don't have a conntrack module for NFPROTO_INET, so
nf_ct_l3proto_try_module_get() fails. Add some manual handling to
load the modules for both NFPROTO_IPV4 and NFPROTO_IPV6 if the
ct expression is used in the inet family.
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 955f4e6..78bf57c 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -129,6 +129,39 @@ static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = {
[NFTA_CT_DIRECTION] = { .type = NLA_U8 },
};
+static int nft_ct_l3proto_try_module_get(uint8_t family)
+{
+ int err;
+
+ if (family == NFPROTO_INET) {
+ err = nf_ct_l3proto_try_module_get(NFPROTO_IPV4);
+ if (err < 0)
+ goto err1;
+ err = nf_ct_l3proto_try_module_get(NFPROTO_IPV6);
+ if (err < 0)
+ goto err2;
+ } else {
+ err = nf_ct_l3proto_try_module_get(family);
+ if (err < 0)
+ goto err1;
+ }
+ return 0;
+
+err2:
+ nf_ct_l3proto_module_put(NFPROTO_IPV4);
+err1:
+ return err;
+}
+
+static void nft_ct_l3proto_module_put(uint8_t family)
+{
+ if (family == NFPROTO_INET) {
+ nf_ct_l3proto_module_put(NFPROTO_IPV4);
+ nf_ct_l3proto_module_put(NFPROTO_IPV6);
+ } else
+ nf_ct_l3proto_module_put(family);
+}
+
static int nft_ct_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
@@ -179,7 +212,7 @@ static int nft_ct_init(const struct nft_ctx *ctx,
return -EOPNOTSUPP;
}
- err = nf_ct_l3proto_try_module_get(ctx->afi->family);
+ err = nft_ct_l3proto_try_module_get(ctx->afi->family);
if (err < 0)
return err;
priv->family = ctx->afi->family;
@@ -195,7 +228,7 @@ static int nft_ct_init(const struct nft_ctx *ctx,
return 0;
err1:
- nf_ct_l3proto_module_put(ctx->afi->family);
+ nft_ct_l3proto_module_put(ctx->afi->family);
return err;
}
@@ -203,7 +236,7 @@ static void nft_ct_destroy(const struct nft_expr *expr)
{
struct nft_ct *priv = nft_expr_priv(expr);
- nf_ct_l3proto_module_put(priv->family);
+ nft_ct_l3proto_module_put(priv->family);
}
static int nft_ct_dump(struct sk_buff *skb, const struct nft_expr *expr)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
` (7 preceding siblings ...)
2014-01-06 18:09 ` [PATCH 7/6] netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET Patrick McHardy
@ 2014-01-07 23:03 ` Pablo Neira Ayuso
8 siblings, 0 replies; 12+ messages in thread
From: Pablo Neira Ayuso @ 2014-01-07 23:03 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel
On Fri, Jan 03, 2014 at 12:16:12PM +0000, Patrick McHardy wrote:
> The following patches add support for mixed IPv4/IPv6 tables to nftables.
>
> The first patch fixes the chain type override logic so chain types override
> the AF defaults instead of the other way around. The second patch adds a
> pointer to the nf_hook_ops struct to nft_pktinfo for a later patch which
> uses ops->pf to match the actual AF of the packet instead of the dummy
> NFPROTO_INET value. The third patch changes the chain and hook registration
> logic to support multiple hook registrations. The nf_tables AF modules can
> provide a callback function to override defaults. The fourth patch finally
> adds a new "inet" family, which basically only initializes the hook
> functions to the IPv4 and IPv6 specific ones and registers a dummy filter
> chain type for NFPROTO_INET. Patches 5 and 6 add support for matching on
> the netfilter hook family and the L4 protocol number to the meta match.
>
> With all this in place, we can create AF-specific rules and AF-independant
> rules that only match on the L4 protocol header and above in the inet table:
>
> table inet filter {
> chain input {
> type filter hook input priority 0;
> }
>
> chain forward {
> type filter hook forward priority 0;
> }
>
> chain output {
> type filter hook output priority 0;
> ip protocol tcp tcp dport 1234 counter packets 2 bytes 120
> ip6 nexthdr tcp tcp dport 1234 counter packets 2 bytes 160
> tcp dport 1234 counter packets 4 bytes 280
> }
> }
>
> Userspace needs a bit of polishing but will most likely follow in a few
> hours.
Series applied, thanks Patrick!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 7/6] netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET
2014-01-06 18:09 ` [PATCH 7/6] netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET Patrick McHardy
@ 2014-01-07 23:03 ` Pablo Neira Ayuso
0 siblings, 0 replies; 12+ messages in thread
From: Pablo Neira Ayuso @ 2014-01-07 23:03 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel
On Mon, Jan 06, 2014 at 06:09:49PM +0000, Patrick McHardy wrote:
> commit 71bcc5bde767f1a6da04391b0d9595f30e3f720b
> Author: Patrick McHardy <kaber@trash.net>
> Date: Mon Jan 6 17:58:02 2014 +0000
>
> netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET
>
> The ct expression can currently not be used in the inet family since
> we don't have a conntrack module for NFPROTO_INET, so
> nf_ct_l3proto_try_module_get() fails. Add some manual handling to
> load the modules for both NFPROTO_IPV4 and NFPROTO_IPV6 if the
> ct expression is used in the inet family.
Applied, thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-01-07 23:03 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-03 12:16 [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Patrick McHardy
2014-01-03 12:16 ` [PATCH 1/6] netfilter: nf_tables: make chain types override the default AF functions Patrick McHardy
2014-01-03 12:16 ` [PATCH 2/6] netfilter: nf_tables: add hook ops to struct nft_pktinfo Patrick McHardy
2014-01-03 12:16 ` [PATCH 3/6] netfilter: nf_tables: add support for multi family tables Patrick McHardy
2014-01-03 12:16 ` [PATCH 4/6] netfilter: nf_tables: add "inet" table for IPv4/IPv6 Patrick McHardy
2014-01-03 12:16 ` [PATCH 5/6] netfilter: nf_tables: add nfproto support to meta expression Patrick McHardy
2014-01-03 12:16 ` [PATCH 6/6] netfilter: nft_meta: add l4proto support Patrick McHardy
2014-01-05 20:39 ` [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Pablo Neira Ayuso
2014-01-05 21:02 ` Patrick McHardy
2014-01-06 18:09 ` [PATCH 7/6] netfilter: nft_ct: load both IPv4 and IPv6 conntrack modules for NFPROTO_INET Patrick McHardy
2014-01-07 23:03 ` Pablo Neira Ayuso
2014-01-07 23:03 ` [RFC PATCH 0/6] netfilter: nf_tables: add mixed IPv4/IPv6 table support Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).