aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2010-07-02 03:32:57 -0400
committerPatrick McHardy <kaber@trash.net>2010-07-02 03:32:57 -0400
commit4df53d8bab65cf2c18daebd51a5a4847e03f1943 (patch)
treef776c088d9d525672eac2e95ef1d183e52d88837
parent7eb9282cd0efac08b8377cbd5037ba297c77e3f7 (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.c31
-rw-r--r--net/bridge/br_private.h3
-rw-r--r--net/bridge/br_sysfs_br.c72
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;
55static int brnf_filter_vlan_tagged __read_mostly = 0; 55static int brnf_filter_vlan_tagged __read_mostly = 0;
56static int brnf_filter_pppoe_tagged __read_mostly = 0; 56static 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
615static 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
622static 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
628static 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}
634static DEVICE_ATTR(nf_call_iptables, S_IRUGO | S_IWUSR,
635 show_nf_call_iptables, store_nf_call_iptables);
636
637static 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
644static 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
650static 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}
656static DEVICE_ATTR(nf_call_ip6tables, S_IRUGO | S_IWUSR,
657 show_nf_call_ip6tables, store_nf_call_ip6tables);
658
659static 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
666static 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
672static 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}
678static DEVICE_ATTR(nf_call_arptables, S_IRUGO | S_IWUSR,
679 show_nf_call_arptables, store_nf_call_arptables);
680#endif
614 681
615static struct attribute *bridge_attrs[] = { 682static 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