aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@aristanetworks.com>2009-11-08 03:53:51 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-08 03:53:51 -0500
commit81adee47dfb608df3ad0b91d230fb3cef75f0060 (patch)
treee9d7a41872f84c1395e21915e5f92c05ab872e69
parentf7a3a1d8affe563846fc17f0e7c0cc1500190c57 (diff)
net: Support specifying the network namespace upon device creation.
There is no good reason to not support userspace specifying the network namespace during device creation, and it makes it easier to create a network device and pass it to a child network namespace with a well known name. We have to be careful to ensure that the target network namespace for the new device exists through the life of the call. To keep that logic clear I have factored out the network namespace grabbing logic into rtnl_link_get_net. In addtion we need to continue to pass the source network namespace to the rtnl_link_ops.newlink method so that we can find the base device source network namespace. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
-rw-r--r--drivers/net/can/dev.c2
-rw-r--r--drivers/net/macvlan.c4
-rw-r--r--drivers/net/veth.c15
-rw-r--r--include/net/rtnetlink.h8
-rw-r--r--net/8021q/vlan_netlink.c4
-rw-r--r--net/core/rtnetlink.c38
-rw-r--r--net/ipv4/ip_gre.c2
7 files changed, 50 insertions, 23 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index c3db111d2ff5..5fe34d64ca2a 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -674,7 +674,7 @@ nla_put_failure:
674 return -EMSGSIZE; 674 return -EMSGSIZE;
675} 675}
676 676
677static int can_newlink(struct net_device *dev, 677static int can_newlink(struct net *src_net, struct net_device *dev,
678 struct nlattr *tb[], struct nlattr *data[]) 678 struct nlattr *tb[], struct nlattr *data[])
679{ 679{
680 return -EOPNOTSUPP; 680 return -EOPNOTSUPP;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 20b7707f38ef..d7dba3f6f763 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -504,7 +504,7 @@ static int macvlan_get_tx_queues(struct net *net,
504 return 0; 504 return 0;
505} 505}
506 506
507static int macvlan_newlink(struct net_device *dev, 507static int macvlan_newlink(struct net *src_net, struct net_device *dev,
508 struct nlattr *tb[], struct nlattr *data[]) 508 struct nlattr *tb[], struct nlattr *data[])
509{ 509{
510 struct macvlan_dev *vlan = netdev_priv(dev); 510 struct macvlan_dev *vlan = netdev_priv(dev);
@@ -515,7 +515,7 @@ static int macvlan_newlink(struct net_device *dev,
515 if (!tb[IFLA_LINK]) 515 if (!tb[IFLA_LINK])
516 return -EINVAL; 516 return -EINVAL;
517 517
518 lowerdev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK])); 518 lowerdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
519 if (lowerdev == NULL) 519 if (lowerdev == NULL)
520 return -ENODEV; 520 return -ENODEV;
521 521
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 9bed694cd215..2d657f2314cb 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -340,7 +340,7 @@ static int veth_validate(struct nlattr *tb[], struct nlattr *data[])
340 340
341static struct rtnl_link_ops veth_link_ops; 341static struct rtnl_link_ops veth_link_ops;
342 342
343static int veth_newlink(struct net_device *dev, 343static int veth_newlink(struct net *src_net, struct net_device *dev,
344 struct nlattr *tb[], struct nlattr *data[]) 344 struct nlattr *tb[], struct nlattr *data[])
345{ 345{
346 int err; 346 int err;
@@ -348,6 +348,7 @@ static int veth_newlink(struct net_device *dev,
348 struct veth_priv *priv; 348 struct veth_priv *priv;
349 char ifname[IFNAMSIZ]; 349 char ifname[IFNAMSIZ];
350 struct nlattr *peer_tb[IFLA_MAX + 1], **tbp; 350 struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
351 struct net *net;
351 352
352 /* 353 /*
353 * create and register peer first 354 * create and register peer first
@@ -380,14 +381,22 @@ static int veth_newlink(struct net_device *dev,
380 else 381 else
381 snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d"); 382 snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
382 383
383 peer = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp); 384 net = rtnl_link_get_net(src_net, tbp);
384 if (IS_ERR(peer)) 385 if (IS_ERR(net))
386 return PTR_ERR(net);
387
388 peer = rtnl_create_link(src_net, net, ifname, &veth_link_ops, tbp);
389 if (IS_ERR(peer)) {
390 put_net(net);
385 return PTR_ERR(peer); 391 return PTR_ERR(peer);
392 }
386 393
387 if (tbp[IFLA_ADDRESS] == NULL) 394 if (tbp[IFLA_ADDRESS] == NULL)
388 random_ether_addr(peer->dev_addr); 395 random_ether_addr(peer->dev_addr);
389 396
390 err = register_netdevice(peer); 397 err = register_netdevice(peer);
398 put_net(net);
399 net = NULL;
391 if (err < 0) 400 if (err < 0)
392 goto err_register_peer; 401 goto err_register_peer;
393 402
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index cd5af1f508f2..48d3efcb0880 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -55,7 +55,8 @@ struct rtnl_link_ops {
55 int (*validate)(struct nlattr *tb[], 55 int (*validate)(struct nlattr *tb[],
56 struct nlattr *data[]); 56 struct nlattr *data[]);
57 57
58 int (*newlink)(struct net_device *dev, 58 int (*newlink)(struct net *src_net,
59 struct net_device *dev,
59 struct nlattr *tb[], 60 struct nlattr *tb[],
60 struct nlattr *data[]); 61 struct nlattr *data[]);
61 int (*changelink)(struct net_device *dev, 62 int (*changelink)(struct net_device *dev,
@@ -83,8 +84,9 @@ extern void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops);
83extern int rtnl_link_register(struct rtnl_link_ops *ops); 84extern int rtnl_link_register(struct rtnl_link_ops *ops);
84extern void rtnl_link_unregister(struct rtnl_link_ops *ops); 85extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
85 86
86extern struct net_device *rtnl_create_link(struct net *net, char *ifname, 87extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
87 const struct rtnl_link_ops *ops, struct nlattr *tb[]); 88extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
89 char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
88extern const struct nla_policy ifla_policy[IFLA_MAX+1]; 90extern const struct nla_policy ifla_policy[IFLA_MAX+1];
89 91
90#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind) 92#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index a91504850195..3c9cf6a8e7fb 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
122static int vlan_newlink(struct net_device *dev, 122static 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 e2f3317f290f..33148a568199 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
736struct 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}
748EXPORT_SYMBOL(rtnl_link_get_net);
749
736static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) 750static 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
979struct net_device *rtnl_create_link(struct net *net, char *ifname, 992struct 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 71a3242fb7d0..a7de9e3a8f18 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
1486static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], 1486static 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;