diff options
author | Florian Westphal <fw@strlen.de> | 2015-05-20 07:42:25 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-05-20 07:51:25 -0400 |
commit | faecbb45ebefb20260ad4a631e011e93c896cb73 (patch) | |
tree | b03c38d28eb48c1ee2f64abb43338f7457ec95ad | |
parent | 1086bbe97a074844188c6c988fa0b1a98c3ccbb9 (diff) |
Revert "netfilter: bridge: query conntrack about skb dnat"
This reverts commit c055d5b03bb4cb69d349d787c9787c0383abd8b2.
There are two issues:
'dnat_took_place' made me think that this is related to
-j DNAT/MASQUERADE.
But thats only one part of the story. This is also relevant for SNAT
when we undo snat translation in reverse/reply direction.
Furthermore, I originally wanted to do this mainly to avoid
storing ipv6 addresses once we make DNAT/REDIRECT work
for ipv6 on bridges.
However, I forgot about SNPT/DNPT which is stateless.
So we can't escape storing address for ipv6 anyway. Might as
well do it for ipv4 too.
Reported-and-tested-by: Bernhard Thaler <bernhard.thaler@wvnet.at>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r-- | include/linux/skbuff.h | 1 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 27 |
2 files changed, 10 insertions, 18 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 66e374d62f64..f15154a879c7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -176,6 +176,7 @@ struct nf_bridge_info { | |||
176 | struct net_device *physindev; | 176 | struct net_device *physindev; |
177 | struct net_device *physoutdev; | 177 | struct net_device *physoutdev; |
178 | char neigh_header[8]; | 178 | char neigh_header[8]; |
179 | __be32 ipv4_daddr; | ||
179 | }; | 180 | }; |
180 | #endif | 181 | #endif |
181 | 182 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index ab55e2472beb..60ddfbeb47f5 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -37,10 +37,6 @@ | |||
37 | #include <net/route.h> | 37 | #include <net/route.h> |
38 | #include <net/netfilter/br_netfilter.h> | 38 | #include <net/netfilter/br_netfilter.h> |
39 | 39 | ||
40 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | ||
41 | #include <net/netfilter/nf_conntrack.h> | ||
42 | #endif | ||
43 | |||
44 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
45 | #include "br_private.h" | 41 | #include "br_private.h" |
46 | #ifdef CONFIG_SYSCTL | 42 | #ifdef CONFIG_SYSCTL |
@@ -350,24 +346,15 @@ free_skb: | |||
350 | return 0; | 346 | return 0; |
351 | } | 347 | } |
352 | 348 | ||
353 | static bool dnat_took_place(const struct sk_buff *skb) | 349 | static bool daddr_was_changed(const struct sk_buff *skb, |
350 | const struct nf_bridge_info *nf_bridge) | ||
354 | { | 351 | { |
355 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) | 352 | return ip_hdr(skb)->daddr != nf_bridge->ipv4_daddr; |
356 | enum ip_conntrack_info ctinfo; | ||
357 | struct nf_conn *ct; | ||
358 | |||
359 | ct = nf_ct_get(skb, &ctinfo); | ||
360 | if (!ct || nf_ct_is_untracked(ct)) | ||
361 | return false; | ||
362 | |||
363 | return test_bit(IPS_DST_NAT_BIT, &ct->status); | ||
364 | #else | ||
365 | return false; | ||
366 | #endif | ||
367 | } | 353 | } |
368 | 354 | ||
369 | /* This requires some explaining. If DNAT has taken place, | 355 | /* This requires some explaining. If DNAT has taken place, |
370 | * we will need to fix up the destination Ethernet address. | 356 | * we will need to fix up the destination Ethernet address. |
357 | * This is also true when SNAT takes place (for the reply direction). | ||
371 | * | 358 | * |
372 | * There are two cases to consider: | 359 | * There are two cases to consider: |
373 | * 1. The packet was DNAT'ed to a device in the same bridge | 360 | * 1. The packet was DNAT'ed to a device in the same bridge |
@@ -421,7 +408,7 @@ static int br_nf_pre_routing_finish(struct sock *sk, struct sk_buff *skb) | |||
421 | nf_bridge->pkt_otherhost = false; | 408 | nf_bridge->pkt_otherhost = false; |
422 | } | 409 | } |
423 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | 410 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; |
424 | if (dnat_took_place(skb)) { | 411 | if (daddr_was_changed(skb, nf_bridge)) { |
425 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { | 412 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { |
426 | struct in_device *in_dev = __in_dev_get_rcu(dev); | 413 | struct in_device *in_dev = __in_dev_get_rcu(dev); |
427 | 414 | ||
@@ -632,6 +619,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, | |||
632 | struct sk_buff *skb, | 619 | struct sk_buff *skb, |
633 | const struct nf_hook_state *state) | 620 | const struct nf_hook_state *state) |
634 | { | 621 | { |
622 | struct nf_bridge_info *nf_bridge; | ||
635 | struct net_bridge_port *p; | 623 | struct net_bridge_port *p; |
636 | struct net_bridge *br; | 624 | struct net_bridge *br; |
637 | __u32 len = nf_bridge_encap_header_len(skb); | 625 | __u32 len = nf_bridge_encap_header_len(skb); |
@@ -669,6 +657,9 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops, | |||
669 | if (!setup_pre_routing(skb)) | 657 | if (!setup_pre_routing(skb)) |
670 | return NF_DROP; | 658 | return NF_DROP; |
671 | 659 | ||
660 | nf_bridge = nf_bridge_info_get(skb); | ||
661 | nf_bridge->ipv4_daddr = ip_hdr(skb)->daddr; | ||
662 | |||
672 | skb->protocol = htons(ETH_P_IP); | 663 | skb->protocol = htons(ETH_P_IP); |
673 | 664 | ||
674 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->sk, skb, | 665 | NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, state->sk, skb, |