diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4edc3dac4cc..9efaf35934f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -60,7 +60,6 @@ struct rtnl_link | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | static DEFINE_MUTEX(rtnl_mutex); | 62 | static DEFINE_MUTEX(rtnl_mutex); |
63 | static struct sock *rtnl; | ||
64 | 63 | ||
65 | void rtnl_lock(void) | 64 | void 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 | ||
461 | int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) | 460 | int 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 | ||
474 | int rtnl_unicast(struct sk_buff *skb, u32 pid) | 474 | int 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 | ||
479 | int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group, | 481 | int 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 | ||
490 | void rtnl_set_sk_err(u32 group, int error) | 493 | void 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); |
1205 | errout: | 1210 | errout: |
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); |
1256 | errout: | 1261 | errout: |
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 | ||
1267 | static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 1272 | static 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 | |||
1385 | static 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 | |||
1399 | static 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 | |||
1413 | static struct pernet_operations rtnetlink_net_ops = { | ||
1414 | .init = rtnetlink_net_init, | ||
1415 | .exit = rtnetlink_net_exit, | ||
1416 | }; | ||
1417 | |||
1376 | void __init rtnetlink_init(void) | 1418 | void __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 | ||