diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-05-08 13:36:44 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2012-05-08 13:36:47 -0400 |
commit | 4981682cc19733f3ca43d3abd81dd4adbc9005d5 (patch) | |
tree | 6c4583e26b8f12559defc11d0c141011a71e3de1 /net/bridge | |
parent | ac3a546ac89fdf3c4b50e40039a5a7f6df4dda72 (diff) |
netfilter: bridge: optionally set indev to vlan
if net.bridge.bridge-nf-filter-vlan-tagged sysctl is enabled, bridge
netfilter removes the vlan header temporarily and then feeds the packet
to ip(6)tables.
When the new "bridge-nf-pass-vlan-input-device" sysctl is on
(default off), then bridge netfilter will also set the
in-interface to the vlan interface; if such an interface exists.
This is needed to make iptables REDIRECT target work with
"vlan-on-top-of-bridge" setups and to allow use of "iptables -i" to
match the vlan device name.
Also update Documentation with current brnf default settings.
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Bart De Schuymer <bdschuym@pandora.be>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_netfilter.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 53f083686ae4..dce55d4ee83b 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -54,12 +54,14 @@ static int brnf_call_ip6tables __read_mostly = 1; | |||
54 | static int brnf_call_arptables __read_mostly = 1; | 54 | static int brnf_call_arptables __read_mostly = 1; |
55 | static int brnf_filter_vlan_tagged __read_mostly = 0; | 55 | static int brnf_filter_vlan_tagged __read_mostly = 0; |
56 | static int brnf_filter_pppoe_tagged __read_mostly = 0; | 56 | static int brnf_filter_pppoe_tagged __read_mostly = 0; |
57 | static int brnf_pass_vlan_indev __read_mostly = 0; | ||
57 | #else | 58 | #else |
58 | #define brnf_call_iptables 1 | 59 | #define brnf_call_iptables 1 |
59 | #define brnf_call_ip6tables 1 | 60 | #define brnf_call_ip6tables 1 |
60 | #define brnf_call_arptables 1 | 61 | #define brnf_call_arptables 1 |
61 | #define brnf_filter_vlan_tagged 0 | 62 | #define brnf_filter_vlan_tagged 0 |
62 | #define brnf_filter_pppoe_tagged 0 | 63 | #define brnf_filter_pppoe_tagged 0 |
64 | #define brnf_pass_vlan_indev 0 | ||
63 | #endif | 65 | #endif |
64 | 66 | ||
65 | #define IS_IP(skb) \ | 67 | #define IS_IP(skb) \ |
@@ -503,6 +505,19 @@ bridged_dnat: | |||
503 | return 0; | 505 | return 0; |
504 | } | 506 | } |
505 | 507 | ||
508 | static struct net_device *brnf_get_logical_dev(struct sk_buff *skb, const struct net_device *dev) | ||
509 | { | ||
510 | struct net_device *vlan, *br; | ||
511 | |||
512 | br = bridge_parent(dev); | ||
513 | if (brnf_pass_vlan_indev == 0 || !vlan_tx_tag_present(skb)) | ||
514 | return br; | ||
515 | |||
516 | vlan = __vlan_find_dev_deep(br, vlan_tx_tag_get(skb) & VLAN_VID_MASK); | ||
517 | |||
518 | return vlan ? vlan : br; | ||
519 | } | ||
520 | |||
506 | /* Some common code for IPv4/IPv6 */ | 521 | /* Some common code for IPv4/IPv6 */ |
507 | static struct net_device *setup_pre_routing(struct sk_buff *skb) | 522 | static struct net_device *setup_pre_routing(struct sk_buff *skb) |
508 | { | 523 | { |
@@ -515,7 +530,7 @@ static struct net_device *setup_pre_routing(struct sk_buff *skb) | |||
515 | 530 | ||
516 | nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; | 531 | nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; |
517 | nf_bridge->physindev = skb->dev; | 532 | nf_bridge->physindev = skb->dev; |
518 | skb->dev = bridge_parent(skb->dev); | 533 | skb->dev = brnf_get_logical_dev(skb, skb->dev); |
519 | if (skb->protocol == htons(ETH_P_8021Q)) | 534 | if (skb->protocol == htons(ETH_P_8021Q)) |
520 | nf_bridge->mask |= BRNF_8021Q; | 535 | nf_bridge->mask |= BRNF_8021Q; |
521 | else if (skb->protocol == htons(ETH_P_PPP_SES)) | 536 | else if (skb->protocol == htons(ETH_P_PPP_SES)) |
@@ -774,7 +789,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, | |||
774 | else | 789 | else |
775 | skb->protocol = htons(ETH_P_IPV6); | 790 | skb->protocol = htons(ETH_P_IPV6); |
776 | 791 | ||
777 | NF_HOOK(pf, NF_INET_FORWARD, skb, bridge_parent(in), parent, | 792 | NF_HOOK(pf, NF_INET_FORWARD, skb, brnf_get_logical_dev(skb, in), parent, |
778 | br_nf_forward_finish); | 793 | br_nf_forward_finish); |
779 | 794 | ||
780 | return NF_STOLEN; | 795 | return NF_STOLEN; |
@@ -1002,6 +1017,13 @@ static ctl_table brnf_table[] = { | |||
1002 | .mode = 0644, | 1017 | .mode = 0644, |
1003 | .proc_handler = brnf_sysctl_call_tables, | 1018 | .proc_handler = brnf_sysctl_call_tables, |
1004 | }, | 1019 | }, |
1020 | { | ||
1021 | .procname = "bridge-nf-pass-vlan-input-dev", | ||
1022 | .data = &brnf_pass_vlan_indev, | ||
1023 | .maxlen = sizeof(int), | ||
1024 | .mode = 0644, | ||
1025 | .proc_handler = brnf_sysctl_call_tables, | ||
1026 | }, | ||
1005 | { } | 1027 | { } |
1006 | }; | 1028 | }; |
1007 | #endif | 1029 | #endif |