ced5d35
Bugzilla: 1015905
ced5d35
Upstream-status: 3.13 (should hit stable)
ced5d35
ced5d35
From 5c0df04613dd39fba5d2a43eaf90a2dc1dcd8899 Mon Sep 17 00:00:00 2001
ced5d35
From: Jiri Pirko <jiri@resnulli.us>
ced5d35
Date: Wed, 6 Nov 2013 17:52:20 +0100
ced5d35
Subject: [PATCH 2/2] netfilter: push reasm skb through instead of original
ced5d35
 frag skbs
ced5d35
ced5d35
Pushing original fragments through causes several problems. For example
ced5d35
for matching, frags may not be matched correctly. Take following
ced5d35
example:
ced5d35
ced5d35
<example>
ced5d35
On HOSTA do:
ced5d35
ip6tables -I INPUT -p icmpv6 -j DROP
ced5d35
ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT
ced5d35
ced5d35
and on HOSTB you do:
ced5d35
ping6 HOSTA -s2000    (MTU is 1500)
ced5d35
ced5d35
Incoming echo requests will be filtered out on HOSTA. This issue does
ced5d35
not occur with smaller packets than MTU (where fragmentation does not happen)
ced5d35
</example>
ced5d35
ced5d35
As was discussed previously, the only correct solution seems to be to use
ced5d35
reassembled skb instead of separete frags. Doing this has positive side
ced5d35
effects in reducing sk_buff by one pointer (nfct_reasm) and also the reams
ced5d35
dances in ipvs and conntrack can be removed.
ced5d35
ced5d35
Future plan is to remove net/ipv6/netfilter/nf_conntrack_reasm.c
ced5d35
entirely and use code in net/ipv6/reassembly.c instead.
ced5d35
ced5d35
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
ced5d35
Acked-by: Julian Anastasov <ja@ssi.bg>
ced5d35
Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
ced5d35
Signed-off-by: David S. Miller <davem@davemloft.net>
ced5d35
ced5d35
Conflicts:
ced5d35
	include/net/netfilter/ipv6/nf_defrag_ipv6.h
ced5d35
	net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
ced5d35
	net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
ced5d35
	net/netfilter/ipvs/ip_vs_core.c
ced5d35
---
ced5d35
 include/linux/skbuff.h                         | 32 ---------------
ced5d35
 include/net/ip_vs.h                            | 32 +--------------
ced5d35
 include/net/netfilter/ipv6/nf_defrag_ipv6.h    |  5 +--
ced5d35
 net/core/skbuff.c                              |  3 --
ced5d35
 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 54 +------------------------
ced5d35
 net/ipv6/netfilter/nf_conntrack_reasm.c        | 19 +--------
ced5d35
 net/ipv6/netfilter/nf_defrag_ipv6_hooks.c      |  7 +++-
ced5d35
 net/netfilter/ipvs/ip_vs_core.c                | 55 +-------------------------
ced5d35
 net/netfilter/ipvs/ip_vs_pe_sip.c              |  8 +---
ced5d35
 9 files changed, 13 insertions(+), 202 deletions(-)
ced5d35
ced5d35
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
ced5d35
index 6bd165b..37b4517 100644
ced5d35
--- a/include/linux/skbuff.h
ced5d35
+++ b/include/linux/skbuff.h
ced5d35
@@ -333,11 +333,6 @@ typedef unsigned int sk_buff_data_t;
ced5d35
 typedef unsigned char *sk_buff_data_t;
ced5d35
 #endif
ced5d35
 
