* [PATCH 20/31] netns ct: NOTRACK in netns
@ 2008-07-21 16:50 Alexey Dobriyan
2008-07-21 17:05 ` Jan Engelhardt
0 siblings, 1 reply; 3+ messages in thread
From: Alexey Dobriyan @ 2008-07-21 16:50 UTC (permalink / raw)
To: kaber
Cc: netdev, netfilter-devel, dev, xemul, ebiederm, dlezcano,
benjamin.thery
Make untracked conntrack per-netns. Compare conntracks with untracked
one in relevant netns.
The following code may looks funny (sort-of self-referential):
if (ct == ct->ct_net->ct.untracked)
...
but, but, given that ->ct_net is set in only one place and is never
overwritten later, it's should be fine actually.
All of this requires some surgery with headers, otherwise circular
dependencies. For that we also lose nf_ct_is_untracked() as function
and make it macro.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
---
include/linux/netfilter/x_tables.h | 4 ++--
include/net/netfilter/nf_conntrack.h | 9 ++-------
include/net/netns/conntrack.h | 3 +++
net/ipv4/netfilter/arptable_filter.c | 1 +
net/ipv4/netfilter/nf_nat_core.c | 2 +-
net/ipv4/netfilter/nf_nat_standalone.c | 2 +-
net/netfilter/nf_conntrack_core.c | 13 +++++--------
net/netfilter/nf_conntrack_netlink.c | 3 ++-
net/netfilter/xt_NOTRACK.c | 3 ++-
net/netfilter/xt_conntrack.c | 4 ++--
net/netfilter/xt_state.c | 3 ++-
11 files changed, 23 insertions(+), 24 deletions(-)
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -171,7 +171,7 @@ struct xt_counters_info
#ifdef __KERNEL__
-#include <linux/netdevice.h>
+struct net_device;
struct xt_match
{
@@ -295,7 +295,7 @@ struct xt_table
int af; /* address/protocol family */
};
-#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter.h>
/* The table itself */
struct xt_table_info
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -262,9 +262,6 @@ extern void nf_conntrack_tcp_update(const struct sk_buff *skb,
struct nf_conn *ct,
int dir);
-/* Fake conntrack entry for untracked connections */
-extern struct nf_conn nf_conntrack_untracked;
-
/* Iterate over all conntracks: if iter returns true, it's deleted. */
extern void
nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data);
@@ -286,10 +283,8 @@ static inline int nf_ct_is_dying(struct nf_conn *ct)
return test_bit(IPS_DYING_BIT, &ct->status);
}
-static inline int nf_ct_is_untracked(const struct sk_buff *skb)
-{
- return (skb->nfct == &nf_conntrack_untracked.ct_general);
-}
+#define nf_ct_is_untracked(net, skb) \
+ ((skb)->nfct == &(net)->ct.untracked.ct_general)
extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
extern unsigned int nf_conntrack_htable_size;
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -3,6 +3,7 @@
#include <linux/list.h>
#include <asm/atomic.h>
+#include <net/netfilter/nf_conntrack.h>
struct netns_ct {
atomic_t count;
@@ -12,5 +13,7 @@ struct netns_ct {
struct hlist_head *expect_hash;
int expect_vmalloc;
struct hlist_head unconfirmed;
+ /* Fake conntrack entry for untracked connections */
+ struct nf_conn untracked;
};
#endif
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -6,6 +6,7 @@
*/
#include <linux/module.h>
+#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_arp/arp_tables.h>
MODULE_LICENSE("GPL");
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -616,7 +616,7 @@ static int __init nf_nat_init(void)
spin_unlock_bh(&nf_nat_lock);
/* Initialize fake conntrack so that NAT will skip it */
- nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
+ init_net.ct.untracked.status |= IPS_NAT_DONE_MASK;
l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -97,7 +97,7 @@ nf_nat_fn(unsigned int hooknum,
return NF_ACCEPT;
/* Don't try to NAT if this packet is not conntracked */
- if (ct == &nf_conntrack_untracked)
+ if (ct == &nf_ct_net(ct)->ct.untracked)
return NF_ACCEPT;
nat = nfct_nat(ct);
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -49,9 +49,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
int nf_conntrack_max __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_max);
-struct nf_conn nf_conntrack_untracked __read_mostly;
-EXPORT_SYMBOL_GPL(nf_conntrack_untracked);
-
unsigned int nf_ct_log_invalid __read_mostly;
static struct kmem_cache *nf_conntrack_cachep __read_mostly;
@@ -1018,8 +1015,8 @@ void nf_conntrack_cleanup(struct net *net)
schedule();
goto i_see_dead_people;
}
- /* wait until all references to nf_conntrack_untracked are dropped */
- while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1)
+ /* wait until all references to untracked conntrack are dropped */
+ while (atomic_read(&net->ct.untracked.ct_general.use) > 1)
schedule();
rcu_assign_pointer(nf_ct_destroy, NULL);
@@ -1179,11 +1176,11 @@ int nf_conntrack_init(struct net *net)
/* Set up fake conntrack:
- to never be deleted, not in any hashes */
#ifdef CONFIG_NET_NS
- nf_conntrack_untracked.ct_net = &init_net;
+ net->ct.untracked.ct_net = net;
#endif
- atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
+ atomic_set(&net->ct.untracked.ct_general.use, 1);
/* - and look it like as a confirmed connection */
- set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);
+ set_bit(IPS_CONFIRMED_BIT, &net->ct.untracked.status);
return ret;
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -30,6 +30,7 @@
#include <linux/netfilter.h>
#include <net/netlink.h>
+#include <net/net_namespace.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_expect.h>
@@ -425,7 +426,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
unsigned int flags = 0, group;
/* ignore our fake conntrack entry */
- if (ct == &nf_conntrack_untracked)
+ if (ct == &nf_ct_net(ct)->ct.untracked)
return NOTIFY_DONE;
if (events & IPCT_DESTROY) {
--- a/net/netfilter/xt_NOTRACK.c
+++ b/net/netfilter/xt_NOTRACK.c
@@ -2,6 +2,7 @@
* on packets so that they are not seen by the conntrack/NAT code.
*/
#include <linux/module.h>
+#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/netfilter/x_tables.h>
@@ -25,7 +26,7 @@ notrack_tg(struct sk_buff *skb, const struct net_device *in,
If there is a real ct entry correspondig to this packet,
it'll hang aroun till timing out. We don't deal with it
for performance reasons. JK */
- skb->nfct = &nf_conntrack_untracked.ct_general;
+ skb->nfct = &dev_net(in ? in : out)->ct.untracked.ct_general;
skb->nfctinfo = IP_CT_NEW;
nf_conntrack_get(skb->nfct);
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -39,7 +39,7 @@ conntrack_mt_v0(const struct sk_buff *skb, const struct net_device *in,
#define FWINV(bool, invflg) ((bool) ^ !!(sinfo->invflags & (invflg)))
- if (ct == &nf_conntrack_untracked)
+ if (ct == &nf_ct_net(ct)->ct.untracked)
statebit = XT_CONNTRACK_STATE_UNTRACKED;
else if (ct)
statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
@@ -217,7 +217,7 @@ conntrack_mt(const struct sk_buff *skb, const struct net_device *in,
ct = nf_ct_get(skb, &ctinfo);
- if (ct == &nf_conntrack_untracked)
+ if (ct == &nf_ct_net(ct)->ct.untracked)
statebit = XT_CONNTRACK_STATE_UNTRACKED;
else if (ct != NULL)
statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
--- a/net/netfilter/xt_state.c
+++ b/net/netfilter/xt_state.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
+#include <linux/netdevice.h>
#include <net/netfilter/nf_conntrack.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_state.h>
@@ -30,7 +31,7 @@ state_mt(const struct sk_buff *skb, const struct net_device *in,
enum ip_conntrack_info ctinfo;
unsigned int statebit;
- if (nf_ct_is_untracked(skb))
+ if (nf_ct_is_untracked(dev_net(in ? in : out), skb))
statebit = XT_STATE_UNTRACKED;
else if (!nf_ct_get(skb, &ctinfo))
statebit = XT_STATE_INVALID;
--
1.5.4.5
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 20/31] netns ct: NOTRACK in netns
2008-07-21 16:50 [PATCH 20/31] netns ct: NOTRACK in netns Alexey Dobriyan
@ 2008-07-21 17:05 ` Jan Engelhardt
2008-07-21 17:08 ` Patrick McHardy
0 siblings, 1 reply; 3+ messages in thread
From: Jan Engelhardt @ 2008-07-21 17:05 UTC (permalink / raw)
To: Alexey Dobriyan
Cc: kaber, netdev, netfilter-devel, dev, xemul, ebiederm, dlezcano,
benjamin.thery
On Monday 2008-07-21 18:50, Alexey Dobriyan wrote:
>Make untracked conntrack per-netns. Compare conntracks with untracked
>one in relevant netns.
>
>The following code may looks funny (sort-of self-referential):
>
> if (ct == ct->ct_net->ct.untracked)
> ...
The untracked conntrack is a singleton as I see it, as such it
should not be netnsed.
>+++ b/net/netfilter/xt_NOTRACK.c
>@@ -25,7 +26,7 @@ notrack_tg(struct sk_buff *skb, const struct net_device *in,
> If there is a real ct entry correspondig to this packet,
> it'll hang aroun till timing out. We don't deal with it
> for performance reasons. JK */
>- skb->nfct = &nf_conntrack_untracked.ct_general;
>+ skb->nfct = &dev_net(in ? in : out)->ct.untracked.ct_general;
You can just use 'in ? : out'.
>+++ b/net/netfilter/xt_state.c
>@@ -30,7 +31,7 @@ state_mt(const struct sk_buff *skb, const struct net_device *in,
> enum ip_conntrack_info ctinfo;
> unsigned int statebit;
>
>- if (nf_ct_is_untracked(skb))
>+ if (nf_ct_is_untracked(dev_net(in ? in : out), skb))
Does this even do the right thing? Given the forward path, where
both in!=NULL and out!=NULL, why should it specifically be 'in'
that is selected?
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 20/31] netns ct: NOTRACK in netns
2008-07-21 17:05 ` Jan Engelhardt
@ 2008-07-21 17:08 ` Patrick McHardy
0 siblings, 0 replies; 3+ messages in thread
From: Patrick McHardy @ 2008-07-21 17:08 UTC (permalink / raw)
To: Jan Engelhardt
Cc: Alexey Dobriyan, netdev, netfilter-devel, dev, xemul, ebiederm,
dlezcano, benjamin.thery
Jan Engelhardt wrote:
> On Monday 2008-07-21 18:50, Alexey Dobriyan wrote:
>
>> +++ b/net/netfilter/xt_state.c
>> @@ -30,7 +31,7 @@ state_mt(const struct sk_buff *skb, const struct net_device *in,
>> enum ip_conntrack_info ctinfo;
>> unsigned int statebit;
>>
>> - if (nf_ct_is_untracked(skb))
>> + if (nf_ct_is_untracked(dev_net(in ? in : out), skb))
>
> Does this even do the right thing? Given the forward path, where
> both in!=NULL and out!=NULL, why should it specifically be 'in'
> that is selected?
It doesn't matter, the namespace during forwaring is always
equal for the input and output devices.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-07-21 17:08 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-21 16:50 [PATCH 20/31] netns ct: NOTRACK in netns Alexey Dobriyan
2008-07-21 17:05 ` Jan Engelhardt
2008-07-21 17:08 ` Patrick McHardy
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).