diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/8021q/vlan_netlink.c | 4 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 38 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 2 |
3 files changed, 30 insertions, 14 deletions
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index a9150485019..3c9cf6a8e7f 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c | |||
@@ -119,7 +119,7 @@ static int vlan_get_tx_queues(struct net *net, | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static int vlan_newlink(struct net_device *dev, | 122 | static int vlan_newlink(struct net *src_net, struct net_device *dev, |
123 | struct nlattr *tb[], struct nlattr *data[]) | 123 | struct nlattr *tb[], struct nlattr *data[]) |
124 | { | 124 | { |
125 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 125 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
@@ -131,7 +131,7 @@ static int vlan_newlink(struct net_device *dev, | |||
131 | 131 | ||
132 | if (!tb[IFLA_LINK]) | 132 | if (!tb[IFLA_LINK]) |
133 | return -EINVAL; | 133 | return -EINVAL; |
134 | real_dev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK])); | 134 | real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); |
135 | if (!real_dev) | 135 | if (!real_dev) |
136 | return -ENODEV; | 136 | return -ENODEV; |
137 | 137 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e2f3317f290..33148a56819 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -733,6 +733,20 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | |||
733 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, | 733 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
734 | }; | 734 | }; |
735 | 735 | ||
736 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | ||
737 | { | ||
738 | struct net *net; | ||
739 | /* Examine the link attributes and figure out which | ||
740 | * network namespace we are talking about. | ||
741 | */ | ||
742 | if (tb[IFLA_NET_NS_PID]) | ||
743 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | ||
744 | else | ||
745 | net = get_net(src_net); | ||
746 | return net; | ||
747 | } | ||
748 | EXPORT_SYMBOL(rtnl_link_get_net); | ||
749 | |||
736 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | 750 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) |
737 | { | 751 | { |
738 | if (dev) { | 752 | if (dev) { |
@@ -756,8 +770,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
756 | int err; | 770 | int err; |
757 | 771 | ||
758 | if (tb[IFLA_NET_NS_PID]) { | 772 | if (tb[IFLA_NET_NS_PID]) { |
759 | struct net *net; | 773 | struct net *net = rtnl_link_get_net(dev_net(dev), tb); |
760 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | ||
761 | if (IS_ERR(net)) { | 774 | if (IS_ERR(net)) { |
762 | err = PTR_ERR(net); | 775 | err = PTR_ERR(net); |
763 | goto errout; | 776 | goto errout; |
@@ -976,8 +989,8 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
976 | return 0; | 989 | return 0; |
977 | } | 990 | } |
978 | 991 | ||
979 | struct net_device *rtnl_create_link(struct net *net, char *ifname, | 992 | struct net_device *rtnl_create_link(struct net *src_net, struct net *net, |
980 | const struct rtnl_link_ops *ops, struct nlattr *tb[]) | 993 | char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) |
981 | { | 994 | { |
982 | int err; | 995 | int err; |
983 | struct net_device *dev; | 996 | struct net_device *dev; |
@@ -985,7 +998,7 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, | |||
985 | unsigned int real_num_queues = 1; | 998 | unsigned int real_num_queues = 1; |
986 | 999 | ||
987 | if (ops->get_tx_queues) { | 1000 | if (ops->get_tx_queues) { |
988 | err = ops->get_tx_queues(net, tb, &num_queues, | 1001 | err = ops->get_tx_queues(src_net, tb, &num_queues, |
989 | &real_num_queues); | 1002 | &real_num_queues); |
990 | if (err) | 1003 | if (err) |
991 | goto err; | 1004 | goto err; |
@@ -995,16 +1008,16 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, | |||
995 | if (!dev) | 1008 | if (!dev) |
996 | goto err; | 1009 | goto err; |
997 | 1010 | ||
1011 | dev_net_set(dev, net); | ||
1012 | dev->rtnl_link_ops = ops; | ||
998 | dev->real_num_tx_queues = real_num_queues; | 1013 | dev->real_num_tx_queues = real_num_queues; |
1014 | |||
999 | if (strchr(dev->name, '%')) { | 1015 | if (strchr(dev->name, '%')) { |
1000 | err = dev_alloc_name(dev, dev->name); | 1016 | err = dev_alloc_name(dev, dev->name); |
1001 | if (err < 0) | 1017 | if (err < 0) |
1002 | goto err_free; | 1018 | goto err_free; |
1003 | } | 1019 | } |
1004 | 1020 | ||
1005 | dev_net_set(dev, net); | ||
1006 | dev->rtnl_link_ops = ops; | ||
1007 | |||
1008 | if (tb[IFLA_MTU]) | 1021 | if (tb[IFLA_MTU]) |
1009 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | 1022 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); |
1010 | if (tb[IFLA_ADDRESS]) | 1023 | if (tb[IFLA_ADDRESS]) |
@@ -1083,6 +1096,7 @@ replay: | |||
1083 | 1096 | ||
1084 | if (1) { | 1097 | if (1) { |
1085 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; | 1098 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; |
1099 | struct net *dest_net; | ||
1086 | 1100 | ||
1087 | if (ops) { | 1101 | if (ops) { |
1088 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { | 1102 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { |
@@ -1147,17 +1161,19 @@ replay: | |||
1147 | if (!ifname[0]) | 1161 | if (!ifname[0]) |
1148 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | 1162 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
1149 | 1163 | ||
1150 | dev = rtnl_create_link(net, ifname, ops, tb); | 1164 | dest_net = rtnl_link_get_net(net, tb); |
1165 | dev = rtnl_create_link(net, dest_net, ifname, ops, tb); | ||
1151 | 1166 | ||
1152 | if (IS_ERR(dev)) | 1167 | if (IS_ERR(dev)) |
1153 | err = PTR_ERR(dev); | 1168 | err = PTR_ERR(dev); |
1154 | else if (ops->newlink) | 1169 | else if (ops->newlink) |
1155 | err = ops->newlink(dev, tb, data); | 1170 | err = ops->newlink(net, dev, tb, data); |
1156 | else | 1171 | else |
1157 | err = register_netdevice(dev); | 1172 | err = register_netdevice(dev); |
1158 | |||
1159 | if (err < 0 && !IS_ERR(dev)) | 1173 | if (err < 0 && !IS_ERR(dev)) |
1160 | free_netdev(dev); | 1174 | free_netdev(dev); |
1175 | |||
1176 | put_net(dest_net); | ||
1161 | return err; | 1177 | return err; |
1162 | } | 1178 | } |
1163 | } | 1179 | } |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 71a3242fb7d..a7de9e3a8f1 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1483,7 +1483,7 @@ static void ipgre_tap_setup(struct net_device *dev) | |||
1483 | dev->features |= NETIF_F_NETNS_LOCAL; | 1483 | dev->features |= NETIF_F_NETNS_LOCAL; |
1484 | } | 1484 | } |
1485 | 1485 | ||
1486 | static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], | 1486 | static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], |
1487 | struct nlattr *data[]) | 1487 | struct nlattr *data[]) |
1488 | { | 1488 | { |
1489 | struct ip_tunnel *nt; | 1489 | struct ip_tunnel *nt; |