ced5d35
-#if defined(CONFIG_NF_DEFRAG_IPV4) || defined(CONFIG_NF_DEFRAG_IPV4_MODULE) || \
ced5d35
-    defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
ced5d35
-#define NET_SKBUFF_NF_DEFRAG_NEEDED 1
ced5d35
-#endif
ced5d35
-
ced5d35
 /** 
ced5d35
  *	struct sk_buff - socket buffer
ced5d35
  *	@next: Next buffer in list
ced5d35
@@ -370,7 +365,6 @@ typedef unsigned char *sk_buff_data_t;
ced5d35
  *	@protocol: Packet protocol from driver
ced5d35
  *	@destructor: Destruct function
ced5d35
  *	@nfct: Associated connection, if any
ced5d35
- *	@nfct_reasm: netfilter conntrack re-assembly pointer
ced5d35
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
ced5d35
  *	@skb_iif: ifindex of device we arrived on
ced5d35
  *	@tc_index: Traffic control index
ced5d35
@@ -459,9 +453,6 @@ struct sk_buff {
ced5d35
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
ced5d35
 	struct nf_conntrack	*nfct;
ced5d35
 #endif
ced5d35
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
ced5d35
-	struct sk_buff		*nfct_reasm;
ced5d35
-#endif
ced5d35
 #ifdef CONFIG_BRIDGE_NETFILTER
ced5d35
 	struct nf_bridge_info	*nf_bridge;
ced5d35
 #endif
ced5d35
@@ -2603,18 +2594,6 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
ced5d35
 		atomic_inc(&nfct->use);
ced5d35
 }
ced5d35
 #endif
ced5d35
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
ced5d35
-static inline void nf_conntrack_get_reasm(struct sk_buff *skb)
ced5d35
-{
ced5d35
-	if (skb)
ced5d35
-		atomic_inc(&skb->users);
ced5d35
-}
ced5d35
-static inline void nf_conntrack_put_reasm(struct sk_buff *skb)
ced5d35
-{
ced5d35
-	if (skb)
ced5d35
-		kfree_skb(skb);
ced5d35
-}
ced5d35
-#endif
ced5d35
 #ifdef CONFIG_BRIDGE_NETFILTER
ced5d35
 static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
ced5d35
 {
ced5d35
@@ -2633,10 +2612,6 @@ static inline void nf_reset(struct sk_buff *skb)
ced5d35
 	nf_conntrack_put(skb->nfct);
ced5d35
 	skb->nfct = NULL;
ced5d35
 #endif
ced5d35
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
ced5d35
-	nf_conntrack_put_reasm(skb->nfct_reasm);
ced5d35
-	skb->nfct_reasm = NULL;
ced5d35
-#endif
ced5d35
 #ifdef CONFIG_BRIDGE_NETFILTER
ced5d35
 	nf_bridge_put(skb->nf_bridge);
ced5d35
 	skb->nf_bridge = NULL;
ced5d35
@@ -2658,10 +2633,6 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
ced5d35
 	nf_conntrack_get(src->nfct);
ced5d35
 	dst->nfctinfo = src->nfctinfo;
ced5d35
 #endif
ced5d35
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
ced5d35
-	dst->nfct_reasm = src->nfct_reasm;
ced5d35
-	nf_conntrack_get_reasm(src->nfct_reasm);
ced5d35
-#endif
ced5d35
 #ifdef CONFIG_BRIDGE_NETFILTER
ced5d35
 	dst->nf_bridge  = src->nf_bridge;
ced5d35
 	nf_bridge_get(src->nf_bridge);
ced5d35
@@ -2673,9 +2644,6 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
ced5d35
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
ced5d35
 	nf_conntrack_put(dst->nfct);
ced5d35
 #endif
ced5d35
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
ced5d35
-	nf_conntrack_put_reasm(dst->nfct_reasm);
ced5d35
-#endif
ced5d35
 #ifdef CONFIG_BRIDGE_NETFILTER
ced5d35
 	nf_bridge_put(dst->nf_bridge);
ced5d35
 #endif
ced5d35
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
ced5d35
index f0d70f0..ff21521 100644
ced5d35
--- a/include/net/ip_vs.h
ced5d35
+++ b/include/net/ip_vs.h
ced5d35
@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size;
ced5d35
 struct ip_vs_iphdr {
ced5d35
 	__u32 len;	/* IPv4 simply where L4 starts
ced5d35
 			   IPv6 where L4 Transport Header starts */
ced5d35
-	__u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
ced5d35
 	__u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
ced5d35
 	__s16 protocol;
ced5d35
 	__s32 flags;
ced5d35
@@ -117,34 +116,12 @@ struct ip_vs_iphdr {
ced5d35
 	union nf_inet_addr daddr;
ced5d35
 };
ced5d35
 
