aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d7c4bb4b1820..abd936d8a716 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -850,6 +850,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
850 struct nlattr *attr, *af_spec; 850 struct nlattr *attr, *af_spec;
851 struct rtnl_af_ops *af_ops; 851 struct rtnl_af_ops *af_ops;
852 852
853 ASSERT_RTNL();
853 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); 854 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
854 if (nlh == NULL) 855 if (nlh == NULL)
855 return -EMSGSIZE; 856 return -EMSGSIZE;
@@ -1007,10 +1008,11 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
1007 s_h = cb->args[0]; 1008 s_h = cb->args[0];
1008 s_idx = cb->args[1]; 1009 s_idx = cb->args[1];
1009 1010
1011 rcu_read_lock();
1010 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 1012 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
1011 idx = 0; 1013 idx = 0;
1012 head = &net->dev_index_head[h]; 1014 head = &net->dev_index_head[h];
1013 hlist_for_each_entry(dev, node, head, index_hlist) { 1015 hlist_for_each_entry_rcu(dev, node, head, index_hlist) {
1014 if (idx < s_idx) 1016 if (idx < s_idx)
1015 goto cont; 1017 goto cont;
1016 if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, 1018 if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK,
@@ -1023,6 +1025,7 @@ cont:
1023 } 1025 }
1024 } 1026 }
1025out: 1027out:
1028 rcu_read_unlock();
1026 cb->args[1] = idx; 1029 cb->args[1] = idx;
1027 cb->args[0] = h; 1030 cb->args[0] = h;
1028 1031
@@ -1043,6 +1046,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
1043 [IFLA_LINKMODE] = { .type = NLA_U8 }, 1046 [IFLA_LINKMODE] = { .type = NLA_U8 },
1044 [IFLA_LINKINFO] = { .type = NLA_NESTED }, 1047 [IFLA_LINKINFO] = { .type = NLA_NESTED },
1045 [IFLA_NET_NS_PID] = { .type = NLA_U32 }, 1048 [IFLA_NET_NS_PID] = { .type = NLA_U32 },
1049 [IFLA_NET_NS_FD] = { .type = NLA_U32 },
1046 [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, 1050 [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 },
1047 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, 1051 [IFLA_VFINFO_LIST] = {. type = NLA_NESTED },
1048 [IFLA_VF_PORTS] = { .type = NLA_NESTED }, 1052 [IFLA_VF_PORTS] = { .type = NLA_NESTED },
@@ -1091,6 +1095,8 @@ struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[])
1091 */ 1095 */
1092 if (tb[IFLA_NET_NS_PID]) 1096 if (tb[IFLA_NET_NS_PID])
1093 net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); 1097 net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID]));
1098 else if (tb[IFLA_NET_NS_FD])
1099 net = get_net_ns_by_fd(nla_get_u32(tb[IFLA_NET_NS_FD]));
1094 else 1100 else
1095 net = get_net(src_net); 1101 net = get_net(src_net);
1096 return net; 1102 return net;
@@ -1221,7 +1227,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
1221 int send_addr_notify = 0; 1227 int send_addr_notify = 0;
1222 int err; 1228 int err;
1223 1229
1224 if (tb[IFLA_NET_NS_PID]) { 1230 if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
1225 struct net *net = rtnl_link_get_net(dev_net(dev), tb); 1231 struct net *net = rtnl_link_get_net(dev_net(dev), tb);
1226 if (IS_ERR(net)) { 1232 if (IS_ERR(net)) {
1227 err = PTR_ERR(net); 1233 err = PTR_ERR(net);
@@ -1499,6 +1505,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1499 char ifname[IFNAMSIZ]; 1505 char ifname[IFNAMSIZ];
1500 struct nlattr *tb[IFLA_MAX+1]; 1506 struct nlattr *tb[IFLA_MAX+1];
1501 int err; 1507 int err;
1508 LIST_HEAD(list_kill);
1502 1509
1503 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); 1510 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
1504 if (err < 0) 1511 if (err < 0)
@@ -1522,7 +1529,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1522 if (!ops) 1529 if (!ops)
1523 return -EOPNOTSUPP; 1530 return -EOPNOTSUPP;
1524 1531
1525 ops->dellink(dev, NULL); 1532 ops->dellink(dev, &list_kill);
1533 unregister_netdevice_many(&list_kill);
1534 list_del(&list_kill);
1526 return 0; 1535 return 0;
1527} 1536}
1528 1537
@@ -1570,12 +1579,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
1570 dev->rtnl_link_state = RTNL_LINK_INITIALIZING; 1579 dev->rtnl_link_state = RTNL_LINK_INITIALIZING;
1571 dev->real_num_tx_queues = real_num_queues; 1580 dev->real_num_tx_queues = real_num_queues;
1572 1581
1573 if (strchr(dev->name, '%')) {
1574 err = dev_alloc_name(dev, dev->name);
1575 if (err < 0)
1576 goto err_free;
1577 }
1578
1579 if (tb[IFLA_MTU]) 1582 if (tb[IFLA_MTU])
1580 dev->mtu = nla_get_u32(tb[IFLA_MTU]); 1583 dev->mtu = nla_get_u32(tb[IFLA_MTU]);
1581 if (tb[IFLA_ADDRESS]) 1584 if (tb[IFLA_ADDRESS])
@@ -1595,8 +1598,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
1595 1598
1596 return dev; 1599 return dev;
1597 1600
1598err_free:
1599 free_netdev(dev);
1600err: 1601err:
1601 return ERR_PTR(err); 1602 return ERR_PTR(err);
1602} 1603}
@@ -1963,6 +1964,8 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
1963 case NETDEV_GOING_DOWN: 1964 case NETDEV_GOING_DOWN:
1964 case NETDEV_UNREGISTER: 1965 case NETDEV_UNREGISTER:
1965 case NETDEV_UNREGISTER_BATCH: 1966 case NETDEV_UNREGISTER_BATCH:
1967 case NETDEV_RELEASE:
1968 case NETDEV_JOIN:
1966 break; 1969 break;
1967 default: 1970 default:
1968 rtmsg_ifinfo(RTM_NEWLINK, dev, 0); 1971 rtmsg_ifinfo(RTM_NEWLINK, dev, 0);