aboutsummaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2013-11-06 11:52:20 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-12-08 10:29:25 -0500
commitfddd8b501c59c87d63a0917c8e9e14bd28e3c724 (patch)
treedd715845dc99cff34e5cc63fd7fc4afdbf5a3850 /include/net
parent2d9a30962d0310d33372c245a6191499a06409f3 (diff)
netfilter: push reasm skb through instead of original frag skbs
[ Upstream commit 6aafeef03b9d9ecf255f3a80ed85ee070260e1ae ] Pushing original fragments through causes several problems. For example for matching, frags may not be matched correctly. Take following example: <example> On HOSTA do: ip6tables -I INPUT -p icmpv6 -j DROP ip6tables -I INPUT -p icmpv6 -m icmp6 --icmpv6-type 128 -j ACCEPT and on HOSTB you do: ping6 HOSTA -s2000 (MTU is 1500) Incoming echo requests will be filtered out on HOSTA. This issue does not occur with smaller packets than MTU (where fragmentation does not happen) </example> As was discussed previously, the only correct solution seems to be to use reassembled skb instead of separete frags. Doing this has positive side effects in reducing sk_buff by one pointer (nfct_reasm) and also the reams dances in ipvs and conntrack can be removed. Future plan is to remove net/ipv6/netfilter/nf_conntrack_reasm.c entirely and use code in net/ipv6/reassembly.c instead. Signed-off-by: Jiri Pirko <jiri@resnulli.us> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/ip_vs.h32
-rw-r--r--include/net/netfilter/ipv6/nf_defrag_ipv6.h5
2 files changed, 2 insertions, 35 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 4c062ccff9aa..f0c13a386bf3 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size;
109struct ip_vs_iphdr { 109struct ip_vs_iphdr {
110 __u32 len; /* IPv4 simply where L4 starts 110 __u32 len; /* IPv4 simply where L4 starts
111 IPv6 where L4 Transport Header starts */ 111 IPv6 where L4 Transport Header starts */
112 __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
113 __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/ 112 __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
114 __s16 protocol; 113 __s16 protocol;
115 __s32 flags; 114 __s32 flags;
@@ -117,34 +116,12 @@ struct ip_vs_iphdr {
117 union nf_inet_addr daddr; 116 union nf_inet_addr daddr;
118}; 117};
119 118
120/* Dependency to module: nf_defrag_ipv6 */
121#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
122static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
123{
124 return skb->nfct_reasm;
125}
126static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
127 int len, void *buffer,
128 const struct ip_vs_iphdr *ipvsh)
129{
130 if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
131 return skb_header_pointer(skb_nfct_reasm(skb),
132 ipvsh->thoff_reasm, len, buffer);
133
134 return skb_header_pointer(skb, offset, len, buffer);
135}
136#else
137static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
138{
139 return NULL;
140}
141static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, 119static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
142 int len, void *buffer, 120 int len, void *buffer,
143 const struct ip_vs_iphdr *ipvsh) 121 const struct ip_vs_iphdr *ipvsh)
144{ 122{
145 return skb_header_pointer(skb, offset, len, buffer); 123 return skb_header_pointer(skb, offset, len, buffer);
146} 124}
147#endif
148 125
149static inline void 126static inline void
150ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) 127ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
@@ -171,19 +148,12 @@ ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
171 (struct ipv6hdr *)skb_network_header(skb); 148 (struct ipv6hdr *)skb_network_header(skb);
172 iphdr->saddr.in6 = iph->saddr; 149 iphdr->saddr.in6 = iph->saddr;
173 iphdr->daddr.in6 = iph->daddr; 150 iphdr->daddr.in6 = iph->daddr;
174 /* ipv6_find_hdr() updates len, flags, thoff_reasm */ 151 /* ipv6_find_hdr() updates len, flags */
175 iphdr->thoff_reasm = 0;
176 iphdr->len = 0; 152 iphdr->len = 0;
177 iphdr->flags = 0; 153 iphdr->flags = 0;
178 iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1, 154 iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1,
179 &iphdr->fragoffs, 155 &iphdr->fragoffs,
180 &iphdr->flags); 156 &iphdr->flags);
181 /* get proto from re-assembled packet and it's offset */
182 if (skb_nfct_reasm(skb))
183 iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
184 &iphdr->thoff_reasm,
185 -1, NULL, NULL);
186
187 } else 157 } else
188#endif 158#endif
189 { 159 {
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
index fd79c9a1779d..17920d847b40 100644
--- a/include/net/netfilter/ipv6/nf_defrag_ipv6.h
+++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h
@@ -6,10 +6,7 @@ extern void nf_defrag_ipv6_enable(void);
6extern int nf_ct_frag6_init(void); 6extern int nf_ct_frag6_init(void);
7extern void nf_ct_frag6_cleanup(void); 7extern void nf_ct_frag6_cleanup(void);
8extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user); 8extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
9extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, 9extern void nf_ct_frag6_consume_orig(struct sk_buff *skb);
10 struct net_device *in,
11 struct net_device *out,
12 int (*okfn)(struct sk_buff *));
13 10
14struct inet_frags_ctl; 11struct inet_frags_ctl;
15 12