ced5d35
-/* Dependency to module: nf_defrag_ipv6 */
ced5d35
-#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
ced5d35
-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
ced5d35
-{
ced5d35
-	return skb->nfct_reasm;
ced5d35
-}
ced5d35
-static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
ced5d35
-				      int len, void *buffer,
ced5d35
-				      const struct ip_vs_iphdr *ipvsh)
ced5d35
-{
ced5d35
-	if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
ced5d35
-		return skb_header_pointer(skb_nfct_reasm(skb),
ced5d35
-					  ipvsh->thoff_reasm, len, buffer);
ced5d35
-
ced5d35
-	return skb_header_pointer(skb, offset, len, buffer);
ced5d35
-}
ced5d35
-#else
ced5d35
-static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
ced5d35
-{
ced5d35
-	return NULL;
ced5d35
-}
ced5d35
 static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
ced5d35
 				      int len, void *buffer,
ced5d35
 				      const struct ip_vs_iphdr *ipvsh)
ced5d35
 {
ced5d35
 	return skb_header_pointer(skb, offset, len, buffer);
ced5d35
 }
ced5d35
-#endif
ced5d35
 
ced5d35
 static inline void
ced5d35
 ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
ced5d35
@@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
ced5d35
 			(struct ipv6hdr *)skb_network_header(skb);
ced5d35
 		iphdr->saddr.in6 = iph->saddr;
ced5d35
 		iphdr->daddr.in6 = iph->daddr;
ced5d35
-		/* ipv6_find_hdr() updates len, flags, thoff_reasm */
ced5d35
-		iphdr->thoff_reasm = 0;
ced5d35
+		/* ipv6_find_hdr() updates len, flags */
ced5d35
 		iphdr->len	 = 0;
ced5d35
 		iphdr->flags	 = 0;
ced5d35
 		iphdr->protocol  = ipv6_find_hdr(skb, &iphdr->len, -1,
ced5d35
 						 &iphdr->fragoffs,
ced5d35
 						 &iphdr->flags);
ced5d35
-		/* get proto from re-assembled packet and it's offset */
ced5d35
-		if (skb_nfct_reasm(skb))
ced5d35
-			iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
ced5d35
-							&iphdr->thoff_reasm,
ced5d35
-							-1, NULL, NULL);
ced5d35
-
ced5d35
 	} else
ced5d35
 #endif
ced5d35
 	{
ced5d35
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
ced5d35
index fd79c9a..17920d8 100644
ced5d35
--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
ced5d35
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
ced5d35
@@ -6,10 +6,7 @@ extern void nf_defrag_ipv6_enable(void);
ced5d35
 extern int nf_ct_frag6_init(void);
ced5d35
 extern void nf_ct_frag6_cleanup(void);
ced5d35
 extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
ced5d35
-extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
ced5d35
-			       struct net_device *in,
ced5d35
-			       struct net_device *out,
ced5d35
-			       int (*okfn)(struct sk_buff *));
ced5d35
+extern void nf_ct_frag6_consume_orig(struct sk_buff *skb);
ced5d35
 
ced5d35
 struct inet_frags_ctl;
ced5d35
 
ced5d35
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
ced5d35
index 2c3d0f5..a75022e 100644
ced5d35
--- a/net/core/skbuff.c
ced5d35
+++ b/net/core/skbuff.c
ced5d35
@@ -580,9 +580,6 @@ static void skb_release_head_state(struct sk_buff *skb)
ced5d35
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
ced5d35
 	nf_conntrack_put(skb->nfct);
ced5d35
 #endif
ced5d35
-#ifdef NET_SKBUFF_NF_DEFRAG_NEEDED
ced5d35
-	nf_conntrack_put_reasm(skb->nfct_reasm);
ced5d35
-#endif
ced5d35
 #ifdef CONFIG_BRIDGE_NETFILTER
ced5d35
 	nf_bridge_put(skb->nf_bridge);
ced5d35
 #endif
ced5d35
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
ced5d35
index c9b6a6e..97cd750 100644
ced5d35
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
ced5d35
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
ced5d35
@@ -172,63 +172,13 @@ out:
ced5d35
 	return nf_conntrack_confirm(skb);
ced5d35
 }
ced5d35
 
