aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn Fastabend <john.r.fastabend@intel.com>2012-11-02 12:32:36 -0400
committerDavid S. Miller <davem@davemloft.net>2012-11-03 15:37:36 -0400
commitc38e01b8b958cb6606bcc156d3d00c3ee99a13f8 (patch)
treed2cb212bc2126117c32d451eb0b7a92d658f239a /net
parent26cdfb4915a9a408f4c1f04111999a11eb0ee606 (diff)
net: fix bridge notify hook to manage flags correctly
The bridge notify hook rtnl_bridge_notify() was not handling the case where the master flags was set or with both flags set. First flags are not being passed correctly and second the logic to parse them is broken. This patch passes the original flags value and fixes the logic. Reported-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/rtnetlink.c26
1 files changed, 18 insertions, 8 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a0e350763fbe..04a201abcf0e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2364,13 +2364,19 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
2364 goto errout; 2364 goto errout;
2365 } 2365 }
2366 2366
2367 if (!flags && master && master->netdev_ops->ndo_bridge_getlink) 2367 if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) &&
2368 master && master->netdev_ops->ndo_bridge_getlink) {
2368 err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev); 2369 err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
2369 else if (dev->netdev_ops->ndo_bridge_getlink) 2370 if (err < 0)
2370 err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev); 2371 goto errout;
2372 }
2371 2373
2372 if (err < 0) 2374 if ((flags & BRIDGE_FLAGS_SELF) &&
2373 goto errout; 2375 dev->netdev_ops->ndo_bridge_getlink) {
2376 err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
2377 if (err < 0)
2378 goto errout;
2379 }
2374 2380
2375 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 2381 rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
2376 return 0; 2382 return 0;
@@ -2389,7 +2395,8 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2389 struct net_device *dev; 2395 struct net_device *dev;
2390 struct nlattr *br_spec, *attr = NULL; 2396 struct nlattr *br_spec, *attr = NULL;
2391 int rem, err = -EOPNOTSUPP; 2397 int rem, err = -EOPNOTSUPP;
2392 u16 flags = 0; 2398 u16 oflags, flags = 0;
2399 bool have_flags = false;
2393 2400
2394 if (nlmsg_len(nlh) < sizeof(*ifm)) 2401 if (nlmsg_len(nlh) < sizeof(*ifm))
2395 return -EINVAL; 2402 return -EINVAL;
@@ -2408,12 +2415,15 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2408 if (br_spec) { 2415 if (br_spec) {
2409 nla_for_each_nested(attr, br_spec, rem) { 2416 nla_for_each_nested(attr, br_spec, rem) {
2410 if (nla_type(attr) == IFLA_BRIDGE_FLAGS) { 2417 if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
2418 have_flags = true;
2411 flags = nla_get_u16(attr); 2419 flags = nla_get_u16(attr);
2412 break; 2420 break;
2413 } 2421 }
2414 } 2422 }
2415 } 2423 }
2416 2424
2425 oflags = flags;
2426
2417 if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { 2427 if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
2418 if (!dev->master || 2428 if (!dev->master ||
2419 !dev->master->netdev_ops->ndo_bridge_setlink) { 2429 !dev->master->netdev_ops->ndo_bridge_setlink) {
@@ -2438,11 +2448,11 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
2438 flags &= ~BRIDGE_FLAGS_SELF; 2448 flags &= ~BRIDGE_FLAGS_SELF;
2439 } 2449 }
2440 2450
2441 if (attr && nla_type(attr) == IFLA_BRIDGE_FLAGS) 2451 if (have_flags)
2442 memcpy(nla_data(attr), &flags, sizeof(flags)); 2452 memcpy(nla_data(attr), &flags, sizeof(flags));
2443 /* Generate event to notify upper layer of bridge change */ 2453 /* Generate event to notify upper layer of bridge change */
2444 if (!err) 2454 if (!err)
2445 err = rtnl_bridge_notify(dev, flags); 2455 err = rtnl_bridge_notify(dev, oflags);
2446out: 2456out:
2447 return err; 2457 return err;
2448} 2458}