diff options
Diffstat (limited to 'net/bridge')
| -rw-r--r-- | net/bridge/br_device.c | 21 | ||||
| -rw-r--r-- | net/bridge/br_fdb.c | 5 | ||||
| -rw-r--r-- | net/bridge/br_forward.c | 14 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_input.c | 15 | ||||
| -rw-r--r-- | net/bridge/br_mdb.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_multicast.c | 74 | ||||
| -rw-r--r-- | net/bridge/br_netfilter.c | 4 | ||||
| -rw-r--r-- | net/bridge/br_netlink.c | 10 | ||||
| -rw-r--r-- | net/bridge/br_notify.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 9 | ||||
| -rw-r--r-- | net/bridge/br_sysfs_br.c | 26 | ||||
| -rw-r--r-- | net/bridge/br_sysfs_if.c | 4 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebt_ulog.c | 6 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebtables.c | 6 | 
15 files changed, 139 insertions, 61 deletions
| diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 967312803e41..2ef66781fedb 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -22,6 +22,9 @@  #include <asm/uaccess.h>  #include "br_private.h" +#define COMMON_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | \ +			 NETIF_F_GSO_MASK | NETIF_F_HW_CSUM) +  /* net device transmit always called with BH disabled */  netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)  { @@ -55,10 +58,10 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)  	skb_pull(skb, ETH_HLEN);  	if (is_broadcast_ether_addr(dest)) -		br_flood_deliver(br, skb); +		br_flood_deliver(br, skb, false);  	else if (is_multicast_ether_addr(dest)) {  		if (unlikely(netpoll_tx_running(dev))) { -			br_flood_deliver(br, skb); +			br_flood_deliver(br, skb, false);  			goto out;  		}  		if (br_multicast_rcv(br, NULL, skb)) { @@ -70,11 +73,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)  		if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb))  			br_multicast_deliver(mdst, skb);  		else -			br_flood_deliver(br, skb); +			br_flood_deliver(br, skb, false);  	} else if ((dst = __br_fdb_get(br, dest, vid)) != NULL)  		br_deliver(dst->dst, skb);  	else -		br_flood_deliver(br, skb); +		br_flood_deliver(br, skb, true);  out:  	rcu_read_unlock(); @@ -346,12 +349,10 @@ void br_dev_setup(struct net_device *dev)  	dev->tx_queue_len = 0;  	dev->priv_flags = IFF_EBRIDGE; -	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | -			NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | NETIF_F_LLTX | -			NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_CTAG_TX; -	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | -			   NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | -			   NETIF_F_HW_VLAN_CTAG_TX; +	dev->features = COMMON_FEATURES | NETIF_F_LLTX | NETIF_F_NETNS_LOCAL | +			NETIF_F_HW_VLAN_CTAG_TX; +	dev->hw_features = COMMON_FEATURES | NETIF_F_HW_VLAN_CTAG_TX; +	dev->vlan_features = COMMON_FEATURES;  	br->dev = dev;  	spin_lock_init(&br->lock); diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index ebfa4443c69b..60aca9109a50 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -707,6 +707,11 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],  		}  	} +	if (is_zero_ether_addr(addr)) { +		pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n"); +		return -EINVAL; +	} +  	p = br_port_get_rtnl(dev);  	if (p == NULL) {  		pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n", diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 092b20e4ee4c..4b81b1471789 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -174,7 +174,8 @@ out:  static void br_flood(struct net_bridge *br, struct sk_buff *skb,  		     struct sk_buff *skb0,  		     void (*__packet_hook)(const struct net_bridge_port *p, -					   struct sk_buff *skb)) +					   struct sk_buff *skb), +		     bool unicast)  {  	struct net_bridge_port *p;  	struct net_bridge_port *prev; @@ -182,6 +183,9 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb,  	prev = NULL;  	list_for_each_entry_rcu(p, &br->port_list, list) { +		/* Do not flood unicast traffic to ports that turn it off */ +		if (unicast && !(p->flags & BR_FLOOD)) +			continue;  		prev = maybe_deliver(prev, p, skb, __packet_hook);  		if (IS_ERR(prev))  			goto out; @@ -203,16 +207,16 @@ out:  /* called with rcu_read_lock */ -void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) +void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, bool unicast)  { -	br_flood(br, skb, NULL, __br_deliver); +	br_flood(br, skb, NULL, __br_deliver, unicast);  }  /* called under bridge lock */  void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, -		      struct sk_buff *skb2) +		      struct sk_buff *skb2, bool unicast)  { -	br_flood(br, skb, skb2, __br_forward); +	br_flood(br, skb, skb2, __br_forward, unicast);  }  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 4cdba60926ff..5623be6b9ecd 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -221,7 +221,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; +	p->flags = BR_LEARNING | BR_FLOOD;  	br_init_port(p);  	p->state = BR_STATE_DISABLED;  	br_stp_port_timer_init(p); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 828e2bcc1f52..1b8b8b824cd7 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -65,6 +65,7 @@ int br_handle_frame_finish(struct sk_buff *skb)  	struct net_bridge_fdb_entry *dst;  	struct net_bridge_mdb_entry *mdst;  	struct sk_buff *skb2; +	bool unicast = true;  	u16 vid = 0;  	if (!p || p->state == BR_STATE_DISABLED) @@ -75,7 +76,8 @@ int br_handle_frame_finish(struct sk_buff *skb)  	/* insert into forwarding database after filtering to avoid spoofing */  	br = p->br; -	br_fdb_update(br, p, eth_hdr(skb)->h_source, vid); +	if (p->flags & BR_LEARNING) +		br_fdb_update(br, p, eth_hdr(skb)->h_source, vid);  	if (!is_broadcast_ether_addr(dest) && is_multicast_ether_addr(dest) &&  	    br_multicast_rcv(br, p, skb)) @@ -94,9 +96,10 @@ int br_handle_frame_finish(struct sk_buff *skb)  	dst = NULL; -	if (is_broadcast_ether_addr(dest)) +	if (is_broadcast_ether_addr(dest)) {  		skb2 = skb; -	else if (is_multicast_ether_addr(dest)) { +		unicast = false; +	} else if (is_multicast_ether_addr(dest)) {  		mdst = br_mdb_get(br, skb, vid);  		if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {  			if ((mdst && mdst->mglist) || @@ -109,6 +112,7 @@ int br_handle_frame_finish(struct sk_buff *skb)  		} else  			skb2 = skb; +		unicast = false;  		br->dev->stats.multicast++;  	} else if ((dst = __br_fdb_get(br, dest, vid)) &&  			dst->is_local) { @@ -122,7 +126,7 @@ int br_handle_frame_finish(struct sk_buff *skb)  			dst->used = jiffies;  			br_forward(dst->dst, skb, skb2);  		} else -			br_flood_forward(br, skb, skb2); +			br_flood_forward(br, skb, skb2, unicast);  	}  	if (skb2) @@ -142,7 +146,8 @@ static int br_handle_local_finish(struct sk_buff *skb)  	u16 vid = 0;  	br_vlan_get_tag(skb, &vid); -	br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid); +	if (p->flags & BR_LEARNING) +		br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid);  	return 0;	 /* process further */  } diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 19942e38fd2d..0daae3ec2355 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -447,7 +447,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)  		call_rcu_bh(&p->rcu, br_multicast_free_pg);  		err = 0; -		if (!mp->ports && !mp->mglist && +		if (!mp->ports && !mp->mglist && mp->timer_armed &&  		    netif_running(br->dev))  			mod_timer(&mp->timer, jiffies);  		break; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index d6448e35e027..69af490cce44 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -23,6 +23,7 @@  #include <linux/skbuff.h>  #include <linux/slab.h>  #include <linux/timer.h> +#include <linux/inetdevice.h>  #include <net/ip.h>  #if IS_ENABLED(CONFIG_IPV6)  #include <net/ipv6.h> @@ -269,7 +270,7 @@ static void br_multicast_del_pg(struct net_bridge *br,  		del_timer(&p->timer);  		call_rcu_bh(&p->rcu, br_multicast_free_pg); -		if (!mp->ports && !mp->mglist && +		if (!mp->ports && !mp->mglist && mp->timer_armed &&  		    netif_running(br->dev))  			mod_timer(&mp->timer, jiffies); @@ -381,7 +382,8 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,  	iph->frag_off = htons(IP_DF);  	iph->ttl = 1;  	iph->protocol = IPPROTO_IGMP; -	iph->saddr = 0; +	iph->saddr = br->multicast_query_use_ifaddr ? +		     inet_select_addr(br->dev, 0, RT_SCOPE_LINK) : 0;  	iph->daddr = htonl(INADDR_ALLHOSTS_GROUP);  	((u8 *)&iph[1])[0] = IPOPT_RA;  	((u8 *)&iph[1])[1] = 4; @@ -616,8 +618,6 @@ rehash:  	mp->br = br;  	mp->addr = *group; -	setup_timer(&mp->timer, br_multicast_group_expired, -		    (unsigned long)mp);  	hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);  	mdb->size++; @@ -655,7 +655,6 @@ static int br_multicast_add_group(struct net_bridge *br,  	struct net_bridge_mdb_entry *mp;  	struct net_bridge_port_group *p;  	struct net_bridge_port_group __rcu **pp; -	unsigned long now = jiffies;  	int err;  	spin_lock(&br->multicast_lock); @@ -670,7 +669,6 @@ static int br_multicast_add_group(struct net_bridge *br,  	if (!port) {  		mp->mglist = true; -		mod_timer(&mp->timer, now + br->multicast_membership_interval);  		goto out;  	} @@ -678,7 +676,7 @@ static int br_multicast_add_group(struct net_bridge *br,  	     (p = mlock_dereference(*pp, br)) != NULL;  	     pp = &p->next) {  		if (p->port == port) -			goto found; +			goto out;  		if ((unsigned long)p->port < (unsigned long)port)  			break;  	} @@ -689,8 +687,6 @@ static int br_multicast_add_group(struct net_bridge *br,  	rcu_assign_pointer(*pp, p);  	br_mdb_notify(br->dev, port, group, RTM_NEWMDB); -found: -	mod_timer(&p->timer, now + br->multicast_membership_interval);  out:  	err = 0; @@ -1016,7 +1012,7 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,  #endif  /* - * Add port to rotuer_list + * Add port to router_list   *  list is maintained ordered by pointer value   *  and locked by br->multicast_lock and RCU   */ @@ -1130,6 +1126,10 @@ static int br_ip4_multicast_query(struct net_bridge *br,  	if (!mp)  		goto out; +	setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); +	mod_timer(&mp->timer, now + br->multicast_membership_interval); +	mp->timer_armed = true; +  	max_delay *= br->multicast_last_member_count;  	if (mp->mglist && @@ -1204,6 +1204,10 @@ static int br_ip6_multicast_query(struct net_bridge *br,  	if (!mp)  		goto out; +	setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp); +	mod_timer(&mp->timer, now + br->multicast_membership_interval); +	mp->timer_armed = true; +  	max_delay *= br->multicast_last_member_count;  	if (mp->mglist &&  	    (timer_pending(&mp->timer) ? @@ -1247,6 +1251,32 @@ static void br_multicast_leave_group(struct net_bridge *br,  	if (!mp)  		goto out; +	if (br->multicast_querier && +	    !timer_pending(&br->multicast_querier_timer)) { +		__br_multicast_send_query(br, port, &mp->addr); + +		time = jiffies + br->multicast_last_member_count * +				 br->multicast_last_member_interval; +		mod_timer(port ? &port->multicast_query_timer : +				 &br->multicast_query_timer, time); + +		for (p = mlock_dereference(mp->ports, br); +		     p != NULL; +		     p = mlock_dereference(p->next, br)) { +			if (p->port != port) +				continue; + +			if (!hlist_unhashed(&p->mglist) && +			    (timer_pending(&p->timer) ? +			     time_after(p->timer.expires, time) : +			     try_to_del_timer_sync(&p->timer) >= 0)) { +				mod_timer(&p->timer, time); +			} + +			break; +		} +	} +  	if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {  		struct net_bridge_port_group __rcu **pp; @@ -1262,7 +1292,7 @@ static void br_multicast_leave_group(struct net_bridge *br,  			call_rcu_bh(&p->rcu, br_multicast_free_pg);  			br_mdb_notify(br->dev, port, group, RTM_DELMDB); -			if (!mp->ports && !mp->mglist && +			if (!mp->ports && !mp->mglist && mp->timer_armed &&  			    netif_running(br->dev))  				mod_timer(&mp->timer, jiffies);  		} @@ -1274,30 +1304,12 @@ static void br_multicast_leave_group(struct net_bridge *br,  		     br->multicast_last_member_interval;  	if (!port) { -		if (mp->mglist && +		if (mp->mglist && mp->timer_armed &&  		    (timer_pending(&mp->timer) ?  		     time_after(mp->timer.expires, time) :  		     try_to_del_timer_sync(&mp->timer) >= 0)) {  			mod_timer(&mp->timer, time);  		} - -		goto out; -	} - -	for (p = mlock_dereference(mp->ports, br); -	     p != NULL; -	     p = mlock_dereference(p->next, br)) { -		if (p->port != port) -			continue; - -		if (!hlist_unhashed(&p->mglist) && -		    (timer_pending(&p->timer) ? -		     time_after(p->timer.expires, time) : -		     try_to_del_timer_sync(&p->timer) >= 0)) { -			mod_timer(&p->timer, time); -		} - -		break;  	}  out: @@ -1619,6 +1631,7 @@ void br_multicast_init(struct net_bridge *br)  	br->multicast_router = 1;  	br->multicast_querier = 0; +	br->multicast_query_use_ifaddr = 0;  	br->multicast_last_member_count = 2;  	br->multicast_startup_query_count = 2; @@ -1672,6 +1685,7 @@ void br_multicast_stop(struct net_bridge *br)  		hlist_for_each_entry_safe(mp, n, &mdb->mhash[i],  					  hlist[ver]) {  			del_timer(&mp->timer); +			mp->timer_armed = false;  			call_rcu_bh(&mp->rcu, br_multicast_free_group);  		}  	} diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 1ed75bfd8d1d..f87736270eaa 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -992,7 +992,7 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = {  #ifdef CONFIG_SYSCTL  static -int brnf_sysctl_call_tables(ctl_table * ctl, int write, +int brnf_sysctl_call_tables(struct ctl_table *ctl, int write,  			    void __user * buffer, size_t * lenp, loff_t * ppos)  {  	int ret; @@ -1004,7 +1004,7 @@ int brnf_sysctl_call_tables(ctl_table * ctl, int write,  	return ret;  } -static ctl_table brnf_table[] = { +static struct ctl_table brnf_table[] = {  	{  		.procname	= "bridge-nf-call-arptables",  		.data		= &brnf_call_arptables, diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 8e3abf564798..1fc30abd3a52 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -30,6 +30,8 @@ static inline size_t br_port_info_size(void)  		+ nla_total_size(1)	/* IFLA_BRPORT_GUARD */  		+ nla_total_size(1)	/* IFLA_BRPORT_PROTECT */  		+ nla_total_size(1)	/* IFLA_BRPORT_FAST_LEAVE */ +		+ nla_total_size(1)	/* IFLA_BRPORT_LEARNING */ +		+ nla_total_size(1)	/* IFLA_BRPORT_UNICAST_FLOOD */  		+ 0;  } @@ -56,7 +58,9 @@ static int br_port_fill_attrs(struct sk_buff *skb,  	    nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||  	    nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||  	    nla_put_u8(skb, IFLA_BRPORT_PROTECT, !!(p->flags & BR_ROOT_BLOCK)) || -	    nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE))) +	    nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)) || +	    nla_put_u8(skb, IFLA_BRPORT_LEARNING, !!(p->flags & BR_LEARNING)) || +	    nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, !!(p->flags & BR_FLOOD)))  		return -EMSGSIZE;  	return 0; @@ -281,6 +285,8 @@ static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {  	[IFLA_BRPORT_MODE]	= { .type = NLA_U8 },  	[IFLA_BRPORT_GUARD]	= { .type = NLA_U8 },  	[IFLA_BRPORT_PROTECT]	= { .type = NLA_U8 }, +	[IFLA_BRPORT_LEARNING]	= { .type = NLA_U8 }, +	[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },  };  /* Change the state of the port and notify spanning tree */ @@ -328,6 +334,8 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])  	br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);  	br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);  	br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK); +	br_set_port_flag(p, tb, IFLA_BRPORT_LEARNING, BR_LEARNING); +	br_set_port_flag(p, tb, IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD);  	if (tb[IFLA_BRPORT_COST]) {  		err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST])); diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 1644b3e1f947..3a3f371b2841 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -31,7 +31,7 @@ struct notifier_block br_device_notifier = {   */  static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)  { -	struct net_device *dev = ptr; +	struct net_device *dev = netdev_notifier_info_to_dev(ptr);  	struct net_bridge_port *p;  	struct net_bridge *br;  	bool changed_addr; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index d2c043a857b6..3be89b3ce17b 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -112,6 +112,7 @@ struct net_bridge_mdb_entry  	struct timer_list		timer;  	struct br_ip			addr;  	bool				mglist; +	bool				timer_armed;  };  struct net_bridge_mdb_htable @@ -157,6 +158,8 @@ struct net_bridge_port  #define BR_ROOT_BLOCK		0x00000004  #define BR_MULTICAST_FAST_LEAVE	0x00000008  #define BR_ADMIN_COST		0x00000010 +#define BR_LEARNING		0x00000020 +#define BR_FLOOD		0x00000040  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING  	u32				multicast_startup_queries_sent; @@ -249,6 +252,7 @@ struct net_bridge  	u8				multicast_disabled:1;  	u8				multicast_querier:1; +	u8				multicast_query_use_ifaddr:1;  	u32				hash_elasticity;  	u32				hash_max; @@ -411,9 +415,10 @@ extern int br_dev_queue_push_xmit(struct sk_buff *skb);  extern void br_forward(const struct net_bridge_port *to,  		struct sk_buff *skb, struct sk_buff *skb0);  extern int br_forward_finish(struct sk_buff *skb); -extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); +extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, +			     bool unicast);  extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, -			     struct sk_buff *skb2); +			     struct sk_buff *skb2, bool unicast);  /* br_if.c */  extern void br_port_carrier_check(struct net_bridge_port *p); diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 8baa9c08e1a4..394bb96b6087 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -375,6 +375,31 @@ static ssize_t store_multicast_snooping(struct device *d,  static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,  		   show_multicast_snooping, store_multicast_snooping); +static ssize_t show_multicast_query_use_ifaddr(struct device *d, +				      struct device_attribute *attr, +				      char *buf) +{ +	struct net_bridge *br = to_bridge(d); +	return sprintf(buf, "%d\n", br->multicast_query_use_ifaddr); +} + +static int set_query_use_ifaddr(struct net_bridge *br, unsigned long val) +{ +	br->multicast_query_use_ifaddr = !!val; +	return 0; +} + +static ssize_t +store_multicast_query_use_ifaddr(struct device *d, +				 struct device_attribute *attr, +				 const char *buf, size_t len) +{ +	return store_bridge_parm(d, buf, len, set_query_use_ifaddr); +} +static DEVICE_ATTR(multicast_query_use_ifaddr, S_IRUGO | S_IWUSR, +		   show_multicast_query_use_ifaddr, +		   store_multicast_query_use_ifaddr); +  static ssize_t show_multicast_querier(struct device *d,  				      struct device_attribute *attr,  				      char *buf) @@ -734,6 +759,7 @@ static struct attribute *bridge_attrs[] = {  	&dev_attr_multicast_router.attr,  	&dev_attr_multicast_snooping.attr,  	&dev_attr_multicast_querier.attr, +	&dev_attr_multicast_query_use_ifaddr.attr,  	&dev_attr_hash_elasticity.attr,  	&dev_attr_hash_max.attr,  	&dev_attr_multicast_last_member_count.attr, diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index a1ef1b6e14dc..2a2cdb756d51 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -158,6 +158,8 @@ static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);  BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE);  BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD);  BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); +BRPORT_ATTR_FLAG(learning, BR_LEARNING); +BRPORT_ATTR_FLAG(unicast_flood, BR_FLOOD);  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING  static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) @@ -195,6 +197,8 @@ static const struct brport_attribute *brport_attrs[] = {  	&brport_attr_hairpin_mode,  	&brport_attr_bpdu_guard,  	&brport_attr_root_block, +	&brport_attr_learning, +	&brport_attr_unicast_flood,  #ifdef CONFIG_BRIDGE_IGMP_SNOOPING  	&brport_attr_multicast_router,  	&brport_attr_multicast_fast_leave, diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index df0364aa12d5..518093802d1d 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -271,6 +271,12 @@ static int ebt_ulog_tg_check(const struct xt_tgchk_param *par)  {  	struct ebt_ulog_info *uloginfo = par->targinfo; +	if (!par->net->xt.ebt_ulog_warn_deprecated) { +		pr_info("ebt_ulog is deprecated and it will be removed soon, " +			"use ebt_nflog instead\n"); +		par->net->xt.ebt_ulog_warn_deprecated = true; +	} +  	if (uloginfo->nlgroup > 31)  		return -EINVAL; diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 3d110c4fc787..ac7802428384 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1339,7 +1339,7 @@ static inline int ebt_make_matchname(const struct ebt_entry_match *m,  	/* ebtables expects 32 bytes long names but xt_match names are 29 bytes  	   long. Copy 29 bytes and fill remaining bytes with zeroes. */ -	strncpy(name, m->u.match->name, sizeof(name)); +	strlcpy(name, m->u.match->name, sizeof(name));  	if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN))  		return -EFAULT;  	return 0; @@ -1351,7 +1351,7 @@ static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,  	char __user *hlp = ubase + ((char *)w - base);  	char name[EBT_FUNCTION_MAXNAMELEN] = {}; -	strncpy(name, w->u.watcher->name, sizeof(name)); +	strlcpy(name, w->u.watcher->name, sizeof(name));  	if (copy_to_user(hlp , name, EBT_FUNCTION_MAXNAMELEN))  		return -EFAULT;  	return 0; @@ -1377,7 +1377,7 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)  	ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);  	if (ret != 0)  		return ret; -	strncpy(name, t->u.target->name, sizeof(name)); +	strlcpy(name, t->u.target->name, sizeof(name));  	if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN))  		return -EFAULT;  	return 0; |