ced5d35
-static unsigned int __ipv6_conntrack_in(struct net *net,
ced5d35
-					unsigned int hooknum,
ced5d35
-					struct sk_buff *skb,
ced5d35
-					const struct net_device *in,
ced5d35
-					const struct net_device *out,
ced5d35
-					int (*okfn)(struct sk_buff *))
ced5d35
-{
ced5d35
-	struct sk_buff *reasm = skb->nfct_reasm;
ced5d35
-	const struct nf_conn_help *help;
ced5d35
-	struct nf_conn *ct;
ced5d35
-	enum ip_conntrack_info ctinfo;
ced5d35
-
ced5d35
-	/* This packet is fragmented and has reassembled packet. */
ced5d35
-	if (reasm) {
ced5d35
-		/* Reassembled packet isn't parsed yet ? */
ced5d35
-		if (!reasm->nfct) {
ced5d35
-			unsigned int ret;
ced5d35
-
ced5d35
-			ret = nf_conntrack_in(net, PF_INET6, hooknum, reasm);
ced5d35
-			if (ret != NF_ACCEPT)
ced5d35
-				return ret;
ced5d35
-		}
ced5d35
-
ced5d35
-		/* Conntrack helpers need the entire reassembled packet in the
ced5d35
-		 * POST_ROUTING hook. In case of unconfirmed connections NAT
ced5d35
-		 * might reassign a helper, so the entire packet is also
ced5d35
-		 * required.
ced5d35
-		 */
ced5d35
-		ct = nf_ct_get(reasm, &ctinfo);
ced5d35
-		if (ct != NULL && !nf_ct_is_untracked(ct)) {
ced5d35
-			help = nfct_help(ct);
ced5d35
-			if ((help && help->helper) || !nf_ct_is_confirmed(ct)) {
ced5d35
-				nf_conntrack_get_reasm(reasm);
ced5d35
-				NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
ced5d35
-					       (struct net_device *)in,
ced5d35
-					       (struct net_device *)out,
ced5d35
-					       okfn, NF_IP6_PRI_CONNTRACK + 1);
ced5d35
-				return NF_DROP_ERR(-ECANCELED);
ced5d35
-			}
ced5d35
-		}
ced5d35
-
ced5d35
-		nf_conntrack_get(reasm->nfct);
ced5d35
-		skb->nfct = reasm->nfct;
ced5d35
-		skb->nfctinfo = reasm->nfctinfo;
ced5d35
-		return NF_ACCEPT;
ced5d35
-	}
ced5d35
-
ced5d35
-	return nf_conntrack_in(net, PF_INET6, hooknum, skb);
ced5d35
-}
ced5d35
-
ced5d35
 static unsigned int ipv6_conntrack_in(unsigned int hooknum,
ced5d35
 				      struct sk_buff *skb,
ced5d35
 				      const struct net_device *in,
ced5d35
 				      const struct net_device *out,
ced5d35
 				      int (*okfn)(struct sk_buff *))
ced5d35
 {
ced5d35
-	return __ipv6_conntrack_in(dev_net(in), hooknum, skb, in, out, okfn);
ced5d35
+	return nf_conntrack_in(dev_net(in), PF_INET6, hooknum, skb);
ced5d35
 }
ced5d35
 
ced5d35
 static unsigned int ipv6_conntrack_local(unsigned int hooknum,
ced5d35
@@ -242,7 +192,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
ced5d35
 		net_notice_ratelimited("ipv6_conntrack_local: packet too short\n");
ced5d35
 		return NF_ACCEPT;
ced5d35
 	}
ced5d35
-	return __ipv6_conntrack_in(dev_net(out), hooknum, skb, in, out, okfn);
ced5d35
+	return nf_conntrack_in(dev_net(out), PF_INET6, hooknum, skb);
ced5d35
 }
ced5d35
 
ced5d35
 static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
ced5d35
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
ced5d35
index dffdc1a..253566a 100644
ced5d35
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
ced5d35
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
ced5d35
@@ -621,31 +621,16 @@ ret_orig:
ced5d35
 	return skb;
ced5d35
 }
ced5d35
 
