[EMAIL PROTECTED] wrote:
From: Daniel Lezcano <[EMAIL PROTECTED]>
This patch creates the network container subsystem.
It consists for the moment on a single file "network.ipv4".
The interface is pretty simple:
To add an IP address to the container:
echo add AB12FFFF > network.ipv4
To remove this IP address:
--------------------------
echo del AB12FFFF > network.ipv4
To list the addresses:
----------------------
cat network.ipv4
The parameter is an IPV4 address in the hexa format. The parsing of a
dotted-decimal
parameter is totally painful. If this format hurts someone, I can change it to
a dotted
format at the risk of having something buggy.
I think passing ipv4 addresses in hexa form is painful :)
Why not use something like this:
__be32 addr;
unsigned int a, b, c, d;
if (sscanf (buffer, "%u.%u.%u.%u", &a, &b, &c, &d) == 4) {
if (a < 256 && b < 256 && c < 256 && d < 256) {
addr = htonl (a<<24 | b<<16 | c<<8 | d);
return 0;
}
}
return -EINVAL;
This patch by itself does nothing more than adding/removing elements from a
list.
Signed-off-by: Daniel Lezcano <[EMAIL PROTECTED]>
---
include/linux/container_subsys.h | 4
init/Kconfig | 8 +
kernel/Makefile | 1
kernel/container_network.c | 285 +++++++++++++++++++++++++++++++++++++++
4 files changed, 298 insertions(+)
Index: 2.6-mm/include/linux/container_subsys.h
===================================================================
--- 2.6-mm.orig/include/linux/container_subsys.h
+++ 2.6-mm/include/linux/container_subsys.h
@@ -30,3 +30,7 @@
#endif
/* */
+
+#ifdef CONFIG_CONTAINER_NETWORK
+SUBSYS(network)
+#endif
Index: 2.6-mm/init/Kconfig
===================================================================
--- 2.6-mm.orig/init/Kconfig
+++ 2.6-mm/init/Kconfig
@@ -326,6 +326,14 @@
Provides a simple Resource Controller for monitoring the
total CPU consumed by the tasks in a container
+config CONTAINER_NETWORK
+ bool "Network container subsystem"
+ depends on CONTAINERS && SECURITY_NETWORK
+ help
+ Provides a network controller to isolate network traffic
+
+ Say N if unsure
+
config CPUSETS
bool "Cpuset support"
depends on SMP && CONTAINERS
Index: 2.6-mm/kernel/Makefile
===================================================================
--- 2.6-mm.orig/kernel/Makefile
+++ 2.6-mm/kernel/Makefile
@@ -43,6 +43,7 @@
obj-$(CONFIG_CPUSETS) += cpuset.o
obj-$(CONFIG_CONTAINER_CPUACCT) += cpu_acct.o
obj-$(CONFIG_CONTAINER_NS) += ns_container.o
+obj-$(CONFIG_CONTAINER_NETWORK) += container_network.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
Index: 2.6-mm/kernel/container_network.c
===================================================================
--- /dev/null
+++ 2.6-mm/kernel/container_network.c
@@ -0,0 +1,285 @@
+/*
+ * container_network.c - container network subsystem
+ *
+ * Copyright 2006, 2007 IBM Corp
+ */
+
+#include <linux/module.h>
+#include <linux/container.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+struct network {
+ struct container_subsys_state css;
+ struct list_head ipv4_list; /* store the IPV4 addresses */
+ rwlock_t ipv4_list_lock;
+};
+
+struct ipv4_list {
+ __be32 address;
+ struct list_head list;
+};
Can we use "struct in_addr" instead of __be32?
(may be you don't want to include in.h?)
+
+static struct network top_network = {
+ .ipv4_list = LIST_HEAD_INIT(top_network.ipv4_list),
+ .ipv4_list_lock = __RW_LOCK_UNLOCKED(top_network.ipv4_list_lock),
+};
+
+struct container_subsys network_subsys;
+
+enum container_filetype {
+ FILE_IPV4,
+};
+
+static inline struct network *container_network(struct container *container)
+{
+ return container_of(
+ container_subsys_state(container, network_subsys_id),
+ struct network, css);
+}
+
+static struct container_subsys_state *network_create(struct container_subsys
*ss,
+ struct container
*container)
+{
+ struct network *network;
+
+ /* Don't let anybody do that */
+ if (!capable(CAP_NET_ADMIN))
+ return ERR_PTR(-EPERM);
+
+ /* The current container is the initial container */
+ if (!container->parent)
+ return &top_network.css;
+
+ network = kzalloc(sizeof(*network), GFP_KERNEL);
+ if (!network)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&network->ipv4_list);
+ network->ipv4_list_lock = __RW_LOCK_UNLOCKED(network->ipv4_list_lock);
+
+ return &network->css;
+}
+
+static void network_destroy(struct container_subsys *ss,
+ struct container *container)
+{
+ struct network *network;
+ struct ipv4_list *entry, *next;
+ struct list_head *l;
+ rwlock_t *lock;
+
+ network = container_network(container);
+ l = &network->ipv4_list;
+ lock = &network->ipv4_list_lock;
+
+ /* flush the ipv4 list */
+ write_lock(lock);
+ list_for_each_entry_safe(entry, next, l, list) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+ write_unlock(lock);
+
+ kfree(network);
+}
+
+static int network_add_ipv4_address(struct container *container, __be32
address)
+{
+ struct ipv4_list *entry;
+ struct network *network;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+ entry->address = address;
+
+ network = container_network(container);
+ write_lock(&network->ipv4_list_lock);
+ list_add(&entry->list, &network->ipv4_list);
+ write_unlock(&network->ipv4_list_lock);
+
+ return 0;
+}
+
+static int network_del_ipv4_address(struct container *container, __be32
address)
+{
+ struct ipv4_list *entry;
+ struct network *network;
+ int ret = 0;
+
+ network = container_network(container);
+ write_lock(&network->ipv4_list_lock);
+ list_for_each_entry(entry, &network->ipv4_list, list) {
+ if (entry->address != address)
+ continue;
+
+ list_del(&entry->list);
+ goto out_free;
+ }
+ ret = -EINVAL;
+out:
+ write_unlock(&network->ipv4_list_lock);
+ return ret;
+
+out_free:
+ kfree(entry);
+ goto out;
+}
+
+static int network_parse_ipv4_address(struct container *container, char
*buffer)
+{
+ int len = strlen(buffer);
+ char *addr;
+ __be32 address;
+
+ /* remove trailing left space */
May be "leading space" is better than "trailing left space" :)
+ while(isspace(*buffer))
+ buffer++;
+
+ /* remove trailing right space */
+ while(isspace(buffer[len - 1]))
+ buffer[(len--) - 1] = 0;
+
+ len = strlen(buffer);
+ addr = memchr(buffer, ' ', len);
+ if (!addr)
+ return -EINVAL;
+ *addr++ = 0;
+
+ /* remove trailing left space again */
+ while(isspace(*addr))
+ addr++;
+
+ /* Shall I check if the address is setup on the host ? */
+ sscanf(addr, "%X", &address);
+
+ if (!strcmp(buffer, "add"))
+ return network_add_ipv4_address(container, address);
+ else if (!strcmp(buffer, "del"))
+ return network_del_ipv4_address(container, address);
+
+ return -EINVAL;
+}
+
+static int network_fill_ipv4_address(struct container *container, char *buffer)
+{
+ struct network *network;
+ struct ipv4_list *entry;
+ char *s = buffer;
+ network = container_network(container);
+
+ read_lock(&network->ipv4_list_lock);
+ list_for_each_entry(entry, &network->ipv4_list, list)
+ s += sprintf(s, "%X\n", entry->address);
Pretty print:
s+= sprintf(s, NIPQUAD_FMT "\n", NIPQUAD(entry->address));
+ read_unlock(&network->ipv4_list_lock);
+
+ return strlen(buffer);
+}
+
+static ssize_t network_write(struct container *container,
+ struct cftype *cft,
+ struct file *file,
+ const char __user *userbuf,
+ size_t nbytes, loff_t *unused_ppos)
+{
+ enum container_filetype type = cft->private;
+ char *buffer;
+ int retval = 0;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (nbytes >= PATH_MAX)
+ return -E2BIG;
+
+ buffer = kmalloc(nbytes + 1, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (copy_from_user(buffer, userbuf, nbytes)) {
+ retval = -EFAULT;
+ goto out_free;
+ }
+ buffer[nbytes] = 0;
+
+ container_lock();
+ switch(type) {
+
+ case FILE_IPV4:
+ retval = network_parse_ipv4_address(container, buffer);
+ break;
+
+ default:
+ retval = -EINVAL;
+ break;
+ };
+ container_unlock();
+
+out_free:
+ if (!retval)
+ retval = nbytes;
+
+ kfree(buffer);
+ return retval;
+}
+
+static ssize_t network_read(struct container *container,
+ struct cftype *cft,
+ struct file *file,
+ char __user *userbuf,
+ size_t nbytes, loff_t *ppos)
+{
+ enum container_filetype type = cft->private;
+ char *page;
+ int retval;
+
+ page = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!page)
+ return -ENOMEM;
+
+ container_lock();
+ switch(type) {
+ case FILE_IPV4:
+ retval = network_fill_ipv4_address(container, page);
+ break;
+
+ default:
+ retval = -EINVAL;
+ };
+ container_unlock();
+
+ retval = simple_read_from_buffer(userbuf, nbytes, ppos, page, retval);
+
+ free_page((unsigned long)page);
+ return retval;
+}
+
+static struct cftype files[] = {
+ {
+ .name = "ipv4",
+ .read = network_read,
+ .write = network_write,
+ .private = FILE_IPV4,
+ },
+};
+
+static int network_populate(struct container_subsys *ss, struct container
*cont)
+{
+ return container_add_files(cont, ss, files, ARRAY_SIZE(files));
+}
+
+struct container_subsys network_subsys = {
+ .name = "network",
+ .create = network_create,
+ .destroy = network_destroy,
+ .populate = network_populate,
+ .subsys_id = network_subsys_id,
+ .can_attach = NULL,
+ .attach = NULL,
+ .fork = NULL,
+ .exit = NULL,
+};
-- _______________________________________________ Containers mailing list [EMAIL PROTECTED] https://lists.linux-foundation.org/mailman/listinfo/containers
--
B e n j a m i n T h e r y - BULL/DT/Open Software R&D
http://www.bull.com
_______________________________________________
Containers mailing list
[EMAIL PROTECTED]
https://lists.linux-foundation.org/mailman/listinfo/containers
_______________________________________________
Devel mailing list
Devel@openvz.org
https://openvz.org/mailman/listinfo/devel