diff options
author | Patrick McHardy <kaber@trash.net> | 2010-07-02 03:32:57 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2010-07-02 03:32:57 -0400 |
commit | 4df53d8bab65cf2c18daebd51a5a4847e03f1943 (patch) | |
tree | f776c088d9d525672eac2e95ef1d183e52d88837 | |
parent | 7eb9282cd0efac08b8377cbd5037ba297c77e3f7 (diff) |
bridge: add per bridge device controls for invoking iptables
Support more fine grained control of bridge netfilter iptables invocation
by adding seperate brnf_call_*tables parameters for each device using the
sysfs interface. Packets are passed to layer 3 netfilter when either the
global parameter or the per bridge parameter is enabled.
Acked-by: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | net/bridge/br_netfilter.c | 31 | ||||
-rw-r--r-- | net/bridge/br_private.h | 3 | ||||
-rw-r--r-- | net/bridge/br_sysfs_br.c | 72 |
3 files changed, 97 insertions, 9 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 6bb6f7c9e6e1..f1d49ae23411 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -55,6 +55,9 @@ 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 | #else | 57 | #else |
58 | #define brnf_call_iptables 1 | ||
59 | #define brnf_call_ip6tables 1 | ||
60 | #define brnf_call_arptables 1 | ||
58 | #define brnf_filter_vlan_tagged 0 | 61 | #define brnf_filter_vlan_tagged 0 |
59 | #define brnf_filter_pppoe_tagged 0 | 62 | #define brnf_filter_pppoe_tagged 0 |
60 | #endif | 63 | #endif |
@@ -543,25 +546,30 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb, | |||
543 | const struct net_device *out, | 546 | const struct net_device *out, |
544 | int (*okfn)(struct sk_buff *)) | 547 | int (*okfn)(struct sk_buff *)) |
545 | { | 548 | { |
549 | struct net_bridge_port *p; | ||
550 | struct net_bridge *br; | ||
546 | struct iphdr *iph; | 551 | struct iphdr *iph; |
547 | __u32 len = nf_bridge_encap_header_len(skb); | 552 | __u32 len = nf_bridge_encap_header_len(skb); |
548 | 553 | ||
549 | if (unlikely(!pskb_may_pull(skb, len))) | 554 | if (unlikely(!pskb_may_pull(skb, len))) |
550 | goto out; | 555 | goto out; |
551 | 556 | ||
557 | p = rcu_dereference(in->br_port); | ||
558 | if (p == NULL) | ||
559 | goto out; | ||
560 | br = p->br; | ||
561 | |||
552 | if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) || | 562 | if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) || |
553 | IS_PPPOE_IPV6(skb)) { | 563 | IS_PPPOE_IPV6(skb)) { |
554 | #ifdef CONFIG_SYSCTL | 564 | if (!brnf_call_ip6tables && !br->nf_call_ip6tables) |
555 | if (!brnf_call_ip6tables) | ||
556 | return NF_ACCEPT; | 565 | return NF_ACCEPT; |
557 | #endif | 566 | |
558 | nf_bridge_pull_encap_header_rcsum(skb); | 567 | nf_bridge_pull_encap_header_rcsum(skb); |
559 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); | 568 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); |
560 | } | 569 | } |
561 | #ifdef CONFIG_SYSCTL | 570 | |
562 | if (!brnf_call_iptables) | 571 | if (!brnf_call_iptables && !br->nf_call_iptables) |
563 | return NF_ACCEPT; | 572 | return NF_ACCEPT; |
564 | #endif | ||
565 | 573 | ||
566 | if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb) && | 574 | if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb) && |
567 | !IS_PPPOE_IP(skb)) | 575 | !IS_PPPOE_IP(skb)) |
@@ -714,12 +722,17 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb, | |||
714 | const struct net_device *out, | 722 | const struct net_device *out, |
715 | int (*okfn)(struct sk_buff *)) | 723 | int (*okfn)(struct sk_buff *)) |
716 | { | 724 | { |
725 | struct net_bridge_port *p; | ||
726 | struct net_bridge *br; | ||
717 | struct net_device **d = (struct net_device **)(skb->cb); | 727 | struct net_device **d = (struct net_device **)(skb->cb); |
718 | 728 | ||
719 | #ifdef CONFIG_SYSCTL | 729 | p = rcu_dereference(out->br_port); |
720 | if (!brnf_call_arptables) | 730 | if (p == NULL) |
731 | return NF_ACCEPT; | ||
732 | br = p->br; | ||
733 | |||
734 | if (!brnf_call_arptables && !br->nf_call_arptables) | ||
721 | return NF_ACCEPT; | 735 | return NF_ACCEPT; |
722 | #endif | ||
723 | 736 | ||
724 | if (skb->protocol != htons(ETH_P_ARP)) { | 737 | if (skb->protocol != htons(ETH_P_ARP)) { |
725 | if (!IS_VLAN_ARP(skb)) | 738 | if (!IS_VLAN_ARP(skb)) |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index c83519b555bb..7484065da303 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -164,6 +164,9 @@ struct net_bridge | |||
164 | unsigned long feature_mask; | 164 | unsigned long feature_mask; |
165 | #ifdef CONFIG_BRIDGE_NETFILTER | 165 | #ifdef CONFIG_BRIDGE_NETFILTER |
166 | struct rtable fake_rtable; | 166 | struct rtable fake_rtable; |
167 | bool nf_call_iptables; | ||
168 | bool nf_call_ip6tables; | ||
169 | bool nf_call_arptables; | ||
167 | #endif | 170 | #endif |
168 | unsigned long flags; | 171 | unsigned long flags; |
169 | #define BR_SET_MAC_ADDR 0x00000001 | 172 | #define BR_SET_MAC_ADDR 0x00000001 |
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 486b8f3861d2..5c1e5559ebba 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
@@ -611,6 +611,73 @@ static DEVICE_ATTR(multicast_startup_query_interval, S_IRUGO | S_IWUSR, | |||
611 | show_multicast_startup_query_interval, | 611 | show_multicast_startup_query_interval, |
612 | store_multicast_startup_query_interval); | 612 | store_multicast_startup_query_interval); |
613 | #endif | 613 | #endif |
614 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
615 | static ssize_t show_nf_call_iptables( | ||
616 | struct device *d, struct device_attribute *attr, char *buf) | ||
617 | { | ||
618 | struct net_bridge *br = to_bridge(d); | ||
619 | return sprintf(buf, "%u\n", br->nf_call_iptables); | ||
620 | } | ||
621 | |||
622 | static int set_nf_call_iptables(struct net_bridge *br, unsigned long val) | ||
623 | { | ||
624 | br->nf_call_iptables = val ? true : false; | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static ssize_t store_nf_call_iptables( | ||
629 | struct device *d, struct device_attribute *attr, const char *buf, | ||
630 | size_t len) | ||
631 | { | ||
632 | return store_bridge_parm(d, buf, len, set_nf_call_iptables); | ||
633 | } | ||
634 | static DEVICE_ATTR(nf_call_iptables, S_IRUGO | S_IWUSR, | ||
635 | show_nf_call_iptables, store_nf_call_iptables); | ||
636 | |||
637 | static ssize_t show_nf_call_ip6tables( | ||
638 | struct device *d, struct device_attribute *attr, char *buf) | ||
639 | { | ||
640 | struct net_bridge *br = to_bridge(d); | ||
641 | return sprintf(buf, "%u\n", br->nf_call_ip6tables); | ||
642 | } | ||
643 | |||
644 | static int set_nf_call_ip6tables(struct net_bridge *br, unsigned long val) | ||
645 | { | ||
646 | br->nf_call_ip6tables = val ? true : false; | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | static ssize_t store_nf_call_ip6tables( | ||
651 | struct device *d, struct device_attribute *attr, const char *buf, | ||
652 | size_t len) | ||
653 | { | ||
654 | return store_bridge_parm(d, buf, len, set_nf_call_ip6tables); | ||
655 | } | ||
656 | static DEVICE_ATTR(nf_call_ip6tables, S_IRUGO | S_IWUSR, | ||
657 | show_nf_call_ip6tables, store_nf_call_ip6tables); | ||
658 | |||
659 | static ssize_t show_nf_call_arptables( | ||
660 | struct device *d, struct device_attribute *attr, char *buf) | ||
661 | { | ||
662 | struct net_bridge *br = to_bridge(d); | ||
663 | return sprintf(buf, "%u\n", br->nf_call_arptables); | ||
664 | } | ||
665 | |||
666 | static int set_nf_call_arptables(struct net_bridge *br, unsigned long val) | ||
667 | { | ||
668 | br->nf_call_arptables = val ? true : false; | ||
669 | return 0; | ||
670 | } | ||
671 | |||
672 | static ssize_t store_nf_call_arptables( | ||
673 | struct device *d, struct device_attribute *attr, const char *buf, | ||
674 | size_t len) | ||
675 | { | ||
676 | return store_bridge_parm(d, buf, len, set_nf_call_arptables); | ||
677 | } | ||
678 | static DEVICE_ATTR(nf_call_arptables, S_IRUGO | S_IWUSR, | ||
679 | show_nf_call_arptables, store_nf_call_arptables); | ||
680 | #endif | ||
614 | 681 | ||
615 | static struct attribute *bridge_attrs[] = { | 682 | static struct attribute *bridge_attrs[] = { |
616 | &dev_attr_forward_delay.attr, | 683 | &dev_attr_forward_delay.attr, |
@@ -645,6 +712,11 @@ static struct attribute *bridge_attrs[] = { | |||
645 | &dev_attr_multicast_query_response_interval.attr, | 712 | &dev_attr_multicast_query_response_interval.attr, |
646 | &dev_attr_multicast_startup_query_interval.attr, | 713 | &dev_attr_multicast_startup_query_interval.attr, |
647 | #endif | 714 | #endif |
715 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
716 | &dev_attr_nf_call_iptables.attr, | ||
717 | &dev_attr_nf_call_ip6tables.attr, | ||
718 | &dev_attr_nf_call_arptables.attr, | ||
719 | #endif | ||
648 | NULL | 720 | NULL |
649 | }; | 721 | }; |
650 | 722 | ||