ced5d35
-void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
ced5d35
-			struct net_device *in, struct net_device *out,
ced5d35
-			int (*okfn)(struct sk_buff *))
ced5d35
+void nf_ct_frag6_consume_orig(struct sk_buff *skb)
ced5d35
 {
ced5d35
 	struct sk_buff *s, *s2;
ced5d35
-	unsigned int ret = 0;
ced5d35
 
ced5d35
 	for (s = NFCT_FRAG6_CB(skb)->orig; s;) {
ced5d35
-		nf_conntrack_put_reasm(s->nfct_reasm);
ced5d35
-		nf_conntrack_get_reasm(skb);
ced5d35
-		s->nfct_reasm = skb;
ced5d35
-
ced5d35
 		s2 = s->next;
ced5d35
 		s->next = NULL;
ced5d35
-
ced5d35
-		if (ret != -ECANCELED)
ced5d35
-			ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s,
ced5d35
-					     in, out, okfn,
ced5d35
-					     NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
ced5d35
-		else
ced5d35
-			kfree_skb(s);
ced5d35
-
ced5d35
+		consume_skb(s);
ced5d35
 		s = s2;
ced5d35
 	}
ced5d35
-	nf_conntrack_put_reasm(skb);
ced5d35
 }
ced5d35
 
ced5d35
 static int nf_ct_net_init(struct net *net)
ced5d35
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
ced5d35
index aacd121..581dd9e 100644
ced5d35
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
ced5d35
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
ced5d35
@@ -75,8 +75,11 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
ced5d35
 	if (reasm == skb)
ced5d35
 		return NF_ACCEPT;
ced5d35
 
ced5d35
-	nf_ct_frag6_output(hooknum, reasm, (struct net_device *)in,
ced5d35
-			   (struct net_device *)out, okfn);
ced5d35
+	nf_ct_frag6_consume_orig(reasm);
ced5d35
+
ced5d35
+	NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
ced5d35
+		       (struct net_device *) in, (struct net_device *) out,
ced5d35
+		       okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
ced5d35
 
ced5d35
 	return NF_STOLEN;
ced5d35
 }
