diff -Naru 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-03-29 07:28:22 -08:00 +++ b/include/linux/netfilter_ipv4/ip_conntrack.h 2005-03-29 07:28:22 -08: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 -Naru a/include/net/ip.h b/include/net/ip.h --- a/include/net/ip.h 2005-03-29 07:28:22 -08:00 +++ b/include/net/ip.h 2005-03-29 07:28:22 -08: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 -Naru a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c --- a/net/ipv4/ip_fragment.c 2005-03-29 07:28:22 -08:00 +++ b/net/ipv4/ip_fragment.c 2005-03-29 07:28:22 -08: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 -Naru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c --- a/net/ipv4/ip_input.c 2005-03-29 07:28:22 -08:00 +++ b/net/ipv4/ip_input.c 2005-03-29 07:28:22 -08: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 -Naru 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-03-29 07:28:22 -08:00 +++ b/net/ipv4/ipvs/ip_vs_core.c 2005-03-29 07:28:22 -08: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 -Naru 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-03-29 07:28:22 -08:00 +++ b/net/ipv4/netfilter/ip_conntrack_core.c 2005-03-29 07:28:22 -08: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 -Naru 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-03-29 07:28:22 -08:00 +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-03-29 07:28:22 -08: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 -Naru 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-03-29 07:28:22 -08:00 +++ b/net/ipv4/netfilter/ip_nat_standalone.c 2005-03-29 07:28:22 -08: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 -Naru a/net/netsyms.c b/net/netsyms.c --- a/net/netsyms.c 2005-03-29 07:28:22 -08:00 +++ b/net/netsyms.c 2005-03-29 07:28:22 -08: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); # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2005/01/26 22:04:53-08:00 kaber@trash.net # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # include/linux/netfilter_ipv4/ip_conntrack.h # 2005/01/26 22:04:47-08:00 kaber@trash.net +1 -2 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # include/net/ip.h # 2005/01/26 22:04:47-08:00 kaber@trash.net +13 -3 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # net/ipv4/ip_fragment.c # 2005/01/26 22:04:47-08:00 kaber@trash.net +13 -19 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # net/ipv4/ip_input.c # 2005/01/26 22:04:47-08:00 kaber@trash.net +2 -2 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # net/ipv4/ipvs/ip_vs_core.c # 2005/01/26 22:04:47-08:00 kaber@trash.net +3 -3 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # net/ipv4/netfilter/ip_conntrack_core.c # 2005/01/26 22:04:47-08:00 kaber@trash.net +6 -10 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # net/ipv4/netfilter/ip_conntrack_standalone.c # 2005/01/26 22:04:48-08:00 kaber@trash.net +0 -7 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # net/ipv4/netfilter/ip_nat_standalone.c # 2005/01/26 22:04:48-08:00 kaber@trash.net +1 -1 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller # # net/netsyms.c # 2005/01/26 22:04:48-08:00 kaber@trash.net +0 -1 # [IPV4]: Keep fragment queues private to each user. # # Signed-off-by: Patrick McHardy # Signed-off-by: David S. Miller #