diff options
author | Jiri Pirko <jiri@resnulli.us> | 2013-11-06 11:52:20 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-11 00:19:35 -0500 |
commit | 6aafeef03b9d9ecf255f3a80ed85ee070260e1ae (patch) | |
tree | 48c7f8ff1709c9874342c02c7039d4431a00b333 /include/net/ip_vs.h | |
parent | 9037c3579a277f3a23ba476664629fda8c35f7c4 (diff) |
netfilter: push reasm skb through instead of original frag skbs
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>
Diffstat (limited to 'include/net/ip_vs.h')
-rw-r--r-- | include/net/ip_vs.h | 32 |
1 files changed, 1 insertions, 31 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index cd7275f9c463..5679d927562b 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -109,7 +109,6 @@ extern int ip_vs_conn_tab_size; | |||
109 | struct ip_vs_iphdr { | 109 | struct 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) | ||
122 | static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) | ||
123 | { | ||
124 | return skb->nfct_reasm; | ||
125 | } | ||
126 | static 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 | ||
137 | static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb) | ||
138 | { | ||
139 | return NULL; | ||
140 | } | ||
141 | static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset, | 119 | static 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 | ||
149 | static inline void | 126 | static inline void |
150 | ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr) | 127 | ip_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 | { |