summaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/bridge/br_if.c6
-rw-r--r--net/bridge/br_input.c2
-rw-r--r--net/bridge/br_ioctl.c2
-rw-r--r--net/bridge/br_multicast.c4
-rw-r--r--net/bridge/br_netfilter.c9
-rw-r--r--net/bridge/br_private.h2
-rw-r--r--net/bridge/br_stp_if.c11
-rw-r--r--net/bridge/netfilter/ebtables.c64
9 files changed, 34 insertions, 68 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 88485cc74dc3..cc4d3c5ab1c6 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -169,7 +169,7 @@ void br_fdb_flush(struct net_bridge *br)
spin_unlock_bh(&br->hash_lock);
}
-/* Flush all entries refering to a specific port.
+/* Flush all entries referring to a specific port.
* if do_all is set also flush static entries
*/
void br_fdb_delete_by_port(struct net_bridge *br,
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index dce8f0009a12..718b60366dfe 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
{
struct net_bridge_port *p;
int err = 0;
+ bool changed_addr;
/* Don't allow bridging non-ethernet like devices */
if ((dev->flags & IFF_LOOPBACK) ||
@@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
list_add_rcu(&p->list, &br->port_list);
spin_lock_bh(&br->lock);
- br_stp_recalculate_bridge_id(br);
+ changed_addr = br_stp_recalculate_bridge_id(br);
br_features_recompute(br);
if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) &&
@@ -456,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
br_ifinfo_notify(RTM_NEWLINK, p);
+ if (changed_addr)
+ call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+
dev_set_mtu(br->dev, br_min_mtu(br));
kobject_uevent(&p->kobj, KOBJ_ADD);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index e2160792e1bc..0c7badad62af 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -164,7 +164,7 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
goto drop;
/* If STP is turned off, then forward */
- if (p->br->stp_enabled == BR_NO_STP)
+ if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
goto forward;
if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index cb43312b846e..3d9fca0e3370 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -106,7 +106,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
/*
* Legacy ioctl's through SIOCDEVPRIVATE
* This interface is deprecated because it was too difficult to
- * to do the translation for 32/64bit ioctl compatability.
+ * to do the translation for 32/64bit ioctl compatibility.
*/
static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 030a002ff8ee..59660c909a7c 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -445,9 +445,9 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
ip6h->payload_len = htons(8 + sizeof(*mldq));
ip6h->nexthdr = IPPROTO_HOPOPTS;
ip6h->hop_limit = 1;
+ ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
&ip6h->saddr);
- ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
hopopt = (u8 *)(ip6h + 1);
@@ -1475,7 +1475,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
ip6h->payload_len == 0)
return 0;
- len = ntohs(ip6h->payload_len);
+ len = ntohs(ip6h->payload_len) + sizeof(*ip6h);
if (skb->len < len)
return -EINVAL;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index f97af5590ba1..74ef4d4846a4 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -249,11 +249,9 @@ static int br_parse_ip_options(struct sk_buff *skb)
goto drop;
}
- /* Zero out the CB buffer if no options present */
- if (iph->ihl == 5) {
- memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+ memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+ if (iph->ihl == 5)
return 0;
- }
opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
if (ip_options_compile(dev_net(dev), opt, skb))
@@ -739,6 +737,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
nf_bridge->mask |= BRNF_PKT_TYPE;
}
+ if (pf == PF_INET && br_parse_ip_options(skb))
+ return NF_DROP;
+
/* The physdev module checks on this */
nf_bridge->mask |= BRNF_BRIDGED;
nf_bridge->physoutdev = skb->dev;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 19e2f46ed086..387013d33745 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br);
extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val);
extern void br_stp_enable_port(struct net_bridge_port *p);
extern void br_stp_disable_port(struct net_bridge_port *p);
-extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
+extern bool br_stp_recalculate_bridge_id(struct net_bridge *br);
extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a);
extern void br_stp_set_bridge_priority(struct net_bridge *br,
u16 newprio);
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 79372d4a4055..9b61d09de9b9 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1];
/* called under bridge lock */
-void br_stp_recalculate_bridge_id(struct net_bridge *br)
+bool br_stp_recalculate_bridge_id(struct net_bridge *br)
{
const unsigned char *br_mac_zero =
(const unsigned char *)br_mac_zero_aligned;
@@ -213,7 +213,7 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
/* user has chosen a value so keep it */
if (br->flags & BR_SET_MAC_ADDR)
- return;
+ return false;
list_for_each_entry(p, &br->port_list, list) {
if (addr == br_mac_zero ||
@@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
}
- if (compare_ether_addr(br->bridge_id.addr, addr))
- br_stp_change_bridge_id(br, addr);
+ if (compare_ether_addr(br->bridge_id.addr, addr) == 0)
+ return false; /* no change */
+
+ br_stp_change_bridge_id(br, addr);
+ return true;
}
/* called under bridge lock */
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 893669caa8de..1a92b369c820 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1766,7 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info,
newinfo->entries_size = size;
- xt_compat_init_offsets(AF_INET, info->nentries);
+ xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries);
return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
entries, newinfo);
}
@@ -1882,7 +1882,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
struct xt_match *match;
struct xt_target *wt;
void *dst = NULL;
- int off, pad = 0, ret = 0;
+ int off, pad = 0;
unsigned int size_kern, entry_offset, match_size = mwt->match_size;
strlcpy(name, mwt->u.name, sizeof(name));
@@ -1935,13 +1935,6 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
break;
}
- if (!dst) {
- ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset,
- off + ebt_compat_entry_padsize());
- if (ret < 0)
- return ret;
- }
-
state->buf_kern_offset += match_size + off;
state->buf_user_offset += match_size;
pad = XT_ALIGN(size_kern) - size_kern;
@@ -2016,50 +2009,6 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
return growth;
}
-#define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \
-({ \
- unsigned int __i; \
- int __ret = 0; \
- struct compat_ebt_entry_mwt *__watcher; \
- \
- for (__i = e->watchers_offset; \
- __i < (e)->target_offset; \
- __i += __watcher->watcher_size + \
- sizeof(struct compat_ebt_entry_mwt)) { \
- __watcher = (void *)(e) + __i; \
- __ret = fn(__watcher , ## args); \
- if (__ret != 0) \
- break; \
- } \
- if (__ret == 0) { \
- if (__i != (e)->target_offset) \
- __ret = -EINVAL; \
- } \
- __ret; \
-})
-
-#define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \
-({ \
- unsigned int __i; \
- int __ret = 0; \
- struct compat_ebt_entry_mwt *__match; \
- \
- for (__i = sizeof(struct ebt_entry); \
- __i < (e)->watchers_offset; \
- __i += __match->match_size + \
- sizeof(struct compat_ebt_entry_mwt)) { \
- __match = (void *)(e) + __i; \
- __ret = fn(__match , ## args); \
- if (__ret != 0) \
- break; \
- } \
- if (__ret == 0) { \
- if (__i != (e)->watchers_offset) \
- __ret = -EINVAL; \
- } \
- __ret; \
-})
-
/* called for all ebt_entry structures. */
static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
unsigned int *total,
@@ -2132,6 +2081,14 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
}
}
+ if (state->buf_kern_start == NULL) {
+ unsigned int offset = buf_start - (char *) base;
+
+ ret = xt_compat_add_offset(NFPROTO_BRIDGE, offset, new_offset);
+ if (ret < 0)
+ return ret;
+ }
+
startoff = state->buf_user_offset - startoff;
BUG_ON(*total < startoff);
@@ -2240,6 +2197,7 @@ static int compat_do_replace(struct net *net, void __user *user,
xt_compat_lock(NFPROTO_BRIDGE);
+ xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
if (ret < 0)
goto out_unlock;