aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2007-11-20 01:26:51 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:54:25 -0500
commit97c53cacf00d1f5aa04adabfebcc806ca8b22b10 (patch)
tree6b7223df312aa27a5017c4d7c4d1e500a33ed8d8 /net/core/rtnetlink.c
parentb854272b3c732316676e9128f7b9e6f1e1ff88b0 (diff)
[NET]: Make rtnetlink infrastructure network namespace aware (v3)
After this patch none of the netlink callback support anything except the initial network namespace but the rtnetlink infrastructure now handles multiple network namespaces. Changes from v2: - IPv6 addrlabel processing Changes from v1: - no need for special rtnl_unlock handling - fixed IPv6 ndisc Signed-off-by: Denis V. Lunev <den@openvz.org> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c63
1 files changed, 52 insertions, 11 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4edc3dac4ccd..9efaf35934f4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -60,7 +60,6 @@ struct rtnl_link
60}; 60};
61 61
62static DEFINE_MUTEX(rtnl_mutex); 62static DEFINE_MUTEX(rtnl_mutex);
63static struct sock *rtnl;
64 63
65void rtnl_lock(void) 64void rtnl_lock(void)
66{ 65{
@@ -458,8 +457,9 @@ size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size)
458 return ret; 457 return ret;
459} 458}
460 459
461int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) 460int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo)
462{ 461{
462 struct sock *rtnl = net->rtnl;
463 int err = 0; 463 int err = 0;
464 464
465 NETLINK_CB(skb).dst_group = group; 465 NETLINK_CB(skb).dst_group = group;
@@ -471,14 +471,17 @@ int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
471 return err; 471 return err;
472} 472}
473 473
474int rtnl_unicast(struct sk_buff *skb, u32 pid) 474int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid)
475{ 475{
476 struct sock *rtnl = net->rtnl;
477
476 return nlmsg_unicast(rtnl, skb, pid); 478 return nlmsg_unicast(rtnl, skb, pid);
477} 479}
478 480
479int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group, 481int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
480 struct nlmsghdr *nlh, gfp_t flags) 482 struct nlmsghdr *nlh, gfp_t flags)
481{ 483{
484 struct sock *rtnl = net->rtnl;
482 int report = 0; 485 int report = 0;
483 486
484 if (nlh) 487 if (nlh)
@@ -487,8 +490,10 @@ int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
487 return nlmsg_notify(rtnl, skb, pid, group, report, flags); 490 return nlmsg_notify(rtnl, skb, pid, group, report, flags);
488} 491}
489 492
490void rtnl_set_sk_err(u32 group, int error) 493void rtnl_set_sk_err(struct net *net, u32 group, int error)
491{ 494{
495 struct sock *rtnl = net->rtnl;
496
492 netlink_set_err(rtnl, 0, group, error); 497 netlink_set_err(rtnl, 0, group, error);
493} 498}
494 499
@@ -1201,7 +1206,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1201 kfree_skb(nskb); 1206 kfree_skb(nskb);
1202 goto errout; 1207 goto errout;
1203 } 1208 }
1204 err = rtnl_unicast(nskb, NETLINK_CB(skb).pid); 1209 err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid);
1205errout: 1210errout:
1206 dev_put(dev); 1211 dev_put(dev);
1207 1212
@@ -1252,10 +1257,10 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
1252 kfree_skb(skb); 1257 kfree_skb(skb);
1253 goto errout; 1258 goto errout;
1254 } 1259 }
1255 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); 1260 err = rtnl_notify(skb, &init_net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
1256errout: 1261errout:
1257 if (err < 0) 1262 if (err < 0)
1258 rtnl_set_sk_err(RTNLGRP_LINK, err); 1263 rtnl_set_sk_err(&init_net, RTNLGRP_LINK, err);
1259} 1264}
1260 1265
1261/* Protected by RTNL sempahore. */ 1266/* Protected by RTNL sempahore. */
@@ -1266,6 +1271,7 @@ static int rtattr_max;
1266 1271
1267static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 1272static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1268{ 1273{
1274 struct net *net = skb->sk->sk_net;
1269 rtnl_doit_func doit; 1275 rtnl_doit_func doit;
1270 int sz_idx, kind; 1276 int sz_idx, kind;
1271 int min_len; 1277 int min_len;
@@ -1294,6 +1300,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1294 return -EPERM; 1300 return -EPERM;
1295 1301
1296 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 1302 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
1303 struct sock *rtnl;
1297 rtnl_dumpit_func dumpit; 1304 rtnl_dumpit_func dumpit;
1298 1305
1299 dumpit = rtnl_get_dumpit(family, type); 1306 dumpit = rtnl_get_dumpit(family, type);
@@ -1301,6 +1308,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1301 return -EOPNOTSUPP; 1308 return -EOPNOTSUPP;
1302 1309
1303 __rtnl_unlock(); 1310 __rtnl_unlock();
1311 rtnl = net->rtnl;
1304 err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); 1312 err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
1305 rtnl_lock(); 1313 rtnl_lock();
1306 return err; 1314 return err;
@@ -1373,6 +1381,40 @@ static struct notifier_block rtnetlink_dev_notifier = {
1373 .notifier_call = rtnetlink_event, 1381 .notifier_call = rtnetlink_event,
1374}; 1382};
1375 1383
1384
1385static int rtnetlink_net_init(struct net *net)
1386{
1387 struct sock *sk;
1388 sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX,
1389 rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
1390 if (!sk)
1391 return -ENOMEM;
1392
1393 /* Don't hold an extra reference on the namespace */
1394 put_net(sk->sk_net);
1395 net->rtnl = sk;
1396 return 0;
1397}
1398
1399static void rtnetlink_net_exit(struct net *net)
1400{
1401 struct sock *sk = net->rtnl;
1402 if (sk) {
1403 /* At the last minute lie and say this is a socket for the
1404 * initial network namespace. So the socket will be safe to
1405 * free.
1406 */
1407 sk->sk_net = get_net(&init_net);
1408 sock_put(sk);
1409 net->rtnl = NULL;
1410 }
1411}
1412
1413static struct pernet_operations rtnetlink_net_ops = {
1414 .init = rtnetlink_net_init,
1415 .exit = rtnetlink_net_exit,
1416};
1417
1376void __init rtnetlink_init(void) 1418void __init rtnetlink_init(void)
1377{ 1419{
1378 int i; 1420 int i;
@@ -1385,10 +1427,9 @@ void __init rtnetlink_init(void)
1385 if (!rta_buf) 1427 if (!rta_buf)
1386 panic("rtnetlink_init: cannot allocate rta_buf\n"); 1428 panic("rtnetlink_init: cannot allocate rta_buf\n");
1387 1429
1388 rtnl = netlink_kernel_create(&init_net, NETLINK_ROUTE, RTNLGRP_MAX, 1430 if (register_pernet_subsys(&rtnetlink_net_ops))
1389 rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
1390 if (rtnl == NULL)
1391 panic("rtnetlink_init: cannot initialize rtnetlink\n"); 1431 panic("rtnetlink_init: cannot initialize rtnetlink\n");
1432
1392 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); 1433 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
1393 register_netdevice_notifier(&rtnetlink_dev_notifier); 1434 register_netdevice_notifier(&rtnetlink_dev_notifier);
1394 1435