aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2015-05-20 07:42:25 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2015-05-20 07:51:25 -0400
commitfaecbb45ebefb20260ad4a631e011e93c896cb73 (patch)
treeb03c38d28eb48c1ee2f64abb43338f7457ec95ad
parent1086bbe97a074844188c6c988fa0b1a98c3ccbb9 (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.h1
-rw-r--r--net/bridge/br_netfilter.c27
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
353static bool dnat_took_place(const struct sk_buff *skb) 349static 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,