aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_forward.c3
-rw-r--r--net/bridge/br_if.c7
-rw-r--r--net/bridge/br_netfilter.c98
-rw-r--r--net/bridge/br_private.h6
-rw-r--r--net/bridge/br_stp.c2
-rw-r--r--net/bridge/br_sysfs_if.c17
-rw-r--r--net/bridge/netfilter/ebt_log.c29
-rw-r--r--net/bridge/netfilter/ebt_ulog.c2
-rw-r--r--net/bridge/netfilter/ebtable_broute.c2
-rw-r--r--net/bridge/netfilter/ebtable_filter.c8
-rw-r--r--net/bridge/netfilter/ebtable_nat.c6
-rw-r--r--net/bridge/netfilter/ebtables.c13
13 files changed, 114 insertions, 83 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 18538d7460d7..07a07770c8b6 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -20,7 +20,7 @@
#include "br_private.h"
/* net device transmit always called with no BH (preempt_disabled) */
-int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_bridge *br = netdev_priv(dev);
const unsigned char *dest = skb->data;
@@ -39,7 +39,7 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
else
br_flood_deliver(br, skb);
- return 0;
+ return NETDEV_TX_OK;
}
static int br_dev_open(struct net_device *dev)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d2c27c808d3b..bc1704ac6cd9 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -22,7 +22,8 @@
static inline int should_deliver(const struct net_bridge_port *p,
const struct sk_buff *skb)
{
- return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
+ return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
+ p->state == BR_STATE_FORWARDING);
}
static inline unsigned packet_length(const struct sk_buff *skb)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index eb404dc3ed6e..142ebac14176 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -256,6 +256,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
p->path_cost = port_cost(dev);
p->priority = 0x8000 >> BR_PORT_BITS;
p->port_no = index;
+ p->flags = 0;
br_init_port(p);
p->state = BR_STATE_DISABLED;
br_stp_port_timer_init(p);
@@ -263,6 +264,10 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
return p;
}
+static struct device_type br_type = {
+ .name = "bridge",
+};
+
int br_add_bridge(struct net *net, const char *name)
{
struct net_device *dev;
@@ -279,6 +284,8 @@ int br_add_bridge(struct net *net, const char *name)
goto out_free;
}
+ SET_NETDEV_DEVTYPE(dev, &br_type);
+
ret = register_netdevice(dev);
if (ret)
goto out_free;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index d22f611e4004..907a82e9023d 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -359,7 +359,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
},
.proto = 0,
};
- struct in_device *in_dev = in_dev_get(dev);
+ struct in_device *in_dev = __in_dev_get_rcu(dev);
/* If err equals -EHOSTUNREACH the error is due to a
* martian destination or due to the fact that
@@ -905,46 +905,62 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb,
* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
* ip_refrag() can return NF_STOLEN. */
static struct nf_hook_ops br_nf_ops[] __read_mostly = {
- { .hook = br_nf_pre_routing,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_PRE_ROUTING,
- .priority = NF_BR_PRI_BRNF, },
- { .hook = br_nf_local_in,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_LOCAL_IN,
- .priority = NF_BR_PRI_BRNF, },
- { .hook = br_nf_forward_ip,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_FORWARD,
- .priority = NF_BR_PRI_BRNF - 1, },
- { .hook = br_nf_forward_arp,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_FORWARD,
- .priority = NF_BR_PRI_BRNF, },
- { .hook = br_nf_local_out,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_LOCAL_OUT,
- .priority = NF_BR_PRI_FIRST, },
- { .hook = br_nf_post_routing,
- .owner = THIS_MODULE,
- .pf = PF_BRIDGE,
- .hooknum = NF_BR_POST_ROUTING,
- .priority = NF_BR_PRI_LAST, },
- { .hook = ip_sabotage_in,
- .owner = THIS_MODULE,
- .pf = PF_INET,
- .hooknum = NF_INET_PRE_ROUTING,
- .priority = NF_IP_PRI_FIRST, },
- { .hook = ip_sabotage_in,
- .owner = THIS_MODULE,
- .pf = PF_INET6,
- .hooknum = NF_INET_PRE_ROUTING,
- .priority = NF_IP6_PRI_FIRST, },
+ {
+ .hook = br_nf_pre_routing,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_PRE_ROUTING,
+ .priority = NF_BR_PRI_BRNF,
+ },
+ {
+ .hook = br_nf_local_in,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_LOCAL_IN,
+ .priority = NF_BR_PRI_BRNF,
+ },
+ {
+ .hook = br_nf_forward_ip,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_FORWARD,
+ .priority = NF_BR_PRI_BRNF - 1,
+ },
+ {
+ .hook = br_nf_forward_arp,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_FORWARD,
+ .priority = NF_BR_PRI_BRNF,
+ },
+ {
+ .hook = br_nf_local_out,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_LOCAL_OUT,
+ .priority = NF_BR_PRI_FIRST,
+ },
+ {
+ .hook = br_nf_post_routing,
+ .owner = THIS_MODULE,
+ .pf = PF_BRIDGE,
+ .hooknum = NF_BR_POST_ROUTING,
+ .priority = NF_BR_PRI_LAST,
+ },
+ {
+ .hook = ip_sabotage_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP_PRI_FIRST,
+ },
+ {
+ .hook = ip_sabotage_in,
+ .owner = THIS_MODULE,
+ .pf = PF_INET6,
+ .hooknum = NF_INET_PRE_ROUTING,
+ .priority = NF_IP6_PRI_FIRST,
+ },
};
#ifdef CONFIG_SYSCTL
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d5b5537272b4..2114e45682ea 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -81,6 +81,9 @@ struct net_bridge_port
struct timer_list message_age_timer;
struct kobject kobj;
struct rcu_head rcu;
+
+ unsigned long flags;
+#define BR_HAIRPIN_MODE 0x00000001
};
struct net_bridge
@@ -140,7 +143,8 @@ static inline int br_is_root_bridge(const struct net_bridge *br)
/* br_device.c */
extern void br_dev_setup(struct net_device *dev);
-extern int br_dev_xmit(struct sk_buff *skb, struct net_device *dev);
+extern netdev_tx_t br_dev_xmit(struct sk_buff *skb,
+ struct net_device *dev);
/* br_fdb.c */
extern int br_fdb_init(void);
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 0660515f3992..fd3f8d6c0998 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -21,7 +21,7 @@
*/
#define MESSAGE_AGE_INCR ((HZ < 256) ? 1 : (HZ/256))
-static const char *br_port_state_names[] = {
+static const char *const br_port_state_names[] = {
[BR_STATE_DISABLED] = "disabled",
[BR_STATE_LISTENING] = "listening",
[BR_STATE_LEARNING] = "learning",
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 4a3cdf8f3813..820643a3ba9c 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -143,6 +143,22 @@ static ssize_t store_flush(struct net_bridge_port *p, unsigned long v)
}
static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
+static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
+{
+ int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
+ return sprintf(buf, "%d\n", hairpin_mode);
+}
+static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
+{
+ if (v)
+ p->flags |= BR_HAIRPIN_MODE;
+ else
+ p->flags &= ~BR_HAIRPIN_MODE;
+ return 0;
+}
+static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
+ show_hairpin_mode, store_hairpin_mode);
+
static struct brport_attribute *brport_attrs[] = {
&brport_attr_path_cost,
&brport_attr_priority,
@@ -159,6 +175,7 @@ static struct brport_attribute *brport_attrs[] = {
&brport_attr_forward_delay_timer,
&brport_attr_hold_timer,
&brport_attr_flush,
+ &brport_attr_hairpin_mode,
NULL
};
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index a94f3cc377c0..e4ea3fdd1d41 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -50,14 +50,6 @@ struct arppayload
unsigned char ip_dst[4];
};
-static void print_MAC(const unsigned char *p)
-{
- int i;
-
- for (i = 0; i < ETH_ALEN; i++, p++)
- printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
-}
-
static void
print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
{
@@ -88,14 +80,11 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
unsigned int bitmask;
spin_lock_bh(&ebt_log_lock);
- printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->u.log.level,
- prefix, in ? in->name : "", out ? out->name : "");
-
- print_MAC(eth_hdr(skb)->h_source);
- printk("MAC dest = ");
- print_MAC(eth_hdr(skb)->h_dest);
-
- printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
+ printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
+ '0' + loginfo->u.log.level, prefix,
+ in ? in->name : "", out ? out->name : "",
+ eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+ ntohs(eth_hdr(skb)->h_proto));
if (loginfo->type == NF_LOG_TYPE_LOG)
bitmask = loginfo->u.log.logflags;
@@ -171,12 +160,8 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
printk(" INCOMPLETE ARP payload");
goto out;
}
- printk(" ARP MAC SRC=");
- print_MAC(ap->mac_src);
- printk(" ARP IP SRC=%pI4", ap->ip_src);
- printk(" ARP MAC DST=");
- print_MAC(ap->mac_dst);
- printk(" ARP IP DST=%pI4", ap->ip_dst);
+ printk(" ARP MAC SRC=%pM ARP IP SRC=%pI4 ARP MAC DST=%pM ARP IP DST=%pI4",
+ ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst);
}
}
out:
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index 133eeae45a4f..ce50688a6431 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -266,7 +266,7 @@ static bool ebt_ulog_tg_check(const struct xt_tgchk_param *par)
if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
- return 0;
+ return true;
}
static struct xt_target ebt_ulog_tg_reg __read_mostly = {
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index c751111440f8..d32ab13e728c 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -41,7 +41,7 @@ static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
return 0;
}
-static struct ebt_table broute_table =
+static const struct ebt_table broute_table =
{
.name = "broute",
.table = &initial_table,
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index a5eea72938a6..60b1a6ca7185 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -50,7 +50,7 @@ static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
return 0;
}
-static struct ebt_table frame_filter =
+static const struct ebt_table frame_filter =
{
.name = "filter",
.table = &initial_table,
@@ -77,21 +77,21 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
{
.hook = ebt_in_hook,
.owner = THIS_MODULE,
- .pf = PF_BRIDGE,
+ .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_LOCAL_IN,
.priority = NF_BR_PRI_FILTER_BRIDGED,
},
{
.hook = ebt_in_hook,
.owner = THIS_MODULE,
- .pf = PF_BRIDGE,
+ .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_FORWARD,
.priority = NF_BR_PRI_FILTER_BRIDGED,
},
{
.hook = ebt_out_hook,
.owner = THIS_MODULE,
- .pf = PF_BRIDGE,
+ .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_LOCAL_OUT,
.priority = NF_BR_PRI_FILTER_OTHER,
},
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 6024c551f9a9..4a98804203b0 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -77,21 +77,21 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
{
.hook = ebt_nat_out,
.owner = THIS_MODULE,
- .pf = PF_BRIDGE,
+ .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_LOCAL_OUT,
.priority = NF_BR_PRI_NAT_DST_OTHER,
},
{
.hook = ebt_nat_out,
.owner = THIS_MODULE,
- .pf = PF_BRIDGE,
+ .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_POST_ROUTING,
.priority = NF_BR_PRI_NAT_SRC,
},
{
.hook = ebt_nat_in,
.owner = THIS_MODULE,
- .pf = PF_BRIDGE,
+ .pf = NFPROTO_BRIDGE,
.hooknum = NF_BR_PRE_ROUTING,
.priority = NF_BR_PRI_NAT_DST_BRIDGED,
},
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 37928d5f2840..bd1c65425d4f 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1103,23 +1103,24 @@ free_newinfo:
return ret;
}
-struct ebt_table *ebt_register_table(struct net *net, struct ebt_table *table)
+struct ebt_table *
+ebt_register_table(struct net *net, const struct ebt_table *input_table)
{
struct ebt_table_info *newinfo;
- struct ebt_table *t;
+ struct ebt_table *t, *table;
struct ebt_replace_kernel *repl;
int ret, i, countersize;
void *p;
- if (!table || !(repl = table->table) || !repl->entries ||
- repl->entries_size == 0 ||
- repl->counters || table->private) {
+ if (input_table == NULL || (repl = input_table->table) == NULL ||
+ repl->entries == 0 || repl->entries_size == 0 ||
+ repl->counters != NULL || input_table->private != NULL) {
BUGPRINT("Bad table data for ebt_register_table!!!\n");
return ERR_PTR(-EINVAL);
}
/* Don't add one table to multiple lists. */
- table = kmemdup(table, sizeof(struct ebt_table), GFP_KERNEL);
+ table = kmemdup(input_table, sizeof(struct ebt_table), GFP_KERNEL);
if (!table) {
ret = -ENOMEM;
goto out;