aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToshiaki Makita <makita.toshiaki@lab.ntt.co.jp>2013-10-16 04:07:13 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-18 16:02:52 -0400
commit8adff41c3d259eb5e313b7b04669eee545925154 (patch)
tree0457c19489a9c482ff5c15fc16729673aa633dda
parent4b6c7879d84ad06a2ac5b964808ed599187a188d (diff)
bridge: Don't use VID 0 and 4095 in vlan filtering
IEEE 802.1Q says that: - VID 0 shall not be configured as a PVID, or configured in any Filtering Database entry. - VID 4095 shall not be configured as a PVID, or transmitted in a tag header. This VID value may be used to indicate a wildcard match for the VID in management operations or Filtering Database entries. (See IEEE 802.1Q-2011 6.9.1 and Table 9-2) Don't accept adding these VIDs in the vlan_filtering implementation. Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> Reviewed-by: Vlad Yasevich <vyasevic@redhat.com> Acked-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bridge/br_fdb.c4
-rw-r--r--net/bridge/br_netlink.c2
-rw-r--r--net/bridge/br_vlan.c97
3 files changed, 49 insertions, 54 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index ffd5874f2592..33e8f23acddd 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -700,7 +700,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
700 700
701 vid = nla_get_u16(tb[NDA_VLAN]); 701 vid = nla_get_u16(tb[NDA_VLAN]);
702 702
703 if (vid >= VLAN_N_VID) { 703 if (!vid || vid >= VLAN_VID_MASK) {
704 pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n", 704 pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
705 vid); 705 vid);
706 return -EINVAL; 706 return -EINVAL;
@@ -794,7 +794,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
794 794
795 vid = nla_get_u16(tb[NDA_VLAN]); 795 vid = nla_get_u16(tb[NDA_VLAN]);
796 796
797 if (vid >= VLAN_N_VID) { 797 if (!vid || vid >= VLAN_VID_MASK) {
798 pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n", 798 pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
799 vid); 799 vid);
800 return -EINVAL; 800 return -EINVAL;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index e74ddc1c29a8..f75d92e4f96b 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -243,7 +243,7 @@ static int br_afspec(struct net_bridge *br,
243 243
244 vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]); 244 vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
245 245
246 if (vinfo->vid >= VLAN_N_VID) 246 if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
247 return -EINVAL; 247 return -EINVAL;
248 248
249 switch (cmd) { 249 switch (cmd) {
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 9a9ffe7e4019..21b6d217872b 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -45,37 +45,34 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
45 return 0; 45 return 0;
46 } 46 }
47 47
48 if (vid) { 48 if (v->port_idx) {
49 if (v->port_idx) { 49 p = v->parent.port;
50 p = v->parent.port; 50 br = p->br;
51 br = p->br; 51 dev = p->dev;
52 dev = p->dev; 52 } else {
53 } else { 53 br = v->parent.br;
54 br = v->parent.br; 54 dev = br->dev;
55 dev = br->dev; 55 }
56 } 56 ops = dev->netdev_ops;
57 ops = dev->netdev_ops; 57
58 58 if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
59 if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { 59 /* Add VLAN to the device filter if it is supported.
60 /* Add VLAN to the device filter if it is supported. 60 * Stricly speaking, this is not necessary now, since
61 * Stricly speaking, this is not necessary now, since 61 * devices are made promiscuous by the bridge, but if
62 * devices are made promiscuous by the bridge, but if 62 * that ever changes this code will allow tagged
63 * that ever changes this code will allow tagged 63 * traffic to enter the bridge.
64 * traffic to enter the bridge. 64 */
65 */ 65 err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q),
66 err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q), 66 vid);
67 vid); 67 if (err)
68 if (err) 68 return err;
69 return err; 69 }
70 }
71
72 err = br_fdb_insert(br, p, dev->dev_addr, vid);
73 if (err) {
74 br_err(br, "failed insert local address into bridge "
75 "forwarding table\n");
76 goto out_filt;
77 }
78 70
71 err = br_fdb_insert(br, p, dev->dev_addr, vid);
72 if (err) {
73 br_err(br, "failed insert local address into bridge "
74 "forwarding table\n");
75 goto out_filt;
79 } 76 }
80 77
81 set_bit(vid, v->vlan_bitmap); 78 set_bit(vid, v->vlan_bitmap);
@@ -98,7 +95,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
98 __vlan_delete_pvid(v, vid); 95 __vlan_delete_pvid(v, vid);
99 clear_bit(vid, v->untagged_bitmap); 96 clear_bit(vid, v->untagged_bitmap);
100 97
101 if (v->port_idx && vid) { 98 if (v->port_idx) {
102 struct net_device *dev = v->parent.port->dev; 99 struct net_device *dev = v->parent.port->dev;
103 const struct net_device_ops *ops = dev->netdev_ops; 100 const struct net_device_ops *ops = dev->netdev_ops;
104 101
@@ -248,7 +245,9 @@ bool br_allowed_egress(struct net_bridge *br,
248 return false; 245 return false;
249} 246}
250 247
251/* Must be protected by RTNL */ 248/* Must be protected by RTNL.
249 * Must be called with vid in range from 1 to 4094 inclusive.
250 */
252int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) 251int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
253{ 252{
254 struct net_port_vlans *pv = NULL; 253 struct net_port_vlans *pv = NULL;
@@ -278,7 +277,9 @@ out:
278 return err; 277 return err;
279} 278}
280 279
281/* Must be protected by RTNL */ 280/* Must be protected by RTNL.
281 * Must be called with vid in range from 1 to 4094 inclusive.
282 */
282int br_vlan_delete(struct net_bridge *br, u16 vid) 283int br_vlan_delete(struct net_bridge *br, u16 vid)
283{ 284{
284 struct net_port_vlans *pv; 285 struct net_port_vlans *pv;
@@ -289,14 +290,9 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
289 if (!pv) 290 if (!pv)
290 return -EINVAL; 291 return -EINVAL;
291 292
292 if (vid) { 293 spin_lock_bh(&br->hash_lock);
293 /* If the VID !=0 remove fdb for this vid. VID 0 is special 294 fdb_delete_by_addr(br, br->dev->dev_addr, vid);
294 * in that it's the default and is always there in the fdb. 295 spin_unlock_bh(&br->hash_lock);
295 */
296 spin_lock_bh(&br->hash_lock);
297 fdb_delete_by_addr(br, br->dev->dev_addr, vid);
298 spin_unlock_bh(&br->hash_lock);
299 }
300 296
301 __vlan_del(pv, vid); 297 __vlan_del(pv, vid);
302 return 0; 298 return 0;
@@ -329,7 +325,9 @@ unlock:
329 return 0; 325 return 0;
330} 326}
331 327
332/* Must be protected by RTNL */ 328/* Must be protected by RTNL.
329 * Must be called with vid in range from 1 to 4094 inclusive.
330 */
333int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) 331int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
334{ 332{
335 struct net_port_vlans *pv = NULL; 333 struct net_port_vlans *pv = NULL;
@@ -363,7 +361,9 @@ clean_up:
363 return err; 361 return err;
364} 362}
365 363
366/* Must be protected by RTNL */ 364/* Must be protected by RTNL.
365 * Must be called with vid in range from 1 to 4094 inclusive.
366 */
367int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) 367int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
368{ 368{
369 struct net_port_vlans *pv; 369 struct net_port_vlans *pv;
@@ -374,14 +374,9 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
374 if (!pv) 374 if (!pv)
375 return -EINVAL; 375 return -EINVAL;
376 376
377 if (vid) { 377 spin_lock_bh(&port->br->hash_lock);
378 /* If the VID !=0 remove fdb for this vid. VID 0 is special 378 fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
379 * in that it's the default and is always there in the fdb. 379 spin_unlock_bh(&port->br->hash_lock);
380 */
381 spin_lock_bh(&port->br->hash_lock);
382 fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
383 spin_unlock_bh(&port->br->hash_lock);
384 }
385 380
386 return __vlan_del(pv, vid); 381 return __vlan_del(pv, vid);
387} 382}