diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/Kconfig | 8 | ||||
-rw-r--r-- | net/core/net_namespace.c | 43 |
2 files changed, 49 insertions, 2 deletions
diff --git a/net/Kconfig b/net/Kconfig index cdba08ca2efe..ab4e6da5012f 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -27,6 +27,14 @@ if NET | |||
27 | 27 | ||
28 | menu "Networking options" | 28 | menu "Networking options" |
29 | 29 | ||
30 | config NET_NS | ||
31 | bool "Network namespace support" | ||
32 | default n | ||
33 | depends on EXPERIMENTAL && !SYSFS | ||
34 | help | ||
35 | Allow user space to create what appear to be multiple instances | ||
36 | of the network stack. | ||
37 | |||
30 | source "net/packet/Kconfig" | 38 | source "net/packet/Kconfig" |
31 | source "net/unix/Kconfig" | 39 | source "net/unix/Kconfig" |
32 | source "net/xfrm/Kconfig" | 40 | source "net/xfrm/Kconfig" |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 0e6cb02d7b77..e478e353ea6b 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
5 | #include <linux/list.h> | 5 | #include <linux/list.h> |
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/sched.h> | ||
7 | #include <net/net_namespace.h> | 8 | #include <net/net_namespace.h> |
8 | 9 | ||
9 | /* | 10 | /* |
@@ -32,12 +33,10 @@ void net_unlock(void) | |||
32 | mutex_unlock(&net_list_mutex); | 33 | mutex_unlock(&net_list_mutex); |
33 | } | 34 | } |
34 | 35 | ||
35 | #if 0 | ||
36 | static struct net *net_alloc(void) | 36 | static struct net *net_alloc(void) |
37 | { | 37 | { |
38 | return kmem_cache_alloc(net_cachep, GFP_KERNEL); | 38 | return kmem_cache_alloc(net_cachep, GFP_KERNEL); |
39 | } | 39 | } |
40 | #endif | ||
41 | 40 | ||
42 | static void net_free(struct net *net) | 41 | static void net_free(struct net *net) |
43 | { | 42 | { |
@@ -128,6 +127,46 @@ out_undo: | |||
128 | goto out; | 127 | goto out; |
129 | } | 128 | } |
130 | 129 | ||
130 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) | ||
131 | { | ||
132 | struct net *new_net = NULL; | ||
133 | int err; | ||
134 | |||
135 | get_net(old_net); | ||
136 | |||
137 | if (!(flags & CLONE_NEWNET)) | ||
138 | return old_net; | ||
139 | |||
140 | #ifndef CONFIG_NET_NS | ||
141 | return ERR_PTR(-EINVAL); | ||
142 | #endif | ||
143 | |||
144 | err = -ENOMEM; | ||
145 | new_net = net_alloc(); | ||
146 | if (!new_net) | ||
147 | goto out; | ||
148 | |||
149 | mutex_lock(&net_mutex); | ||
150 | err = setup_net(new_net); | ||
151 | if (err) | ||
152 | goto out_unlock; | ||
153 | |||
154 | net_lock(); | ||
155 | list_add_tail(&new_net->list, &net_namespace_list); | ||
156 | net_unlock(); | ||
157 | |||
158 | |||
159 | out_unlock: | ||
160 | mutex_unlock(&net_mutex); | ||
161 | out: | ||
162 | put_net(old_net); | ||
163 | if (err) { | ||
164 | net_free(new_net); | ||
165 | new_net = ERR_PTR(err); | ||
166 | } | ||
167 | return new_net; | ||
168 | } | ||
169 | |||
131 | static int __init net_ns_init(void) | 170 | static int __init net_ns_init(void) |
132 | { | 171 | { |
133 | int err; | 172 | int err; |