diff options
author | Bart De Schuymer <bdschuym@pandora.be> | 2010-04-15 06:14:51 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-04-15 06:14:51 -0400 |
commit | ea2d9b41bd418894d1ee25de1642c3325d71c397 (patch) | |
tree | e8187786c8d83123da104476fc0eb7132ec29045 /net/bridge | |
parent | 9c6eb28aca52d562f3ffbaebaa56385df9972a43 (diff) |
netfilter: bridge-netfilter: simplify IP DNAT
Remove br_netfilter.c::br_nf_local_out(). The function
br_nf_local_out() was needed because the PF_BRIDGE::LOCAL_OUT hook
could be called when IP DNAT happens on to-be-bridged traffic. The
new scheme eliminates this mess.
Signed-off-by: Bart De Schuymer <bdschuym@pandora.be>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_device.c | 9 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 114 |
2 files changed, 26 insertions, 97 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 5b8a6e73b02f..007bde87415d 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/etherdevice.h> | 16 | #include <linux/etherdevice.h> |
17 | #include <linux/ethtool.h> | 17 | #include <linux/ethtool.h> |
18 | 18 | #include <linux/netfilter_bridge.h> | |
19 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
20 | #include "br_private.h" | 20 | #include "br_private.h" |
21 | 21 | ||
@@ -28,6 +28,13 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
28 | struct net_bridge_mdb_entry *mdst; | 28 | struct net_bridge_mdb_entry *mdst; |
29 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | 29 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); |
30 | 30 | ||
31 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
32 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | ||
33 | br_nf_pre_routing_finish_bridge_slow(skb); | ||
34 | return NETDEV_TX_OK; | ||
35 | } | ||
36 | #endif | ||
37 | |||
31 | brstats->tx_packets++; | 38 | brstats->tx_packets++; |
32 | brstats->tx_bytes += skb->len; | 39 | brstats->tx_bytes += skb->len; |
33 | 40 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index dd6f538ba0b0..05dc6304992c 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -246,8 +246,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | |||
246 | } | 246 | } |
247 | 247 | ||
248 | /* This requires some explaining. If DNAT has taken place, | 248 | /* This requires some explaining. If DNAT has taken place, |
249 | * we will need to fix up the destination Ethernet address, | 249 | * we will need to fix up the destination Ethernet address. |
250 | * and this is a tricky process. | ||
251 | * | 250 | * |
252 | * There are two cases to consider: | 251 | * There are two cases to consider: |
253 | * 1. The packet was DNAT'ed to a device in the same bridge | 252 | * 1. The packet was DNAT'ed to a device in the same bridge |
@@ -261,52 +260,38 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | |||
261 | * call ip_route_input() and to look at skb->dst->dev, which is | 260 | * call ip_route_input() and to look at skb->dst->dev, which is |
262 | * changed to the destination device if ip_route_input() succeeds. | 261 | * changed to the destination device if ip_route_input() succeeds. |
263 | * | 262 | * |
264 | * Let us first consider the case that ip_route_input() succeeds: | 263 | * Let's first consider the case that ip_route_input() succeeds: |
265 | * | ||
266 | * If skb->dst->dev equals the logical bridge device the packet | ||
267 | * came in on, we can consider this bridging. The packet is passed | ||
268 | * through the neighbour output function to build a new destination | ||
269 | * MAC address, which will make the packet enter br_nf_local_out() | ||
270 | * not much later. In that function it is assured that the iptables | ||
271 | * FORWARD chain is traversed for the packet. | ||
272 | * | 264 | * |
265 | * If the output device equals the logical bridge device the packet | ||
266 | * came in on, we can consider this bridging. The corresponding MAC | ||
267 | * address will be obtained in br_nf_pre_routing_finish_bridge. | ||
273 | * Otherwise, the packet is considered to be routed and we just | 268 | * Otherwise, the packet is considered to be routed and we just |
274 | * change the destination MAC address so that the packet will | 269 | * change the destination MAC address so that the packet will |
275 | * later be passed up to the IP stack to be routed. For a redirected | 270 | * later be passed up to the IP stack to be routed. For a redirected |
276 | * packet, ip_route_input() will give back the localhost as output device, | 271 | * packet, ip_route_input() will give back the localhost as output device, |
277 | * which differs from the bridge device. | 272 | * which differs from the bridge device. |
278 | * | 273 | * |
279 | * Let us now consider the case that ip_route_input() fails: | 274 | * Let's now consider the case that ip_route_input() fails: |
280 | * | 275 | * |
281 | * This can be because the destination address is martian, in which case | 276 | * This can be because the destination address is martian, in which case |
282 | * the packet will be dropped. | 277 | * the packet will be dropped. |
283 | * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input() | 278 | * If IP forwarding is disabled, ip_route_input() will fail, while |
284 | * will fail, while __ip_route_output_key() will return success. The source | 279 | * ip_route_output_key() can return success. The source |
285 | * address for __ip_route_output_key() is set to zero, so __ip_route_output_key | 280 | * address for ip_route_output_key() is set to zero, so ip_route_output_key() |
286 | * thinks we're handling a locally generated packet and won't care | 281 | * thinks we're handling a locally generated packet and won't care |
287 | * if IP forwarding is allowed. We send a warning message to the users's | 282 | * if IP forwarding is enabled. If the output device equals the logical bridge |
288 | * log telling her to put IP forwarding on. | 283 | * device, we proceed as if ip_route_input() succeeded. If it differs from the |
289 | * | 284 | * logical bridge port or if ip_route_output_key() fails we drop the packet. |
290 | * ip_route_input() will also fail if there is no route available. | 285 | */ |
291 | * In that case we just drop the packet. | 286 | |
292 | * | ||
293 | * --Lennert, 20020411 | ||
294 | * --Bart, 20020416 (updated) | ||
295 | * --Bart, 20021007 (updated) | ||
296 | * --Bart, 20062711 (updated) */ | ||
297 | static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | 287 | static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) |
298 | { | 288 | { |
299 | if (skb->pkt_type == PACKET_OTHERHOST) { | ||
300 | skb->pkt_type = PACKET_HOST; | ||
301 | skb->nf_bridge->mask |= BRNF_PKT_TYPE; | ||
302 | } | ||
303 | skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | ||
304 | |||
305 | skb->dev = bridge_parent(skb->dev); | 289 | skb->dev = bridge_parent(skb->dev); |
306 | if (skb->dev) { | 290 | if (skb->dev) { |
307 | struct dst_entry *dst = skb_dst(skb); | 291 | struct dst_entry *dst = skb_dst(skb); |
308 | 292 | ||
309 | nf_bridge_pull_encap_header(skb); | 293 | nf_bridge_pull_encap_header(skb); |
294 | skb->nf_bridge->mask |= BRNF_BRIDGED_DNAT; | ||
310 | 295 | ||
311 | if (dst->hh) | 296 | if (dst->hh) |
312 | return neigh_hh_output(dst->hh, skb); | 297 | return neigh_hh_output(dst->hh, skb); |
@@ -368,9 +353,6 @@ free_skb: | |||
368 | } else { | 353 | } else { |
369 | if (skb_dst(skb)->dev == dev) { | 354 | if (skb_dst(skb)->dev == dev) { |
370 | bridged_dnat: | 355 | bridged_dnat: |
371 | /* Tell br_nf_local_out this is a | ||
372 | * bridged frame */ | ||
373 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | ||
374 | skb->dev = nf_bridge->physindev; | 356 | skb->dev = nf_bridge->physindev; |
375 | nf_bridge_push_encap_header(skb); | 357 | nf_bridge_push_encap_header(skb); |
376 | NF_HOOK_THRESH(NFPROTO_BRIDGE, | 358 | NF_HOOK_THRESH(NFPROTO_BRIDGE, |
@@ -721,54 +703,6 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb, | |||
721 | return NF_STOLEN; | 703 | return NF_STOLEN; |
722 | } | 704 | } |
723 | 705 | ||
724 | /* PF_BRIDGE/LOCAL_OUT *********************************************** | ||
725 | * | ||
726 | * This function sees both locally originated IP packets and forwarded | ||
727 | * IP packets (in both cases the destination device is a bridge | ||
728 | * device). It also sees bridged-and-DNAT'ed packets. | ||
729 | * | ||
730 | * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged | ||
731 | * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward() | ||
732 | * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority | ||
733 | * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor | ||
734 | * will be executed. | ||
735 | */ | ||
736 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff *skb, | ||
737 | const struct net_device *in, | ||
738 | const struct net_device *out, | ||
739 | int (*okfn)(struct sk_buff *)) | ||
740 | { | ||
741 | struct net_device *realindev; | ||
742 | struct nf_bridge_info *nf_bridge; | ||
743 | |||
744 | if (!skb->nf_bridge) | ||
745 | return NF_ACCEPT; | ||
746 | |||
747 | /* Need exclusive nf_bridge_info since we might have multiple | ||
748 | * different physoutdevs. */ | ||
749 | if (!nf_bridge_unshare(skb)) | ||
750 | return NF_DROP; | ||
751 | |||
752 | nf_bridge = skb->nf_bridge; | ||
753 | if (!(nf_bridge->mask & BRNF_BRIDGED_DNAT)) | ||
754 | return NF_ACCEPT; | ||
755 | |||
756 | /* Bridged, take PF_BRIDGE/FORWARD. | ||
757 | * (see big note in front of br_nf_pre_routing_finish) */ | ||
758 | nf_bridge->physoutdev = skb->dev; | ||
759 | realindev = nf_bridge->physindev; | ||
760 | |||
761 | if (nf_bridge->mask & BRNF_PKT_TYPE) { | ||
762 | skb->pkt_type = PACKET_OTHERHOST; | ||
763 | nf_bridge->mask ^= BRNF_PKT_TYPE; | ||
764 | } | ||
765 | nf_bridge_push_encap_header(skb); | ||
766 | |||
767 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev, | ||
768 | br_forward_finish); | ||
769 | return NF_STOLEN; | ||
770 | } | ||
771 | |||
772 | #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) | 706 | #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) |
773 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) | 707 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) |
774 | { | 708 | { |
@@ -797,10 +731,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | |||
797 | struct net_device *realoutdev = bridge_parent(skb->dev); | 731 | struct net_device *realoutdev = bridge_parent(skb->dev); |
798 | u_int8_t pf; | 732 | u_int8_t pf; |
799 | 733 | ||
800 | if (!nf_bridge) | 734 | if (!nf_bridge || !(nf_bridge->mask & BRNF_BRIDGED)) |
801 | return NF_ACCEPT; | ||
802 | |||
803 | if (!(nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT))) | ||
804 | return NF_ACCEPT; | 735 | return NF_ACCEPT; |
805 | 736 | ||
806 | if (!realoutdev) | 737 | if (!realoutdev) |
@@ -847,10 +778,8 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb, | |||
847 | return NF_ACCEPT; | 778 | return NF_ACCEPT; |
848 | } | 779 | } |
849 | 780 | ||
850 | /* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent | 781 | /* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because |
851 | * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input. | 782 | * br_dev_queue_push_xmit is called afterwards */ |
852 | * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because | ||
853 | * ip_refrag() can return NF_STOLEN. */ | ||
854 | static struct nf_hook_ops br_nf_ops[] __read_mostly = { | 783 | static struct nf_hook_ops br_nf_ops[] __read_mostly = { |
855 | { | 784 | { |
856 | .hook = br_nf_pre_routing, | 785 | .hook = br_nf_pre_routing, |
@@ -881,13 +810,6 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = { | |||
881 | .priority = NF_BR_PRI_BRNF, | 810 | .priority = NF_BR_PRI_BRNF, |
882 | }, | 811 | }, |
883 | { | 812 | { |
884 | .hook = br_nf_local_out, | ||
885 | .owner = THIS_MODULE, | ||
886 | .pf = PF_BRIDGE, | ||
887 | .hooknum = NF_BR_LOCAL_OUT, | ||
888 | .priority = NF_BR_PRI_FIRST, | ||
889 | }, | ||
890 | { | ||
891 | .hook = br_nf_post_routing, | 813 | .hook = br_nf_post_routing, |
892 | .owner = THIS_MODULE, | 814 | .owner = THIS_MODULE, |
893 | .pf = PF_BRIDGE, | 815 | .pf = PF_BRIDGE, |