aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}