* [PATCH 2.6]: keep fragment queues private to each user
@ 2005-01-25 4:57 Patrick McHardy
2005-01-25 11:57 ` Herbert Xu
2005-01-26 5:41 ` David S. Miller
0 siblings, 2 replies; 8+ messages in thread
From: Patrick McHardy @ 2005-01-25 4:57 UTC (permalink / raw)
To: David S. Miller; +Cc: Maillist netdev
[-- Attachment #1: Type: text/plain, Size: 430 bytes --]
Hi Dave,
This patch keeps fragment queues private to each ip_defrag user to avoid
skbs jumping between different callers. It shouldn't change any wanted
behaviour, the only questionable one was ip_call_ra_chain, but the RA
option is included in each fragment. If you're fine with the patch I'm going
to send a 2.4 version later.
Regards
Patrick
PS: The patch should apply in any order with the netfilter patches I
just sent.
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 11405 bytes --]
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2005/01/25 05:35:12+01:00 kaber@coreworks.de
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_nat_standalone.c
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +1 -1
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_conntrack_standalone.c
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +4 -7
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_conntrack_core.c
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +2 -9
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ipvs/ip_vs_core.c
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +11 -8
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ip_input.c
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +2 -2
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ip_fragment.c
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +13 -20
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# include/net/ip.h
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +14 -3
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# include/linux/netfilter_ipv4/ip_conntrack.h
# 2005/01/25 05:35:04+01:00 kaber@coreworks.de +1 -2
# [IPV4]: keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h 2005-01-25 05:35:30 +01:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h 2005-01-25 05:35:30 +01:00
@@ -262,10 +262,9 @@
/* Fake conntrack entry for untracked connections */
extern struct ip_conntrack ip_conntrack_untracked;
-extern int ip_ct_no_defrag;
/* Returns new sk_buff, or NULL */
struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb);
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
/* Iterate over all conntracks: if iter returns true, it's deleted. */
extern void
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h 2005-01-25 05:35:30 +01:00
+++ b/include/net/ip.h 2005-01-25 05:35:30 +01:00
@@ -286,9 +286,20 @@
/*
* Functions provided by ip_fragment.o
*/
-
-struct sk_buff *ip_defrag(struct sk_buff *skb);
-extern void ipfrag_flush(void);
+
+enum ip_defrag_users
+{
+ IP_DEFRAG_LOCAL_DELIVER,
+ IP_DEFRAG_CALL_RA_CHAIN,
+ IP_DEFRAG_CONNTRACK_IN,
+ IP_DEFRAG_CONNTRACK_OUT,
+ IP_DEFRAG_NAT_OUT,
+ IP_DEFRAG_VS_IN,
+ IP_DEFRAG_VS_OUT,
+ IP_DEFRAG_VS_FWD
+};
+
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
extern int ip_frag_nqueues;
extern atomic_t ip_frag_mem;
diff -Nru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
--- a/net/ipv4/ip_fragment.c 2005-01-25 05:35:30 +01:00
+++ b/net/ipv4/ip_fragment.c 2005-01-25 05:35:30 +01:00
@@ -73,6 +73,7 @@
struct ipq {
struct ipq *next; /* linked list pointers */
struct list_head lru_list; /* lru list member */
+ u32 user;
u32 saddr;
u32 daddr;
u16 id;
@@ -243,13 +244,13 @@
/* Memory limiting on fragments. Evictor trashes the oldest
* fragment queue until we are back under the threshold.
*/
-static void __ip_evictor(int threshold)
+static void ip_evictor(void)
{
struct ipq *qp;
struct list_head *tmp;
int work;
- work = atomic_read(&ip_frag_mem) - threshold;
+ work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
if (work <= 0)
return;
@@ -274,11 +275,6 @@
}
}
-static inline void ip_evictor(void)
-{
- __ip_evictor(sysctl_ipfrag_low_thresh);
-}
-
/*
* Oops, a fragment queue timed out. Kill it and send an ICMP reply.
*/
@@ -325,7 +321,8 @@
if(qp->id == qp_in->id &&
qp->saddr == qp_in->saddr &&
qp->daddr == qp_in->daddr &&
- qp->protocol == qp_in->protocol) {
+ qp->protocol == qp_in->protocol &&
+ qp->user == user) {
atomic_inc(&qp->refcnt);
write_unlock(&ipfrag_lock);
qp_in->last_in |= COMPLETE;
@@ -352,7 +349,7 @@
}
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
{
struct ipq *qp;
@@ -364,6 +361,7 @@
qp->id = iph->id;
qp->saddr = iph->saddr;
qp->daddr = iph->daddr;
+ qp->user = user;
qp->len = 0;
qp->meat = 0;
qp->fragments = NULL;
@@ -386,7 +384,7 @@
/* Find the correct entry in the "incomplete datagrams" queue for
* this IP datagram, and create new one, if nothing is found.
*/
-static inline struct ipq *ip_find(struct iphdr *iph)
+static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
{
__u16 id = iph->id;
__u32 saddr = iph->saddr;
@@ -400,7 +398,8 @@
if(qp->id == id &&
qp->saddr == saddr &&
qp->daddr == daddr &&
- qp->protocol == protocol) {
+ qp->protocol == protocol &&
+ qp->user == user) {
atomic_inc(&qp->refcnt);
read_unlock(&ipfrag_lock);
return qp;
@@ -408,7 +407,7 @@
}
read_unlock(&ipfrag_lock);
- return ip_frag_create(hash, iph);
+ return ip_frag_create(hash, iph, user);
}
/* Add new segment to existing queue. */
@@ -642,7 +641,7 @@
}
/* Process an incoming IP datagram fragment. */
-struct sk_buff *ip_defrag(struct sk_buff *skb)
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
{
struct iphdr *iph = skb->nh.iph;
struct ipq *qp;
@@ -657,7 +656,7 @@
dev = skb->dev;
/* Lookup (or create) queue header */
- if ((qp = ip_find(iph)) != NULL) {
+ if ((qp = ip_find(iph, user)) != NULL) {
struct sk_buff *ret = NULL;
spin_lock(&qp->lock);
@@ -689,10 +688,4 @@
add_timer(&ipfrag_secret_timer);
}
-void ipfrag_flush(void)
-{
- __ip_evictor(0);
-}
-
EXPORT_SYMBOL(ip_defrag);
-EXPORT_SYMBOL(ipfrag_flush);
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c 2005-01-25 05:35:30 +01:00
+++ b/net/ipv4/ip_input.c 2005-01-25 05:35:30 +01:00
@@ -172,7 +172,7 @@
(!sk->sk_bound_dev_if ||
sk->sk_bound_dev_if == skb->dev->ifindex)) {
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
if (skb == NULL) {
read_unlock(&ip_ra_lock);
return 1;
@@ -273,7 +273,7 @@
*/
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
if (!skb)
return 0;
}
diff -Nru a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
--- a/net/ipv4/ipvs/ip_vs_core.c 2005-01-25 05:35:30 +01:00
+++ b/net/ipv4/ipvs/ip_vs_core.c 2005-01-25 05:35:30 +01:00
@@ -544,9 +544,9 @@
}
static inline struct sk_buff *
-ip_vs_gather_frags(struct sk_buff *skb)
+ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
{
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, user);
if (skb)
ip_send_check(skb->nh.iph);
return skb;
@@ -620,7 +620,7 @@
/* reassemble IP fragments */
if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
- skb = ip_vs_gather_frags(skb);
+ skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
if (!skb)
return NF_STOLEN;
*pskb = skb;
@@ -759,7 +759,7 @@
/* reassemble IP fragments */
if (unlikely(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET) &&
!pp->dont_defrag)) {
- skb = ip_vs_gather_frags(skb);
+ skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
if (!skb)
return NF_STOLEN;
iph = skb->nh.iph;
@@ -839,7 +839,8 @@
* forward to the right destination host if relevant.
* Currently handles error types - unreachable, quench, ttl exceeded.
*/
-static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
+static int
+ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
{
struct sk_buff *skb = *pskb;
struct iphdr *iph;
@@ -853,7 +854,9 @@
/* reassemble IP fragments */
if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
- skb = ip_vs_gather_frags(skb);
+ skb = ip_vs_gather_frags(skb,
+ hooknum == NF_IP_LOCAL_IN ?
+ IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
if (!skb)
return NF_STOLEN;
*pskb = skb;
@@ -962,7 +965,7 @@
iph = skb->nh.iph;
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
- int related, verdict = ip_vs_in_icmp(pskb, &related);
+ int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum);
if (related)
return verdict;
@@ -1057,7 +1060,7 @@
if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP)
return NF_ACCEPT;
- return ip_vs_in_icmp(pskb, &r);
+ return ip_vs_in_icmp(pskb, &r, hooknum);
}
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c 2005-01-25 05:35:30 +01:00
+++ b/net/ipv4/netfilter/ip_conntrack_core.c 2005-01-25 05:35:30 +01:00
@@ -936,29 +936,22 @@
}
}
-int ip_ct_no_defrag;
-
/* Returns new sk_buff, or NULL */
struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb)
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
{
struct sock *sk = skb->sk;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int olddebug = skb->nf_debug;
#endif
- if (unlikely(ip_ct_no_defrag)) {
- kfree_skb(skb);
- return NULL;
- }
-
if (sk) {
sock_hold(sk);
skb_orphan(skb);
}
local_bh_disable();
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, user);
local_bh_enable();
if (!skb) {
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-01-25 05:35:30 +01:00
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-01-25 05:35:30 +01:00
@@ -391,7 +391,10 @@
/* Gather fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- *pskb = ip_ct_gather_frags(*pskb);
+ *pskb = ip_ct_gather_frags(*pskb,
+ hooknum == NF_IP_PRE_ROUTING ?
+ IP_DEFRAG_CONNTRACK_IN :
+ IP_DEFRAG_CONNTRACK_OUT);
if (!*pskb)
return NF_STOLEN;
}
@@ -823,12 +826,6 @@
cleanup_defraglocalops:
nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
cleanup_defragops:
- /* Frag queues may hold fragments with skb->dst == NULL */
- ip_ct_no_defrag = 1;
- synchronize_net();
- local_bh_disable();
- ipfrag_flush();
- local_bh_enable();
nf_unregister_hook(&ip_conntrack_defrag_ops);
cleanup_proc_stat:
#ifdef CONFIG_PROC_FS
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-25 05:35:30 +01:00
+++ b/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-25 05:35:30 +01:00
@@ -195,7 +195,7 @@
I'm starting to have nightmares about fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- *pskb = ip_ct_gather_frags(*pskb);
+ *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
if (!*pskb)
return NF_STOLEN;
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6]: keep fragment queues private to each user
2005-01-25 4:57 [PATCH 2.6]: keep fragment queues private to each user Patrick McHardy
@ 2005-01-25 11:57 ` Herbert Xu
2005-01-25 14:41 ` Patrick McHardy
2005-01-26 5:41 ` David S. Miller
1 sibling, 1 reply; 8+ messages in thread
From: Herbert Xu @ 2005-01-25 11:57 UTC (permalink / raw)
To: Patrick McHardy; +Cc: davem, netdev
Patrick McHardy <kaber@trash.net> wrote:
>
> This patch keeps fragment queues private to each ip_defrag user to avoid
> skbs jumping between different callers. It shouldn't change any wanted
> behaviour, the only questionable one was ip_call_ra_chain, but the RA
> option is included in each fragment. If you're fine with the patch I'm going
> to send a 2.4 version later.
Patch looks good.
However, I think this is still not enough. What about fragments
that come from different interfaces? Fragments with different
security paths?
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6]: keep fragment queues private to each user
2005-01-25 11:57 ` Herbert Xu
@ 2005-01-25 14:41 ` Patrick McHardy
2005-01-25 20:47 ` Herbert Xu
0 siblings, 1 reply; 8+ messages in thread
From: Patrick McHardy @ 2005-01-25 14:41 UTC (permalink / raw)
To: Herbert Xu; +Cc: davem, netdev
Herbert Xu wrote:
>However, I think this is still not enough. What about fragments
>that come from different interfaces? Fragments with different
>security paths?
>
Fragments with different security paths are indeed a problem, I
already tried fixing them by keeping the secpaths of all fragments
on a list in the head secpath and changing __xfrm_policy_check to
deal with them, but it is pretty tricky to get right. For different
interfaces: I'm not exactly sure where this is a problem, except
that any classification will only look at the head fragment interface.
Regards
Patrick
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6]: keep fragment queues private to each user
2005-01-25 14:41 ` Patrick McHardy
@ 2005-01-25 20:47 ` Herbert Xu
0 siblings, 0 replies; 8+ messages in thread
From: Herbert Xu @ 2005-01-25 20:47 UTC (permalink / raw)
To: Patrick McHardy; +Cc: davem, netdev
On Tue, Jan 25, 2005 at 03:41:04PM +0100, Patrick McHardy wrote:
>
> deal with them, but it is pretty tricky to get right. For different
> interfaces: I'm not exactly sure where this is a problem, except
> that any classification will only look at the head fragment interface.
Well consider an IPIP interface over a transport mode ESP SA...
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6]: keep fragment queues private to each user
2005-01-25 4:57 [PATCH 2.6]: keep fragment queues private to each user Patrick McHardy
2005-01-25 11:57 ` Herbert Xu
@ 2005-01-26 5:41 ` David S. Miller
2005-01-26 23:30 ` Patrick McHardy
1 sibling, 1 reply; 8+ messages in thread
From: David S. Miller @ 2005-01-26 5:41 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netdev
On Tue, 25 Jan 2005 05:57:47 +0100
Patrick McHardy <kaber@trash.net> wrote:
> This patch keeps fragment queues private to each ip_defrag user to avoid
> skbs jumping between different callers. It shouldn't change any wanted
> behaviour, the only questionable one was ip_call_ra_chain, but the RA
> option is included in each fragment. If you're fine with the patch I'm going
> to send a 2.4 version later.
Please fix the CONFIG_SMP build. You use some variable "user"
in ip_frag_intern(), yet don't add this as an argument or
anything like that.
The "user" use you added is protected by CONFIG_SMP, so my guess
is that you compile and tested this without SMP enabled.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6]: keep fragment queues private to each user
2005-01-26 5:41 ` David S. Miller
@ 2005-01-26 23:30 ` Patrick McHardy
2005-01-27 2:44 ` [PATCH 2.4]: " Patrick McHardy
2005-01-27 6:29 ` [PATCH 2.6]: " David S. Miller
0 siblings, 2 replies; 8+ messages in thread
From: Patrick McHardy @ 2005-01-26 23:30 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
[-- Attachment #1: Type: text/plain, Size: 669 bytes --]
David S. Miller wrote:
>On Tue, 25 Jan 2005 05:57:47 +0100
>Patrick McHardy <kaber@trash.net> wrote:
>
>>This patch keeps fragment queues private to each ip_defrag user to avoid
>>skbs jumping between different callers. It shouldn't change any wanted
>>behaviour, the only questionable one was ip_call_ra_chain, but the RA
>>option is included in each fragment. If you're fine with the patch I'm going
>>to send a 2.4 version later.
>>
>
>Please fix the CONFIG_SMP build. You use some variable "user"
>in ip_frag_intern(), yet don't add this as an argument or
>anything like that.
>
Sorry, new patch attached. I'll send the 2.4 patch later tonight.
Regards
Patrick
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 11412 bytes --]
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2005/01/27 00:20:54+01:00 kaber@coreworks.de
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_nat_standalone.c
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +1 -1
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_conntrack_standalone.c
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +4 -7
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_conntrack_core.c
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +2 -9
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ipvs/ip_vs_core.c
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +11 -8
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ip_input.c
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +2 -2
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ip_fragment.c
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +13 -20
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# include/net/ip.h
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +14 -3
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# include/linux/netfilter_ipv4/ip_conntrack.h
# 2005/01/27 00:20:46+01:00 kaber@coreworks.de +1 -2
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h 2005-01-27 00:22:21 +01:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h 2005-01-27 00:22:21 +01:00
@@ -262,10 +262,9 @@
/* Fake conntrack entry for untracked connections */
extern struct ip_conntrack ip_conntrack_untracked;
-extern int ip_ct_no_defrag;
/* Returns new sk_buff, or NULL */
struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb);
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
/* Iterate over all conntracks: if iter returns true, it's deleted. */
extern void
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h 2005-01-27 00:22:21 +01:00
+++ b/include/net/ip.h 2005-01-27 00:22:21 +01:00
@@ -286,9 +286,20 @@
/*
* Functions provided by ip_fragment.o
*/
-
-struct sk_buff *ip_defrag(struct sk_buff *skb);
-extern void ipfrag_flush(void);
+
+enum ip_defrag_users
+{
+ IP_DEFRAG_LOCAL_DELIVER,
+ IP_DEFRAG_CALL_RA_CHAIN,
+ IP_DEFRAG_CONNTRACK_IN,
+ IP_DEFRAG_CONNTRACK_OUT,
+ IP_DEFRAG_NAT_OUT,
+ IP_DEFRAG_VS_IN,
+ IP_DEFRAG_VS_OUT,
+ IP_DEFRAG_VS_FWD
+};
+
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
extern int ip_frag_nqueues;
extern atomic_t ip_frag_mem;
diff -Nru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
--- a/net/ipv4/ip_fragment.c 2005-01-27 00:22:21 +01:00
+++ b/net/ipv4/ip_fragment.c 2005-01-27 00:22:21 +01:00
@@ -73,6 +73,7 @@
struct ipq {
struct ipq *next; /* linked list pointers */
struct list_head lru_list; /* lru list member */
+ u32 user;
u32 saddr;
u32 daddr;
u16 id;
@@ -243,13 +244,13 @@
/* Memory limiting on fragments. Evictor trashes the oldest
* fragment queue until we are back under the threshold.
*/
-static void __ip_evictor(int threshold)
+static void ip_evictor(void)
{
struct ipq *qp;
struct list_head *tmp;
int work;
- work = atomic_read(&ip_frag_mem) - threshold;
+ work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
if (work <= 0)
return;
@@ -274,11 +275,6 @@
}
}
-static inline void ip_evictor(void)
-{
- __ip_evictor(sysctl_ipfrag_low_thresh);
-}
-
/*
* Oops, a fragment queue timed out. Kill it and send an ICMP reply.
*/
@@ -325,7 +321,8 @@
if(qp->id == qp_in->id &&
qp->saddr == qp_in->saddr &&
qp->daddr == qp_in->daddr &&
- qp->protocol == qp_in->protocol) {
+ qp->protocol == qp_in->protocol &&
+ qp->user == qp_in->user) {
atomic_inc(&qp->refcnt);
write_unlock(&ipfrag_lock);
qp_in->last_in |= COMPLETE;
@@ -352,7 +349,7 @@
}
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
{
struct ipq *qp;
@@ -364,6 +361,7 @@
qp->id = iph->id;
qp->saddr = iph->saddr;
qp->daddr = iph->daddr;
+ qp->user = user;
qp->len = 0;
qp->meat = 0;
qp->fragments = NULL;
@@ -386,7 +384,7 @@
/* Find the correct entry in the "incomplete datagrams" queue for
* this IP datagram, and create new one, if nothing is found.
*/
-static inline struct ipq *ip_find(struct iphdr *iph)
+static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
{
__u16 id = iph->id;
__u32 saddr = iph->saddr;
@@ -400,7 +398,8 @@
if(qp->id == id &&
qp->saddr == saddr &&
qp->daddr == daddr &&
- qp->protocol == protocol) {
+ qp->protocol == protocol &&
+ qp->user == user) {
atomic_inc(&qp->refcnt);
read_unlock(&ipfrag_lock);
return qp;
@@ -408,7 +407,7 @@
}
read_unlock(&ipfrag_lock);
- return ip_frag_create(hash, iph);
+ return ip_frag_create(hash, iph, user);
}
/* Add new segment to existing queue. */
@@ -642,7 +641,7 @@
}
/* Process an incoming IP datagram fragment. */
-struct sk_buff *ip_defrag(struct sk_buff *skb)
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
{
struct iphdr *iph = skb->nh.iph;
struct ipq *qp;
@@ -657,7 +656,7 @@
dev = skb->dev;
/* Lookup (or create) queue header */
- if ((qp = ip_find(iph)) != NULL) {
+ if ((qp = ip_find(iph, user)) != NULL) {
struct sk_buff *ret = NULL;
spin_lock(&qp->lock);
@@ -689,10 +688,4 @@
add_timer(&ipfrag_secret_timer);
}
-void ipfrag_flush(void)
-{
- __ip_evictor(0);
-}
-
EXPORT_SYMBOL(ip_defrag);
-EXPORT_SYMBOL(ipfrag_flush);
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c 2005-01-27 00:22:21 +01:00
+++ b/net/ipv4/ip_input.c 2005-01-27 00:22:21 +01:00
@@ -172,7 +172,7 @@
(!sk->sk_bound_dev_if ||
sk->sk_bound_dev_if == skb->dev->ifindex)) {
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
if (skb == NULL) {
read_unlock(&ip_ra_lock);
return 1;
@@ -273,7 +273,7 @@
*/
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
if (!skb)
return 0;
}
diff -Nru a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
--- a/net/ipv4/ipvs/ip_vs_core.c 2005-01-27 00:22:21 +01:00
+++ b/net/ipv4/ipvs/ip_vs_core.c 2005-01-27 00:22:21 +01:00
@@ -544,9 +544,9 @@
}
static inline struct sk_buff *
-ip_vs_gather_frags(struct sk_buff *skb)
+ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
{
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, user);
if (skb)
ip_send_check(skb->nh.iph);
return skb;
@@ -620,7 +620,7 @@
/* reassemble IP fragments */
if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
- skb = ip_vs_gather_frags(skb);
+ skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
if (!skb)
return NF_STOLEN;
*pskb = skb;
@@ -759,7 +759,7 @@
/* reassemble IP fragments */
if (unlikely(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET) &&
!pp->dont_defrag)) {
- skb = ip_vs_gather_frags(skb);
+ skb = ip_vs_gather_frags(skb, IP_DEFRAG_VS_OUT);
if (!skb)
return NF_STOLEN;
iph = skb->nh.iph;
@@ -839,7 +839,8 @@
* forward to the right destination host if relevant.
* Currently handles error types - unreachable, quench, ttl exceeded.
*/
-static int ip_vs_in_icmp(struct sk_buff **pskb, int *related)
+static int
+ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
{
struct sk_buff *skb = *pskb;
struct iphdr *iph;
@@ -853,7 +854,9 @@
/* reassemble IP fragments */
if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
- skb = ip_vs_gather_frags(skb);
+ skb = ip_vs_gather_frags(skb,
+ hooknum == NF_IP_LOCAL_IN ?
+ IP_DEFRAG_VS_IN : IP_DEFRAG_VS_FWD);
if (!skb)
return NF_STOLEN;
*pskb = skb;
@@ -962,7 +965,7 @@
iph = skb->nh.iph;
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
- int related, verdict = ip_vs_in_icmp(pskb, &related);
+ int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum);
if (related)
return verdict;
@@ -1057,7 +1060,7 @@
if ((*pskb)->nh.iph->protocol != IPPROTO_ICMP)
return NF_ACCEPT;
- return ip_vs_in_icmp(pskb, &r);
+ return ip_vs_in_icmp(pskb, &r, hooknum);
}
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c 2005-01-27 00:22:21 +01:00
+++ b/net/ipv4/netfilter/ip_conntrack_core.c 2005-01-27 00:22:21 +01:00
@@ -936,29 +936,22 @@
}
}
-int ip_ct_no_defrag;
-
/* Returns new sk_buff, or NULL */
struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb)
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
{
struct sock *sk = skb->sk;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int olddebug = skb->nf_debug;
#endif
- if (unlikely(ip_ct_no_defrag)) {
- kfree_skb(skb);
- return NULL;
- }
-
if (sk) {
sock_hold(sk);
skb_orphan(skb);
}
local_bh_disable();
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, user);
local_bh_enable();
if (!skb) {
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-01-27 00:22:21 +01:00
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-01-27 00:22:21 +01:00
@@ -391,7 +391,10 @@
/* Gather fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- *pskb = ip_ct_gather_frags(*pskb);
+ *pskb = ip_ct_gather_frags(*pskb,
+ hooknum == NF_IP_PRE_ROUTING ?
+ IP_DEFRAG_CONNTRACK_IN :
+ IP_DEFRAG_CONNTRACK_OUT);
if (!*pskb)
return NF_STOLEN;
}
@@ -823,12 +826,6 @@
cleanup_defraglocalops:
nf_unregister_hook(&ip_conntrack_defrag_local_out_ops);
cleanup_defragops:
- /* Frag queues may hold fragments with skb->dst == NULL */
- ip_ct_no_defrag = 1;
- synchronize_net();
- local_bh_disable();
- ipfrag_flush();
- local_bh_enable();
nf_unregister_hook(&ip_conntrack_defrag_ops);
cleanup_proc_stat:
#ifdef CONFIG_PROC_FS
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-27 00:22:21 +01:00
+++ b/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-27 00:22:21 +01:00
@@ -195,7 +195,7 @@
I'm starting to have nightmares about fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- *pskb = ip_ct_gather_frags(*pskb);
+ *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
if (!*pskb)
return NF_STOLEN;
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2.4]: keep fragment queues private to each user
2005-01-26 23:30 ` Patrick McHardy
@ 2005-01-27 2:44 ` Patrick McHardy
2005-01-27 6:29 ` [PATCH 2.6]: " David S. Miller
1 sibling, 0 replies; 8+ messages in thread
From: Patrick McHardy @ 2005-01-27 2:44 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
[-- Attachment #1: Type: text/plain, Size: 37 bytes --]
2.4 backport of the ip_defrag fix.
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 10889 bytes --]
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2005/01/27 03:42:30+01:00 kaber@coreworks.de
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/netsyms.c
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +0 -1
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_nat_standalone.c
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +1 -1
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_conntrack_standalone.c
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +0 -7
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/netfilter/ip_conntrack_core.c
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +6 -10
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ipvs/ip_vs_core.c
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +3 -3
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ip_input.c
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +2 -2
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/ipv4/ip_fragment.c
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +13 -19
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# include/net/ip.h
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +13 -3
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# include/linux/netfilter_ipv4/ip_conntrack.h
# 2005/01/27 03:42:28+01:00 kaber@coreworks.de +1 -2
# [IPV4]: Keep fragment queues private to each user
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
--- a/include/linux/netfilter_ipv4/ip_conntrack.h 2005-01-27 03:42:45 +01:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h 2005-01-27 03:42:45 +01:00
@@ -249,10 +249,9 @@
/* Call me when a conntrack is destroyed. */
extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
-extern int ip_ct_no_defrag;
/* Returns new sk_buff, or NULL */
struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb);
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
/* Delete all conntracks which match. */
extern void
diff -Nru a/include/net/ip.h b/include/net/ip.h
--- a/include/net/ip.h 2005-01-27 03:42:45 +01:00
+++ b/include/net/ip.h 2005-01-27 03:42:45 +01:00
@@ -227,9 +227,19 @@
/*
* Functions provided by ip_fragment.o
*/
-
-struct sk_buff *ip_defrag(struct sk_buff *skb);
-extern void ipfrag_flush(void);
+
+enum ip_defrag_users
+{
+ IP_DEFRAG_LOCAL_DELIVER,
+ IP_DEFRAG_CALL_RA_CHAIN,
+ IP_DEFRAG_CONNTRACK_IN,
+ IP_DEFRAG_CONNTRACK_OUT,
+ IP_DEFRAG_NAT_OUT,
+ IP_DEFRAG_VS_OUT,
+ IP_DEFRAG_VS_FWD
+};
+
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user);
extern int ip_frag_nqueues;
extern atomic_t ip_frag_mem;
diff -Nru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
--- a/net/ipv4/ip_fragment.c 2005-01-27 03:42:45 +01:00
+++ b/net/ipv4/ip_fragment.c 2005-01-27 03:42:45 +01:00
@@ -72,6 +72,7 @@
struct ipq {
struct ipq *next; /* linked list pointers */
struct list_head lru_list; /* lru list member */
+ u32 user;
u32 saddr;
u32 daddr;
u16 id;
@@ -242,13 +243,13 @@
/* Memory limiting on fragments. Evictor trashes the oldest
* fragment queue until we are back under the threshold.
*/
-static void __ip_evictor(int threshold)
+static void ip_evictor(void)
{
struct ipq *qp;
struct list_head *tmp;
int work;
- work = atomic_read(&ip_frag_mem) - threshold;
+ work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh;
if (work <= 0)
return;
@@ -273,11 +274,6 @@
}
}
-static inline void ip_evictor(void)
-{
- __ip_evictor(sysctl_ipfrag_low_thresh);
-}
-
/*
* Oops, a fragment queue timed out. Kill it and send an ICMP reply.
*/
@@ -324,7 +320,8 @@
if(qp->id == qp_in->id &&
qp->saddr == qp_in->saddr &&
qp->daddr == qp_in->daddr &&
- qp->protocol == qp_in->protocol) {
+ qp->protocol == qp_in->protocol &&
+ qp->user == qp_in->user) {
atomic_inc(&qp->refcnt);
write_unlock(&ipfrag_lock);
qp_in->last_in |= COMPLETE;
@@ -351,7 +348,7 @@
}
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
-static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user)
{
struct ipq *qp;
@@ -363,6 +360,7 @@
qp->id = iph->id;
qp->saddr = iph->saddr;
qp->daddr = iph->daddr;
+ qp->user = user;
qp->len = 0;
qp->meat = 0;
qp->fragments = NULL;
@@ -385,7 +383,7 @@
/* Find the correct entry in the "incomplete datagrams" queue for
* this IP datagram, and create new one, if nothing is found.
*/
-static inline struct ipq *ip_find(struct iphdr *iph)
+static inline struct ipq *ip_find(struct iphdr *iph, u32 user)
{
__u16 id = iph->id;
__u32 saddr = iph->saddr;
@@ -399,7 +397,8 @@
if(qp->id == id &&
qp->saddr == saddr &&
qp->daddr == daddr &&
- qp->protocol == protocol) {
+ qp->protocol == protocol &&
+ qp->user == user) {
atomic_inc(&qp->refcnt);
read_unlock(&ipfrag_lock);
return qp;
@@ -407,7 +406,7 @@
}
read_unlock(&ipfrag_lock);
- return ip_frag_create(hash, iph);
+ return ip_frag_create(hash, iph, user);
}
/* Add new segment to existing queue. */
@@ -641,7 +640,7 @@
}
/* Process an incoming IP datagram fragment. */
-struct sk_buff *ip_defrag(struct sk_buff *skb)
+struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user)
{
struct iphdr *iph = skb->nh.iph;
struct ipq *qp;
@@ -656,7 +655,7 @@
dev = skb->dev;
/* Lookup (or create) queue header */
- if ((qp = ip_find(iph)) != NULL) {
+ if ((qp = ip_find(iph, user)) != NULL) {
struct sk_buff *ret = NULL;
spin_lock(&qp->lock);
@@ -686,9 +685,4 @@
ipfrag_secret_timer.function = ipfrag_secret_rebuild;
ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
add_timer(&ipfrag_secret_timer);
-}
-
-void ipfrag_flush(void)
-{
- __ip_evictor(0);
}
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c 2005-01-27 03:42:44 +01:00
+++ b/net/ipv4/ip_input.c 2005-01-27 03:42:44 +01:00
@@ -170,7 +170,7 @@
&& ((sk->bound_dev_if == 0)
|| (sk->bound_dev_if == skb->dev->ifindex))) {
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN);
if (skb == NULL) {
read_unlock(&ip_ra_lock);
return 1;
@@ -291,7 +291,7 @@
*/
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER);
if (!skb)
return 0;
}
diff -Nru a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
--- a/net/ipv4/ipvs/ip_vs_core.c 2005-01-27 03:42:44 +01:00
+++ b/net/ipv4/ipvs/ip_vs_core.c 2005-01-27 03:42:44 +01:00
@@ -506,7 +506,7 @@
/* reassemble IP fragments, but will it happen in ICMP packets?? */
if (skb->nh.iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_VS_OUT);
if (!skb)
return NF_STOLEN;
*skb_p = skb;
@@ -658,7 +658,7 @@
/* reassemble IP fragments */
if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_VS_OUT);
if (!skb)
return NF_STOLEN;
iph = skb->nh.iph;
@@ -1164,7 +1164,7 @@
return NF_ACCEPT;
if (iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) {
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, IP_DEFRAG_VS_FWD);
if (!skb)
return NF_STOLEN;
*skb_p = skb;
diff -Nru a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
--- a/net/ipv4/netfilter/ip_conntrack_core.c 2005-01-27 03:42:44 +01:00
+++ b/net/ipv4/netfilter/ip_conntrack_core.c 2005-01-27 03:42:44 +01:00
@@ -834,7 +834,10 @@
/* Gather fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- *pskb = ip_ct_gather_frags(*pskb);
+ *pskb = ip_ct_gather_frags(*pskb,
+ hooknum == NF_IP_PRE_ROUTING ?
+ IP_DEFRAG_CONNTRACK_IN :
+ IP_DEFRAG_CONNTRACK_OUT);
if (!*pskb)
return NF_STOLEN;
}
@@ -1183,29 +1186,22 @@
WRITE_UNLOCK(&ip_conntrack_lock);
}
-int ip_ct_no_defrag;
-
/* Returns new sk_buff, or NULL */
struct sk_buff *
-ip_ct_gather_frags(struct sk_buff *skb)
+ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
{
struct sock *sk = skb->sk;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int olddebug = skb->nf_debug;
#endif
- if (unlikely(ip_ct_no_defrag)) {
- kfree_skb(skb);
- return NULL;
- }
-
if (sk) {
sock_hold(sk);
skb_orphan(skb);
}
local_bh_disable();
- skb = ip_defrag(skb);
+ skb = ip_defrag(skb, user);
local_bh_enable();
if (!skb) {
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-01-27 03:42:45 +01:00
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-01-27 03:42:45 +01:00
@@ -393,13 +393,6 @@
cleanup_inandlocalops:
nf_unregister_hook(&ip_conntrack_local_out_ops);
cleanup_inops:
- /* Frag queues may hold fragments with skb->dst == NULL */
- ip_ct_no_defrag = 1;
- local_bh_disable();
- br_write_lock(BR_NETPROTO_LOCK);
- br_write_unlock(BR_NETPROTO_LOCK);
- ipfrag_flush();
- local_bh_enable();
nf_unregister_hook(&ip_conntrack_in_ops);
cleanup_proc:
proc_net_remove("ip_conntrack");
diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
--- a/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-27 03:42:45 +01:00
+++ b/net/ipv4/netfilter/ip_nat_standalone.c 2005-01-27 03:42:45 +01:00
@@ -201,7 +201,7 @@
I'm starting to have nightmares about fragments. */
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
- *pskb = ip_ct_gather_frags(*pskb);
+ *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
if (!*pskb)
return NF_STOLEN;
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c 2005-01-27 03:42:45 +01:00
+++ b/net/netsyms.c 2005-01-27 03:42:45 +01:00
@@ -287,7 +287,6 @@
EXPORT_SYMBOL(inetdev_by_index);
EXPORT_SYMBOL(in_dev_finish_destroy);
EXPORT_SYMBOL(ip_defrag);
-EXPORT_SYMBOL(ipfrag_flush);
/* Route manipulation */
EXPORT_SYMBOL(ip_rt_ioctl);
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2.6]: keep fragment queues private to each user
2005-01-26 23:30 ` Patrick McHardy
2005-01-27 2:44 ` [PATCH 2.4]: " Patrick McHardy
@ 2005-01-27 6:29 ` David S. Miller
1 sibling, 0 replies; 8+ messages in thread
From: David S. Miller @ 2005-01-27 6:29 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netdev
On Thu, 27 Jan 2005 00:30:56 +0100
Patrick McHardy <kaber@trash.net> wrote:
> Sorry, new patch attached. I'll send the 2.4 patch later tonight.
Thanks. I'll apply this and the 2.4.x variant.
Although I have a theoretical objection to this thing. It is
extending a namespace we have no such control over. The namespace
is saddr/daddr/ID. But perhaps I'm being overly anal.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2005-01-27 6:29 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-25 4:57 [PATCH 2.6]: keep fragment queues private to each user Patrick McHardy
2005-01-25 11:57 ` Herbert Xu
2005-01-25 14:41 ` Patrick McHardy
2005-01-25 20:47 ` Herbert Xu
2005-01-26 5:41 ` David S. Miller
2005-01-26 23:30 ` Patrick McHardy
2005-01-27 2:44 ` [PATCH 2.4]: " Patrick McHardy
2005-01-27 6:29 ` [PATCH 2.6]: " David S. Miller
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).