diff options
author | Patrick McHardy <kaber@trash.net> | 2006-02-20 01:29:47 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-02-20 01:29:47 -0500 |
commit | 8e249f088131cde5f77fd073bf0b0e8b3e9ea4ac (patch) | |
tree | e0113097593dd2b805310bf525b0d2a6823f0a06 /net/ipv4 | |
parent | 669d32a293a348e692c365ddac2b23f3b907fcf1 (diff) |
[NETFILTER]: Fix outgoing redirects to loopback
When redirecting an outgoing packet to loopback, it keeps the original
conntrack reference and information from the outgoing path, which
falsely triggers the check for DNAT on input and the dst_entry is
released to trigger rerouting. ip_route_input refuses to route the
packet because it has a local source address and it is dropped.
Look at the packet itself to dermine if it was NATed. Also fix a
missing inversion that causes unneccesary xfrm lookups.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/ip_nat_standalone.c | 16 |
1 files changed, 5 insertions, 11 deletions
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 7c3f7d380240..ab1f88fa21ec 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -200,20 +200,14 @@ ip_nat_in(unsigned int hooknum, | |||
200 | const struct net_device *out, | 200 | const struct net_device *out, |
201 | int (*okfn)(struct sk_buff *)) | 201 | int (*okfn)(struct sk_buff *)) |
202 | { | 202 | { |
203 | struct ip_conntrack *ct; | ||
204 | enum ip_conntrack_info ctinfo; | ||
205 | unsigned int ret; | 203 | unsigned int ret; |
204 | u_int32_t daddr = (*pskb)->nh.iph->daddr; | ||
206 | 205 | ||
207 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); | 206 | ret = ip_nat_fn(hooknum, pskb, in, out, okfn); |
208 | if (ret != NF_DROP && ret != NF_STOLEN | 207 | if (ret != NF_DROP && ret != NF_STOLEN |
209 | && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { | 208 | && daddr != (*pskb)->nh.iph->daddr) { |
210 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 209 | dst_release((*pskb)->dst); |
211 | 210 | (*pskb)->dst = NULL; | |
212 | if (ct->tuplehash[dir].tuple.dst.ip != | ||
213 | ct->tuplehash[!dir].tuple.src.ip) { | ||
214 | dst_release((*pskb)->dst); | ||
215 | (*pskb)->dst = NULL; | ||
216 | } | ||
217 | } | 211 | } |
218 | return ret; | 212 | return ret; |
219 | } | 213 | } |
@@ -276,7 +270,7 @@ ip_nat_local_fn(unsigned int hooknum, | |||
276 | ct->tuplehash[!dir].tuple.src.ip | 270 | ct->tuplehash[!dir].tuple.src.ip |
277 | #ifdef CONFIG_XFRM | 271 | #ifdef CONFIG_XFRM |
278 | || ct->tuplehash[dir].tuple.dst.u.all != | 272 | || ct->tuplehash[dir].tuple.dst.u.all != |
279 | ct->tuplehash[dir].tuple.src.u.all | 273 | ct->tuplehash[!dir].tuple.src.u.all |
280 | #endif | 274 | #endif |
281 | ) | 275 | ) |
282 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; | 276 | return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; |