|
|
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 |
|