diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 182 |
1 files changed, 117 insertions, 65 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 446cbaf81185..7ebed55b5f7d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <net/arp.h> | 50 | #include <net/arp.h> |
51 | #include <net/route.h> | 51 | #include <net/route.h> |
52 | #include <net/udp.h> | 52 | #include <net/udp.h> |
53 | #include <net/tcp.h> | ||
53 | #include <net/sock.h> | 54 | #include <net/sock.h> |
54 | #include <net/pkt_sched.h> | 55 | #include <net/pkt_sched.h> |
55 | #include <net/fib_rules.h> | 56 | #include <net/fib_rules.h> |
@@ -669,9 +670,19 @@ int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) | |||
669 | 670 | ||
670 | for (i = 0; i < RTAX_MAX; i++) { | 671 | for (i = 0; i < RTAX_MAX; i++) { |
671 | if (metrics[i]) { | 672 | if (metrics[i]) { |
673 | if (i == RTAX_CC_ALGO - 1) { | ||
674 | char tmp[TCP_CA_NAME_MAX], *name; | ||
675 | |||
676 | name = tcp_ca_get_name_by_key(metrics[i], tmp); | ||
677 | if (!name) | ||
678 | continue; | ||
679 | if (nla_put_string(skb, i + 1, name)) | ||
680 | goto nla_put_failure; | ||
681 | } else { | ||
682 | if (nla_put_u32(skb, i + 1, metrics[i])) | ||
683 | goto nla_put_failure; | ||
684 | } | ||
672 | valid++; | 685 | valid++; |
673 | if (nla_put_u32(skb, i+1, metrics[i])) | ||
674 | goto nla_put_failure; | ||
675 | } | 686 | } |
676 | } | 687 | } |
677 | 688 | ||
@@ -864,6 +875,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, | |||
864 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 875 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
865 | + nla_total_size(1) /* IFLA_LINKMODE */ | 876 | + nla_total_size(1) /* IFLA_LINKMODE */ |
866 | + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ | 877 | + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ |
878 | + nla_total_size(4) /* IFLA_LINK_NETNSID */ | ||
867 | + nla_total_size(ext_filter_mask | 879 | + nla_total_size(ext_filter_mask |
868 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ | 880 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ |
869 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ | 881 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ |
@@ -1158,6 +1170,18 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
1158 | goto nla_put_failure; | 1170 | goto nla_put_failure; |
1159 | } | 1171 | } |
1160 | 1172 | ||
1173 | if (dev->rtnl_link_ops && | ||
1174 | dev->rtnl_link_ops->get_link_net) { | ||
1175 | struct net *link_net = dev->rtnl_link_ops->get_link_net(dev); | ||
1176 | |||
1177 | if (!net_eq(dev_net(dev), link_net)) { | ||
1178 | int id = peernet2id(dev_net(dev), link_net); | ||
1179 | |||
1180 | if (nla_put_s32(skb, IFLA_LINK_NETNSID, id)) | ||
1181 | goto nla_put_failure; | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1161 | if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC))) | 1185 | if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC))) |
1162 | goto nla_put_failure; | 1186 | goto nla_put_failure; |
1163 | 1187 | ||
@@ -1188,7 +1212,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
1188 | 1212 | ||
1189 | nla_nest_end(skb, af_spec); | 1213 | nla_nest_end(skb, af_spec); |
1190 | 1214 | ||
1191 | return nlmsg_end(skb, nlh); | 1215 | nlmsg_end(skb, nlh); |
1216 | return 0; | ||
1192 | 1217 | ||
1193 | nla_put_failure: | 1218 | nla_put_failure: |
1194 | nlmsg_cancel(skb, nlh); | 1219 | nlmsg_cancel(skb, nlh); |
@@ -1223,6 +1248,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
1223 | [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, | 1248 | [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, |
1224 | [IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, /* ignored */ | 1249 | [IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, /* ignored */ |
1225 | [IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, | 1250 | [IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, |
1251 | [IFLA_LINK_NETNSID] = { .type = NLA_S32 }, | ||
1226 | }; | 1252 | }; |
1227 | 1253 | ||
1228 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 1254 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
@@ -1237,18 +1263,12 @@ static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { | |||
1237 | }; | 1263 | }; |
1238 | 1264 | ||
1239 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { | 1265 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { |
1240 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | 1266 | [IFLA_VF_MAC] = { .len = sizeof(struct ifla_vf_mac) }, |
1241 | .len = sizeof(struct ifla_vf_mac) }, | 1267 | [IFLA_VF_VLAN] = { .len = sizeof(struct ifla_vf_vlan) }, |
1242 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | 1268 | [IFLA_VF_TX_RATE] = { .len = sizeof(struct ifla_vf_tx_rate) }, |
1243 | .len = sizeof(struct ifla_vf_vlan) }, | 1269 | [IFLA_VF_SPOOFCHK] = { .len = sizeof(struct ifla_vf_spoofchk) }, |
1244 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | 1270 | [IFLA_VF_RATE] = { .len = sizeof(struct ifla_vf_rate) }, |
1245 | .len = sizeof(struct ifla_vf_tx_rate) }, | 1271 | [IFLA_VF_LINK_STATE] = { .len = sizeof(struct ifla_vf_link_state) }, |
1246 | [IFLA_VF_SPOOFCHK] = { .type = NLA_BINARY, | ||
1247 | .len = sizeof(struct ifla_vf_spoofchk) }, | ||
1248 | [IFLA_VF_RATE] = { .type = NLA_BINARY, | ||
1249 | .len = sizeof(struct ifla_vf_rate) }, | ||
1250 | [IFLA_VF_LINK_STATE] = { .type = NLA_BINARY, | ||
1251 | .len = sizeof(struct ifla_vf_link_state) }, | ||
1252 | }; | 1272 | }; |
1253 | 1273 | ||
1254 | static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { | 1274 | static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { |
@@ -1280,7 +1300,6 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1280 | s_h = cb->args[0]; | 1300 | s_h = cb->args[0]; |
1281 | s_idx = cb->args[1]; | 1301 | s_idx = cb->args[1]; |
1282 | 1302 | ||
1283 | rcu_read_lock(); | ||
1284 | cb->seq = net->dev_base_seq; | 1303 | cb->seq = net->dev_base_seq; |
1285 | 1304 | ||
1286 | /* A hack to preserve kernel<->userspace interface. | 1305 | /* A hack to preserve kernel<->userspace interface. |
@@ -1302,7 +1321,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1302 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | 1321 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
1303 | idx = 0; | 1322 | idx = 0; |
1304 | head = &net->dev_index_head[h]; | 1323 | head = &net->dev_index_head[h]; |
1305 | hlist_for_each_entry_rcu(dev, head, index_hlist) { | 1324 | hlist_for_each_entry(dev, head, index_hlist) { |
1306 | if (idx < s_idx) | 1325 | if (idx < s_idx) |
1307 | goto cont; | 1326 | goto cont; |
1308 | err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | 1327 | err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, |
@@ -1315,7 +1334,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1315 | */ | 1334 | */ |
1316 | WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); | 1335 | WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); |
1317 | 1336 | ||
1318 | if (err <= 0) | 1337 | if (err < 0) |
1319 | goto out; | 1338 | goto out; |
1320 | 1339 | ||
1321 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | 1340 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
@@ -1324,7 +1343,6 @@ cont: | |||
1324 | } | 1343 | } |
1325 | } | 1344 | } |
1326 | out: | 1345 | out: |
1327 | rcu_read_unlock(); | ||
1328 | cb->args[1] = idx; | 1346 | cb->args[1] = idx; |
1329 | cb->args[0] = h; | 1347 | cb->args[0] = h; |
1330 | 1348 | ||
@@ -1914,10 +1932,10 @@ static int rtnl_group_changelink(const struct sk_buff *skb, | |||
1914 | struct ifinfomsg *ifm, | 1932 | struct ifinfomsg *ifm, |
1915 | struct nlattr **tb) | 1933 | struct nlattr **tb) |
1916 | { | 1934 | { |
1917 | struct net_device *dev; | 1935 | struct net_device *dev, *aux; |
1918 | int err; | 1936 | int err; |
1919 | 1937 | ||
1920 | for_each_netdev(net, dev) { | 1938 | for_each_netdev_safe(net, dev, aux) { |
1921 | if (dev->group == group) { | 1939 | if (dev->group == group) { |
1922 | err = do_setlink(skb, dev, ifm, tb, NULL, 0); | 1940 | err = do_setlink(skb, dev, ifm, tb, NULL, 0); |
1923 | if (err < 0) | 1941 | if (err < 0) |
@@ -1992,11 +2010,11 @@ replay: | |||
1992 | } | 2010 | } |
1993 | 2011 | ||
1994 | if (1) { | 2012 | if (1) { |
1995 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0]; | 2013 | struct nlattr *attr[ops ? ops->maxtype + 1 : 1]; |
1996 | struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 0]; | 2014 | struct nlattr *slave_attr[m_ops ? m_ops->slave_maxtype + 1 : 1]; |
1997 | struct nlattr **data = NULL; | 2015 | struct nlattr **data = NULL; |
1998 | struct nlattr **slave_data = NULL; | 2016 | struct nlattr **slave_data = NULL; |
1999 | struct net *dest_net; | 2017 | struct net *dest_net, *link_net = NULL; |
2000 | 2018 | ||
2001 | if (ops) { | 2019 | if (ops) { |
2002 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { | 2020 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { |
@@ -2102,7 +2120,25 @@ replay: | |||
2102 | if (IS_ERR(dest_net)) | 2120 | if (IS_ERR(dest_net)) |
2103 | return PTR_ERR(dest_net); | 2121 | return PTR_ERR(dest_net); |
2104 | 2122 | ||
2105 | dev = rtnl_create_link(dest_net, ifname, name_assign_type, ops, tb); | 2123 | err = -EPERM; |
2124 | if (!netlink_ns_capable(skb, dest_net->user_ns, CAP_NET_ADMIN)) | ||
2125 | goto out; | ||
2126 | |||
2127 | if (tb[IFLA_LINK_NETNSID]) { | ||
2128 | int id = nla_get_s32(tb[IFLA_LINK_NETNSID]); | ||
2129 | |||
2130 | link_net = get_net_ns_by_id(dest_net, id); | ||
2131 | if (!link_net) { | ||
2132 | err = -EINVAL; | ||
2133 | goto out; | ||
2134 | } | ||
2135 | err = -EPERM; | ||
2136 | if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN)) | ||
2137 | goto out; | ||
2138 | } | ||
2139 | |||
2140 | dev = rtnl_create_link(link_net ? : dest_net, ifname, | ||
2141 | name_assign_type, ops, tb); | ||
2106 | if (IS_ERR(dev)) { | 2142 | if (IS_ERR(dev)) { |
2107 | err = PTR_ERR(dev); | 2143 | err = PTR_ERR(dev); |
2108 | goto out; | 2144 | goto out; |
@@ -2111,7 +2147,7 @@ replay: | |||
2111 | dev->ifindex = ifm->ifi_index; | 2147 | dev->ifindex = ifm->ifi_index; |
2112 | 2148 | ||
2113 | if (ops->newlink) { | 2149 | if (ops->newlink) { |
2114 | err = ops->newlink(net, dev, tb, data); | 2150 | err = ops->newlink(link_net ? : net, dev, tb, data); |
2115 | /* Drivers should call free_netdev() in ->destructor | 2151 | /* Drivers should call free_netdev() in ->destructor |
2116 | * and unregister it on failure after registration | 2152 | * and unregister it on failure after registration |
2117 | * so that device could be finally freed in rtnl_unlock. | 2153 | * so that device could be finally freed in rtnl_unlock. |
@@ -2131,10 +2167,27 @@ replay: | |||
2131 | } | 2167 | } |
2132 | err = rtnl_configure_link(dev, ifm); | 2168 | err = rtnl_configure_link(dev, ifm); |
2133 | if (err < 0) | 2169 | if (err < 0) |
2134 | unregister_netdevice(dev); | 2170 | goto out_unregister; |
2171 | if (link_net) { | ||
2172 | err = dev_change_net_namespace(dev, dest_net, ifname); | ||
2173 | if (err < 0) | ||
2174 | goto out_unregister; | ||
2175 | } | ||
2135 | out: | 2176 | out: |
2177 | if (link_net) | ||
2178 | put_net(link_net); | ||
2136 | put_net(dest_net); | 2179 | put_net(dest_net); |
2137 | return err; | 2180 | return err; |
2181 | out_unregister: | ||
2182 | if (ops->newlink) { | ||
2183 | LIST_HEAD(list_kill); | ||
2184 | |||
2185 | ops->dellink(dev, &list_kill); | ||
2186 | unregister_netdevice_many(&list_kill); | ||
2187 | } else { | ||
2188 | unregister_netdevice(dev); | ||
2189 | } | ||
2190 | goto out; | ||
2138 | } | 2191 | } |
2139 | } | 2192 | } |
2140 | 2193 | ||
@@ -2315,7 +2368,8 @@ static int nlmsg_populate_fdb_fill(struct sk_buff *skb, | |||
2315 | if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) | 2368 | if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) |
2316 | goto nla_put_failure; | 2369 | goto nla_put_failure; |
2317 | 2370 | ||
2318 | return nlmsg_end(skb, nlh); | 2371 | nlmsg_end(skb, nlh); |
2372 | return 0; | ||
2319 | 2373 | ||
2320 | nla_put_failure: | 2374 | nla_put_failure: |
2321 | nlmsg_cancel(skb, nlh); | 2375 | nlmsg_cancel(skb, nlh); |
@@ -2698,10 +2752,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
2698 | idx); | 2752 | idx); |
2699 | } | 2753 | } |
2700 | 2754 | ||
2701 | idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx); | ||
2702 | if (dev->netdev_ops->ndo_fdb_dump) | 2755 | if (dev->netdev_ops->ndo_fdb_dump) |
2703 | idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, bdev, dev, | 2756 | idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL, |
2704 | idx); | 2757 | idx); |
2758 | else | ||
2759 | idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx); | ||
2705 | 2760 | ||
2706 | cops = NULL; | 2761 | cops = NULL; |
2707 | } | 2762 | } |
@@ -2797,7 +2852,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, | |||
2797 | 2852 | ||
2798 | nla_nest_end(skb, protinfo); | 2853 | nla_nest_end(skb, protinfo); |
2799 | 2854 | ||
2800 | return nlmsg_end(skb, nlh); | 2855 | nlmsg_end(skb, nlh); |
2856 | return 0; | ||
2801 | nla_put_failure: | 2857 | nla_put_failure: |
2802 | nlmsg_cancel(skb, nlh); | 2858 | nlmsg_cancel(skb, nlh); |
2803 | return -EMSGSIZE; | 2859 | return -EMSGSIZE; |
@@ -2868,32 +2924,24 @@ static inline size_t bridge_nlmsg_size(void) | |||
2868 | + nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */ | 2924 | + nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_MODE */ |
2869 | } | 2925 | } |
2870 | 2926 | ||
2871 | static int rtnl_bridge_notify(struct net_device *dev, u16 flags) | 2927 | static int rtnl_bridge_notify(struct net_device *dev) |
2872 | { | 2928 | { |
2873 | struct net *net = dev_net(dev); | 2929 | struct net *net = dev_net(dev); |
2874 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); | ||
2875 | struct sk_buff *skb; | 2930 | struct sk_buff *skb; |
2876 | int err = -EOPNOTSUPP; | 2931 | int err = -EOPNOTSUPP; |
2877 | 2932 | ||
2933 | if (!dev->netdev_ops->ndo_bridge_getlink) | ||
2934 | return 0; | ||
2935 | |||
2878 | skb = nlmsg_new(bridge_nlmsg_size(), GFP_ATOMIC); | 2936 | skb = nlmsg_new(bridge_nlmsg_size(), GFP_ATOMIC); |
2879 | if (!skb) { | 2937 | if (!skb) { |
2880 | err = -ENOMEM; | 2938 | err = -ENOMEM; |
2881 | goto errout; | 2939 | goto errout; |
2882 | } | 2940 | } |
2883 | 2941 | ||
2884 | if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) && | 2942 | err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0); |
2885 | br_dev && br_dev->netdev_ops->ndo_bridge_getlink) { | 2943 | if (err < 0) |
2886 | err = br_dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0); | 2944 | goto errout; |
2887 | if (err < 0) | ||
2888 | goto errout; | ||
2889 | } | ||
2890 | |||
2891 | if ((flags & BRIDGE_FLAGS_SELF) && | ||
2892 | dev->netdev_ops->ndo_bridge_getlink) { | ||
2893 | err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev, 0); | ||
2894 | if (err < 0) | ||
2895 | goto errout; | ||
2896 | } | ||
2897 | 2945 | ||
2898 | if (!skb->len) | 2946 | if (!skb->len) |
2899 | goto errout; | 2947 | goto errout; |
@@ -2915,7 +2963,7 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2915 | struct net_device *dev; | 2963 | struct net_device *dev; |
2916 | struct nlattr *br_spec, *attr = NULL; | 2964 | struct nlattr *br_spec, *attr = NULL; |
2917 | int rem, err = -EOPNOTSUPP; | 2965 | int rem, err = -EOPNOTSUPP; |
2918 | u16 oflags, flags = 0; | 2966 | u16 flags = 0; |
2919 | bool have_flags = false; | 2967 | bool have_flags = false; |
2920 | 2968 | ||
2921 | if (nlmsg_len(nlh) < sizeof(*ifm)) | 2969 | if (nlmsg_len(nlh) < sizeof(*ifm)) |
@@ -2945,8 +2993,6 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2945 | } | 2993 | } |
2946 | } | 2994 | } |
2947 | 2995 | ||
2948 | oflags = flags; | ||
2949 | |||
2950 | if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { | 2996 | if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { |
2951 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); | 2997 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); |
2952 | 2998 | ||
@@ -2955,7 +3001,7 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2955 | goto out; | 3001 | goto out; |
2956 | } | 3002 | } |
2957 | 3003 | ||
2958 | err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh); | 3004 | err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh, flags); |
2959 | if (err) | 3005 | if (err) |
2960 | goto out; | 3006 | goto out; |
2961 | 3007 | ||
@@ -2966,17 +3012,20 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2966 | if (!dev->netdev_ops->ndo_bridge_setlink) | 3012 | if (!dev->netdev_ops->ndo_bridge_setlink) |
2967 | err = -EOPNOTSUPP; | 3013 | err = -EOPNOTSUPP; |
2968 | else | 3014 | else |
2969 | err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh); | 3015 | err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh, |
2970 | 3016 | flags); | |
2971 | if (!err) | 3017 | if (!err) { |
2972 | flags &= ~BRIDGE_FLAGS_SELF; | 3018 | flags &= ~BRIDGE_FLAGS_SELF; |
3019 | |||
3020 | /* Generate event to notify upper layer of bridge | ||
3021 | * change | ||
3022 | */ | ||
3023 | err = rtnl_bridge_notify(dev); | ||
3024 | } | ||
2973 | } | 3025 | } |
2974 | 3026 | ||
2975 | if (have_flags) | 3027 | if (have_flags) |
2976 | memcpy(nla_data(attr), &flags, sizeof(flags)); | 3028 | memcpy(nla_data(attr), &flags, sizeof(flags)); |
2977 | /* Generate event to notify upper layer of bridge change */ | ||
2978 | if (!err) | ||
2979 | err = rtnl_bridge_notify(dev, oflags); | ||
2980 | out: | 3029 | out: |
2981 | return err; | 3030 | return err; |
2982 | } | 3031 | } |
@@ -2988,7 +3037,7 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
2988 | struct net_device *dev; | 3037 | struct net_device *dev; |
2989 | struct nlattr *br_spec, *attr = NULL; | 3038 | struct nlattr *br_spec, *attr = NULL; |
2990 | int rem, err = -EOPNOTSUPP; | 3039 | int rem, err = -EOPNOTSUPP; |
2991 | u16 oflags, flags = 0; | 3040 | u16 flags = 0; |
2992 | bool have_flags = false; | 3041 | bool have_flags = false; |
2993 | 3042 | ||
2994 | if (nlmsg_len(nlh) < sizeof(*ifm)) | 3043 | if (nlmsg_len(nlh) < sizeof(*ifm)) |
@@ -3018,8 +3067,6 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3018 | } | 3067 | } |
3019 | } | 3068 | } |
3020 | 3069 | ||
3021 | oflags = flags; | ||
3022 | |||
3023 | if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { | 3070 | if (!flags || (flags & BRIDGE_FLAGS_MASTER)) { |
3024 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); | 3071 | struct net_device *br_dev = netdev_master_upper_dev_get(dev); |
3025 | 3072 | ||
@@ -3028,7 +3075,7 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3028 | goto out; | 3075 | goto out; |
3029 | } | 3076 | } |
3030 | 3077 | ||
3031 | err = br_dev->netdev_ops->ndo_bridge_dellink(dev, nlh); | 3078 | err = br_dev->netdev_ops->ndo_bridge_dellink(dev, nlh, flags); |
3032 | if (err) | 3079 | if (err) |
3033 | goto out; | 3080 | goto out; |
3034 | 3081 | ||
@@ -3039,17 +3086,21 @@ static int rtnl_bridge_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
3039 | if (!dev->netdev_ops->ndo_bridge_dellink) | 3086 | if (!dev->netdev_ops->ndo_bridge_dellink) |
3040 | err = -EOPNOTSUPP; | 3087 | err = -EOPNOTSUPP; |
3041 | else | 3088 | else |
3042 | err = dev->netdev_ops->ndo_bridge_dellink(dev, nlh); | 3089 | err = dev->netdev_ops->ndo_bridge_dellink(dev, nlh, |
3090 | flags); | ||
3043 | 3091 | ||
3044 | if (!err) | 3092 | if (!err) { |
3045 | flags &= ~BRIDGE_FLAGS_SELF; | 3093 | flags &= ~BRIDGE_FLAGS_SELF; |
3094 | |||
3095 | /* Generate event to notify upper layer of bridge | ||
3096 | * change | ||
3097 | */ | ||
3098 | err = rtnl_bridge_notify(dev); | ||
3099 | } | ||
3046 | } | 3100 | } |
3047 | 3101 | ||
3048 | if (have_flags) | 3102 | if (have_flags) |
3049 | memcpy(nla_data(attr), &flags, sizeof(flags)); | 3103 | memcpy(nla_data(attr), &flags, sizeof(flags)); |
3050 | /* Generate event to notify upper layer of bridge change */ | ||
3051 | if (!err) | ||
3052 | err = rtnl_bridge_notify(dev, oflags); | ||
3053 | out: | 3104 | out: |
3054 | return err; | 3105 | return err; |
3055 | } | 3106 | } |
@@ -3139,6 +3190,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi | |||
3139 | case NETDEV_UNREGISTER_FINAL: | 3190 | case NETDEV_UNREGISTER_FINAL: |
3140 | case NETDEV_RELEASE: | 3191 | case NETDEV_RELEASE: |
3141 | case NETDEV_JOIN: | 3192 | case NETDEV_JOIN: |
3193 | case NETDEV_BONDING_INFO: | ||
3142 | break; | 3194 | break; |
3143 | default: | 3195 | default: |
3144 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL); | 3196 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL); |