diff options
-rw-r--r-- | net/core/rtnetlink.c | 26 |
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); |
2446 | out: | 2456 | out: |
2447 | return err; | 2457 | return err; |
2448 | } | 2458 | } |