ced5d35
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
ced5d35
index 4f69e83..1517b50 100644
ced5d35
--- a/net/netfilter/ipvs/ip_vs_core.c
ced5d35
+++ b/net/netfilter/ipvs/ip_vs_core.c
ced5d35
@@ -1131,12 +1131,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
ced5d35
 	ip_vs_fill_iph_skb(af, skb, &iph;;
ced5d35
 #ifdef CONFIG_IP_VS_IPV6
ced5d35
 	if (af == AF_INET6) {
ced5d35
-		if (!iph.fragoffs && skb_nfct_reasm(skb)) {
ced5d35
-			struct sk_buff *reasm = skb_nfct_reasm(skb);
ced5d35
-			/* Save fw mark for coming frags */
ced5d35
-			reasm->ipvs_property = 1;
ced5d35
-			reasm->mark = skb->mark;
ced5d35
-		}
ced5d35
 		if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
ced5d35
 			int related;
ced5d35
 			int verdict = ip_vs_out_icmp_v6(skb, &related,
ced5d35
@@ -1606,12 +1600,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
ced5d35
 
ced5d35
 #ifdef CONFIG_IP_VS_IPV6
ced5d35
 	if (af == AF_INET6) {
ced5d35
-		if (!iph.fragoffs && skb_nfct_reasm(skb)) {
ced5d35
-			struct sk_buff *reasm = skb_nfct_reasm(skb);
ced5d35
-			/* Save fw mark for coming frags. */
ced5d35
-			reasm->ipvs_property = 1;
ced5d35
-			reasm->mark = skb->mark;
ced5d35
-		}
ced5d35
 		if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
ced5d35
 			int related;
ced5d35
 			int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum,
ced5d35
@@ -1663,9 +1651,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
ced5d35
 		/* sorry, all this trouble for a no-hit :) */
ced5d35
 		IP_VS_DBG_PKT(12, af, pp, skb, 0,
ced5d35
 			      "ip_vs_in: packet continues traversal as normal");
ced5d35
-		if (iph.fragoffs && !skb_nfct_reasm(skb)) {
ced5d35
+		if (iph.fragoffs) {
ced5d35
 			/* Fragment that couldn't be mapped to a conn entry
ced5d35
-			 * and don't have any pointer to a reasm skb
ced5d35
 			 * is missing module nf_defrag_ipv6
ced5d35
 			 */
ced5d35
 			IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
ced5d35
@@ -1748,38 +1735,6 @@ ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb,
ced5d35
 #ifdef CONFIG_IP_VS_IPV6
ced5d35
 
ced5d35
 /*
ced5d35
- * AF_INET6 fragment handling
ced5d35
- * Copy info from first fragment, to the rest of them.
ced5d35
- */
ced5d35
-static unsigned int
ced5d35
-ip_vs_preroute_frag6(unsigned int hooknum, struct sk_buff *skb,
ced5d35
-		     const struct net_device *in,
ced5d35
-		     const struct net_device *out,
ced5d35
-		     int (*okfn)(struct sk_buff *))
ced5d35
-{
ced5d35
-	struct sk_buff *reasm = skb_nfct_reasm(skb);
ced5d35
-	struct net *net;
ced5d35
-
ced5d35
-	/* Skip if not a "replay" from nf_ct_frag6_output or first fragment.
ced5d35
-	 * ipvs_property is set when checking first fragment
ced5d35
-	 * in ip_vs_in() and ip_vs_out().
ced5d35
-	 */
ced5d35
-	if (reasm)
ced5d35
-		IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property);
ced5d35
-	if (!reasm || !reasm->ipvs_property)
ced5d35
-		return NF_ACCEPT;
ced5d35
-
ced5d35
-	net = skb_net(skb);
ced5d35
-	if (!net_ipvs(net)->enable)
ced5d35
-		return NF_ACCEPT;
ced5d35
-
ced5d35
-	/* Copy stored fw mark, saved in ip_vs_{in,out} */
ced5d35
-	skb->mark = reasm->mark;
ced5d35
-
ced5d35
-	return NF_ACCEPT;
ced5d35
-}
ced5d35
-
ced5d35
-/*
ced5d35
  *	AF_INET6 handler in NF_INET_LOCAL_IN chain
ced5d35
  *	Schedule and forward packets from remote clients
ced5d35
  */
ced5d35
@@ -1916,14 +1871,6 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
ced5d35
 		.priority	= 100,
ced5d35
 	},
ced5d35
 #ifdef CONFIG_IP_VS_IPV6
ced5d35
-	/* After mangle & nat fetch 2:nd fragment and following */
ced5d35
-	{
ced5d35
-		.hook		= ip_vs_preroute_frag6,
ced5d35
-		.owner		= THIS_MODULE,
ced5d35
-		.pf		= NFPROTO_IPV6,
ced5d35
-		.hooknum	= NF_INET_PRE_ROUTING,
ced5d35
-		.priority	= NF_IP6_PRI_NAT_DST + 1,
ced5d35
-	},
ced5d35
 	/* After packet filtering, change source only for VS/NAT */
ced5d35
 	{
ced5d35
 		.hook		= ip_vs_reply6,
ced5d35
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
ced5d35
index 9ef22bd..bed5f70 100644
ced5d35
--- a/net/netfilter/ipvs/ip_vs_pe_sip.c
ced5d35
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
ced5d35
@@ -65,7 +65,6 @@ static int get_callid(const char *dptr, unsigned int dataoff,
ced5d35
 static int
ced5d35
 ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
ced5d35
 {
ced5d35
-	struct sk_buff *reasm = skb_nfct_reasm(skb);
ced5d35
 	struct ip_vs_iphdr iph;
ced5d35
 	unsigned int dataoff, datalen, matchoff, matchlen;
ced5d35
 	const char *dptr;
ced5d35
@@ -79,15 +78,10 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
ced5d35
 	/* todo: IPv6 fragments:
ced5d35
 	 *       I think this only should be done for the first fragment. /HS
ced5d35
 	 */
ced5d35
-	if (reasm) {
ced5d35
-		skb = reasm;
ced5d35
-		dataoff = iph.thoff_reasm + sizeof(struct udphdr);
ced5d35
-	} else
ced5d35
-		dataoff = iph.len + sizeof(struct udphdr);
ced5d35
+	dataoff = iph.len + sizeof(struct udphdr);
ced5d35
 
ced5d35
 	if (dataoff >= skb->len)
ced5d35
 		return -EINVAL;
ced5d35
-	/* todo: Check if this will mess-up the reasm skb !!! /HS */
ced5d35
 	retc = skb_linearize(skb);
ced5d35
 	if (retc < 0)
ced5d35
 		return retc;
ced5d35
-- 
ced5d35
1.8.3.1
ced5d35