aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pppol2tp.c
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@gmail.com>2009-01-21 18:55:15 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-21 18:55:15 -0500
commit4e9fb8016a351b5b9da7fea32bcfdbc9d836e421 (patch)
treed8cce017f0327cef58f9caa9fea92f9ebd6e263f /drivers/net/pppol2tp.c
parenta6bcf1c1d38e0672db35e0d9f2504ac04ddf3ed5 (diff)
net: pppol2tp - introduce net-namespace functionality
- Each tunnel and appropriate lock are inside own namespace now. - pppox code allows to create per-namespace sockets for both PX_PROTO_OE and PX_PROTO_OL2TP protocols. Actually since now pppox_create support net-namespaces new PPPo... protocols (if they ever will be) should support net-namespace too otherwise explicit check for &init_net would be needed. Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: James Chapman <jchapman@katalix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/pppol2tp.c')
-rw-r--r--drivers/net/pppol2tp.c160
1 files changed, 117 insertions, 43 deletions
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 635dd5fbe62d..f3f9cb1f77c0 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -90,7 +90,9 @@
90#include <linux/hash.h> 90#include <linux/hash.h>
91#include <linux/sort.h> 91#include <linux/sort.h>
92#include <linux/proc_fs.h> 92#include <linux/proc_fs.h>
93#include <linux/nsproxy.h>
93#include <net/net_namespace.h> 94#include <net/net_namespace.h>
95#include <net/netns/generic.h>
94#include <net/dst.h> 96#include <net/dst.h>
95#include <net/ip.h> 97#include <net/ip.h>
96#include <net/udp.h> 98#include <net/udp.h>
@@ -204,6 +206,7 @@ struct pppol2tp_tunnel
204 struct sock *sock; /* Parent socket */ 206 struct sock *sock; /* Parent socket */
205 struct list_head list; /* Keep a list of all open 207 struct list_head list; /* Keep a list of all open
206 * prepared sockets */ 208 * prepared sockets */
209 struct net *pppol2tp_net; /* the net we belong to */
207 210
208 atomic_t ref_count; 211 atomic_t ref_count;
209}; 212};
@@ -227,8 +230,20 @@ static atomic_t pppol2tp_tunnel_count;
227static atomic_t pppol2tp_session_count; 230static atomic_t pppol2tp_session_count;
228static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL }; 231static struct ppp_channel_ops pppol2tp_chan_ops = { pppol2tp_xmit , NULL };
229static struct proto_ops pppol2tp_ops; 232static struct proto_ops pppol2tp_ops;
230static LIST_HEAD(pppol2tp_tunnel_list); 233
231static DEFINE_RWLOCK(pppol2tp_tunnel_list_lock); 234/* per-net private data for this module */
235static unsigned int pppol2tp_net_id;
236struct pppol2tp_net {
237 struct list_head pppol2tp_tunnel_list;
238 rwlock_t pppol2tp_tunnel_list_lock;
239};
240
241static inline struct pppol2tp_net *pppol2tp_pernet(struct net *net)
242{
243 BUG_ON(!net);
244
245 return net_generic(net, pppol2tp_net_id);
246}
232 247
233/* Helpers to obtain tunnel/session contexts from sockets. 248/* Helpers to obtain tunnel/session contexts from sockets.
234 */ 249 */
@@ -321,18 +336,19 @@ pppol2tp_session_find(struct pppol2tp_tunnel *tunnel, u16 session_id)
321 336
322/* Lookup a tunnel by id 337/* Lookup a tunnel by id
323 */ 338 */
324static struct pppol2tp_tunnel *pppol2tp_tunnel_find(u16 tunnel_id) 339static struct pppol2tp_tunnel *pppol2tp_tunnel_find(struct net *net, u16 tunnel_id)
325{ 340{
326 struct pppol2tp_tunnel *tunnel = NULL; 341 struct pppol2tp_tunnel *tunnel;
342 struct pppol2tp_net *pn = pppol2tp_pernet(net);
327 343
328 read_lock_bh(&pppol2tp_tunnel_list_lock); 344 read_lock_bh(&pn->pppol2tp_tunnel_list_lock);
329 list_for_each_entry(tunnel, &pppol2tp_tunnel_list, list) { 345 list_for_each_entry(tunnel, &pn->pppol2tp_tunnel_list, list) {
330 if (tunnel->stats.tunnel_id == tunnel_id) { 346 if (tunnel->stats.tunnel_id == tunnel_id) {
331 read_unlock_bh(&pppol2tp_tunnel_list_lock); 347 read_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
332 return tunnel; 348 return tunnel;
333 } 349 }
334 } 350 }
335 read_unlock_bh(&pppol2tp_tunnel_list_lock); 351 read_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
336 352
337 return NULL; 353 return NULL;
338} 354}
@@ -1287,10 +1303,12 @@ again:
1287 */ 1303 */
1288static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel) 1304static void pppol2tp_tunnel_free(struct pppol2tp_tunnel *tunnel)
1289{ 1305{
1306 struct pppol2tp_net *pn = pppol2tp_pernet(tunnel->pppol2tp_net);
1307
1290 /* Remove from socket list */ 1308 /* Remove from socket list */
1291 write_lock_bh(&pppol2tp_tunnel_list_lock); 1309 write_lock_bh(&pn->pppol2tp_tunnel_list_lock);
1292 list_del_init(&tunnel->list); 1310 list_del_init(&tunnel->list);
1293 write_unlock_bh(&pppol2tp_tunnel_list_lock); 1311 write_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
1294 1312
1295 atomic_dec(&pppol2tp_tunnel_count); 1313 atomic_dec(&pppol2tp_tunnel_count);
1296 kfree(tunnel); 1314 kfree(tunnel);
@@ -1444,13 +1462,14 @@ error:
1444/* Internal function to prepare a tunnel (UDP) socket to have PPPoX 1462/* Internal function to prepare a tunnel (UDP) socket to have PPPoX
1445 * sockets attached to it. 1463 * sockets attached to it.
1446 */ 1464 */
1447static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id, 1465static struct sock *pppol2tp_prepare_tunnel_socket(struct net *net,
1448 int *error) 1466 int fd, u16 tunnel_id, int *error)
1449{ 1467{
1450 int err; 1468 int err;
1451 struct socket *sock = NULL; 1469 struct socket *sock = NULL;
1452 struct sock *sk; 1470 struct sock *sk;
1453 struct pppol2tp_tunnel *tunnel; 1471 struct pppol2tp_tunnel *tunnel;
1472 struct pppol2tp_net *pn;
1454 struct sock *ret = NULL; 1473 struct sock *ret = NULL;
1455 1474
1456 /* Get the tunnel UDP socket from the fd, which was opened by 1475 /* Get the tunnel UDP socket from the fd, which was opened by
@@ -1524,11 +1543,15 @@ static struct sock *pppol2tp_prepare_tunnel_socket(int fd, u16 tunnel_id,
1524 /* Misc init */ 1543 /* Misc init */
1525 rwlock_init(&tunnel->hlist_lock); 1544 rwlock_init(&tunnel->hlist_lock);
1526 1545
1546 /* The net we belong to */
1547 tunnel->pppol2tp_net = net;
1548 pn = pppol2tp_pernet(net);
1549
1527 /* Add tunnel to our list */ 1550 /* Add tunnel to our list */
1528 INIT_LIST_HEAD(&tunnel->list); 1551 INIT_LIST_HEAD(&tunnel->list);
1529 write_lock_bh(&pppol2tp_tunnel_list_lock); 1552 write_lock_bh(&pn->pppol2tp_tunnel_list_lock);
1530 list_add(&tunnel->list, &pppol2tp_tunnel_list); 1553 list_add(&tunnel->list, &pn->pppol2tp_tunnel_list);
1531 write_unlock_bh(&pppol2tp_tunnel_list_lock); 1554 write_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
1532 atomic_inc(&pppol2tp_tunnel_count); 1555 atomic_inc(&pppol2tp_tunnel_count);
1533 1556
1534 /* Bump the reference count. The tunnel context is deleted 1557 /* Bump the reference count. The tunnel context is deleted
@@ -1629,7 +1652,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
1629 * tunnel id. 1652 * tunnel id.
1630 */ 1653 */
1631 if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) { 1654 if ((sp->pppol2tp.s_session == 0) && (sp->pppol2tp.d_session == 0)) {
1632 tunnel_sock = pppol2tp_prepare_tunnel_socket(sp->pppol2tp.fd, 1655 tunnel_sock = pppol2tp_prepare_tunnel_socket(sock_net(sk),
1656 sp->pppol2tp.fd,
1633 sp->pppol2tp.s_tunnel, 1657 sp->pppol2tp.s_tunnel,
1634 &error); 1658 &error);
1635 if (tunnel_sock == NULL) 1659 if (tunnel_sock == NULL)
@@ -1637,7 +1661,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
1637 1661
1638 tunnel = tunnel_sock->sk_user_data; 1662 tunnel = tunnel_sock->sk_user_data;
1639 } else { 1663 } else {
1640 tunnel = pppol2tp_tunnel_find(sp->pppol2tp.s_tunnel); 1664 tunnel = pppol2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel);
1641 1665
1642 /* Error if we can't find the tunnel */ 1666 /* Error if we can't find the tunnel */
1643 error = -ENOENT; 1667 error = -ENOENT;
@@ -2347,8 +2371,9 @@ end:
2347#include <linux/seq_file.h> 2371#include <linux/seq_file.h>
2348 2372
2349struct pppol2tp_seq_data { 2373struct pppol2tp_seq_data {
2350 struct pppol2tp_tunnel *tunnel; /* current tunnel */ 2374 struct net *seq_net; /* net of inode */
2351 struct pppol2tp_session *session; /* NULL means get first session in tunnel */ 2375 struct pppol2tp_tunnel *tunnel; /* current tunnel */
2376 struct pppol2tp_session *session; /* NULL means get first session in tunnel */
2352}; 2377};
2353 2378
2354static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr) 2379static struct pppol2tp_session *next_session(struct pppol2tp_tunnel *tunnel, struct pppol2tp_session *curr)
@@ -2384,17 +2409,18 @@ out:
2384 return session; 2409 return session;
2385} 2410}
2386 2411
2387static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_tunnel *curr) 2412static struct pppol2tp_tunnel *next_tunnel(struct pppol2tp_net *pn,
2413 struct pppol2tp_tunnel *curr)
2388{ 2414{
2389 struct pppol2tp_tunnel *tunnel = NULL; 2415 struct pppol2tp_tunnel *tunnel = NULL;
2390 2416
2391 read_lock_bh(&pppol2tp_tunnel_list_lock); 2417 read_lock_bh(&pn->pppol2tp_tunnel_list_lock);
2392 if (list_is_last(&curr->list, &pppol2tp_tunnel_list)) { 2418 if (list_is_last(&curr->list, &pn->pppol2tp_tunnel_list)) {
2393 goto out; 2419 goto out;
2394 } 2420 }
2395 tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list); 2421 tunnel = list_entry(curr->list.next, struct pppol2tp_tunnel, list);
2396out: 2422out:
2397 read_unlock_bh(&pppol2tp_tunnel_list_lock); 2423 read_unlock_bh(&pn->pppol2tp_tunnel_list_lock);
2398 2424
2399 return tunnel; 2425 return tunnel;
2400} 2426}
@@ -2402,6 +2428,7 @@ out:
2402static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs) 2428static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs)
2403{ 2429{
2404 struct pppol2tp_seq_data *pd = SEQ_START_TOKEN; 2430 struct pppol2tp_seq_data *pd = SEQ_START_TOKEN;
2431 struct pppol2tp_net *pn;
2405 loff_t pos = *offs; 2432 loff_t pos = *offs;
2406 2433
2407 if (!pos) 2434 if (!pos)
@@ -2409,14 +2436,15 @@ static void *pppol2tp_seq_start(struct seq_file *m, loff_t *offs)
2409 2436
2410 BUG_ON(m->private == NULL); 2437 BUG_ON(m->private == NULL);
2411 pd = m->private; 2438 pd = m->private;
2439 pn = pppol2tp_pernet(pd->seq_net);
2412 2440
2413 if (pd->tunnel == NULL) { 2441 if (pd->tunnel == NULL) {
2414 if (!list_empty(&pppol2tp_tunnel_list)) 2442 if (!list_empty(&pn->pppol2tp_tunnel_list))
2415 pd->tunnel = list_entry(pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list); 2443 pd->tunnel = list_entry(pn->pppol2tp_tunnel_list.next, struct pppol2tp_tunnel, list);
2416 } else { 2444 } else {
2417 pd->session = next_session(pd->tunnel, pd->session); 2445 pd->session = next_session(pd->tunnel, pd->session);
2418 if (pd->session == NULL) { 2446 if (pd->session == NULL) {
2419 pd->tunnel = next_tunnel(pd->tunnel); 2447 pd->tunnel = next_tunnel(pn, pd->tunnel);
2420 } 2448 }
2421 } 2449 }
2422 2450
@@ -2532,6 +2560,7 @@ static int pppol2tp_proc_open(struct inode *inode, struct file *file)
2532{ 2560{
2533 struct seq_file *m; 2561 struct seq_file *m;
2534 struct pppol2tp_seq_data *pd; 2562 struct pppol2tp_seq_data *pd;
2563 struct net *net;
2535 int ret = 0; 2564 int ret = 0;
2536 2565
2537 ret = seq_open(file, &pppol2tp_seq_ops); 2566 ret = seq_open(file, &pppol2tp_seq_ops);
@@ -2542,12 +2571,15 @@ static int pppol2tp_proc_open(struct inode *inode, struct file *file)
2542 2571
2543 /* Allocate and fill our proc_data for access later */ 2572 /* Allocate and fill our proc_data for access later */
2544 ret = -ENOMEM; 2573 ret = -ENOMEM;
2545 m->private = kzalloc(sizeof(struct pppol2tp_seq_data), GFP_KERNEL); 2574 m->private = kzalloc(sizeof(*pd), GFP_KERNEL);
2546 if (m->private == NULL) 2575 if (m->private == NULL)
2547 goto out; 2576 goto out;
2548 2577
2549 pd = m->private; 2578 pd = m->private;
2550 ret = 0; 2579 net = maybe_get_net(PDE_NET(PDE(inode)));
2580 BUG_ON(!net);
2581 pd->seq_net = net;
2582 return 0;
2551 2583
2552out: 2584out:
2553 return ret; 2585 return ret;
@@ -2558,6 +2590,9 @@ out:
2558static int pppol2tp_proc_release(struct inode *inode, struct file *file) 2590static int pppol2tp_proc_release(struct inode *inode, struct file *file)
2559{ 2591{
2560 struct seq_file *m = (struct seq_file *)file->private_data; 2592 struct seq_file *m = (struct seq_file *)file->private_data;
2593 struct pppol2tp_seq_data *pd = m->private;
2594
2595 put_net(pd->seq_net);
2561 2596
2562 kfree(m->private); 2597 kfree(m->private);
2563 m->private = NULL; 2598 m->private = NULL;
@@ -2573,8 +2608,6 @@ static const struct file_operations pppol2tp_proc_fops = {
2573 .release = pppol2tp_proc_release, 2608 .release = pppol2tp_proc_release,
2574}; 2609};
2575 2610
2576static struct proc_dir_entry *pppol2tp_proc;
2577
2578#endif /* CONFIG_PROC_FS */ 2611#endif /* CONFIG_PROC_FS */
2579 2612
2580/***************************************************************************** 2613/*****************************************************************************
@@ -2606,6 +2639,57 @@ static struct pppox_proto pppol2tp_proto = {
2606 .ioctl = pppol2tp_ioctl 2639 .ioctl = pppol2tp_ioctl
2607}; 2640};
2608 2641
2642static __net_init int pppol2tp_init_net(struct net *net)
2643{
2644 struct pppol2tp_net *pn;
2645 struct proc_dir_entry *pde;
2646 int err;
2647
2648 pn = kzalloc(sizeof(*pn), GFP_KERNEL);
2649 if (!pn)
2650 return -ENOMEM;
2651
2652 INIT_LIST_HEAD(&pn->pppol2tp_tunnel_list);
2653 rwlock_init(&pn->pppol2tp_tunnel_list_lock);
2654
2655 err = net_assign_generic(net, pppol2tp_net_id, pn);
2656 if (err)
2657 goto out;
2658
2659 pde = proc_net_fops_create(net, "pppol2tp", S_IRUGO, &pppol2tp_proc_fops);
2660#ifdef CONFIG_PROC_FS
2661 if (!pde) {
2662 err = -ENOMEM;
2663 goto out;
2664 }
2665#endif
2666
2667 return 0;
2668
2669out:
2670 kfree(pn);
2671 return err;
2672}
2673
2674static __net_exit void pppol2tp_exit_net(struct net *net)
2675{
2676 struct pppoe_net *pn;
2677
2678 proc_net_remove(net, "pppol2tp");
2679 pn = net_generic(net, pppol2tp_net_id);
2680 /*
2681 * if someone has cached our net then
2682 * further net_generic call will return NULL
2683 */
2684 net_assign_generic(net, pppol2tp_net_id, NULL);
2685 kfree(pn);
2686}
2687
2688static __net_initdata struct pernet_operations pppol2tp_net_ops = {
2689 .init = pppol2tp_init_net,
2690 .exit = pppol2tp_exit_net,
2691};
2692
2609static int __init pppol2tp_init(void) 2693static int __init pppol2tp_init(void)
2610{ 2694{
2611 int err; 2695 int err;
@@ -2617,23 +2701,17 @@ static int __init pppol2tp_init(void)
2617 if (err) 2701 if (err)
2618 goto out_unregister_pppol2tp_proto; 2702 goto out_unregister_pppol2tp_proto;
2619 2703
2620#ifdef CONFIG_PROC_FS 2704 err = register_pernet_gen_device(&pppol2tp_net_id, &pppol2tp_net_ops);
2621 pppol2tp_proc = proc_net_fops_create(&init_net, "pppol2tp", 0, 2705 if (err)
2622 &pppol2tp_proc_fops);
2623 if (!pppol2tp_proc) {
2624 err = -ENOMEM;
2625 goto out_unregister_pppox_proto; 2706 goto out_unregister_pppox_proto;
2626 } 2707
2627#endif /* CONFIG_PROC_FS */
2628 printk(KERN_INFO "PPPoL2TP kernel driver, %s\n", 2708 printk(KERN_INFO "PPPoL2TP kernel driver, %s\n",
2629 PPPOL2TP_DRV_VERSION); 2709 PPPOL2TP_DRV_VERSION);
2630 2710
2631out: 2711out:
2632 return err; 2712 return err;
2633#ifdef CONFIG_PROC_FS
2634out_unregister_pppox_proto: 2713out_unregister_pppox_proto:
2635 unregister_pppox_proto(PX_PROTO_OL2TP); 2714 unregister_pppox_proto(PX_PROTO_OL2TP);
2636#endif
2637out_unregister_pppol2tp_proto: 2715out_unregister_pppol2tp_proto:
2638 proto_unregister(&pppol2tp_sk_proto); 2716 proto_unregister(&pppol2tp_sk_proto);
2639 goto out; 2717 goto out;
@@ -2642,10 +2720,6 @@ out_unregister_pppol2tp_proto:
2642static void __exit pppol2tp_exit(void) 2720static void __exit pppol2tp_exit(void)
2643{ 2721{
2644 unregister_pppox_proto(PX_PROTO_OL2TP); 2722 unregister_pppox_proto(PX_PROTO_OL2TP);
2645
2646#ifdef CONFIG_PROC_FS
2647 remove_proc_entry("pppol2tp", init_net.proc_net);
2648#endif
2649 proto_unregister(&pppol2tp_sk_proto); 2723 proto_unregister(&pppol2tp_sk_proto);
2650} 2724}
2651 2725