From: Daniel Lezcano <dlezcano-juSfH4iHXoxBDgjK7y7TUQ@public.gmane.org>
To: Benjamin Thery <benjamin.thery-6ktuUTfB/bM@public.gmane.org>
Cc: Linux Containers <containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org>
Subject: Re: [RFC][patch 1/3] network container subsystem
Date: Wed, 05 Sep 2007 14:43:32 +0200 [thread overview]
Message-ID: <46DEA474.7070603@meiosys.com> (raw)
In-Reply-To: <46DE97F5.3090609-6ktuUTfB/bM@public.gmane.org>
Benjamin Thery wrote:
> dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org wrote:
>> From: Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
>>
>> 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;
>
I didn't think about this format, I will change it.
>>
>> This patch by itself does nothing more than adding/removing elements
>> from a list.
>>
>> Signed-off-by: Daniel Lezcano <dlezcano-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
>>
>> ---
>> 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?)
Perhaps struct sockaddr is more adequate. We can just use a list for
storing ipv4, ipv6, ...
>> +
>> +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" :)
... yes :D
>
>
>> + 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));
Thanks.
>
>
>> + 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 Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
>> https://lists.linux-foundation.org/mailman/listinfo/containers
>
>
next prev parent reply other threads:[~2007-09-05 12:43 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-04 17:00 [RFC][patch 0/3] Network container subsystem - bind filtering dlezcano-NmTC/0ZBporQT0dZR+AlfA
2007-09-04 17:00 ` [RFC][patch 1/3] network container subsystem dlezcano-NmTC/0ZBporQT0dZR+AlfA
[not found] ` <20070904171525.771956554-lUQnSZrVijcklpeYT4thRqpRWpusSO0yQ3R/GR7Q8HurIzol8Bc5pA@public.gmane.org>
2007-09-05 11:50 ` Benjamin Thery
[not found] ` <46DE97F5.3090609-6ktuUTfB/bM@public.gmane.org>
2007-09-05 12:43 ` Daniel Lezcano [this message]
2007-09-05 15:49 ` Serge E. Hallyn
2007-09-04 17:00 ` [RFC][patch 2/3] network security hooks dlezcano-NmTC/0ZBporQT0dZR+AlfA
[not found] ` <20070904171527.201921132-lUQnSZrVijcklpeYT4thRqpRWpusSO0yQ3R/GR7Q8HurIzol8Bc5pA@public.gmane.org>
2007-09-05 16:04 ` Serge E. Hallyn
2007-09-04 17:00 ` [RFC][patch 3/3] activate filtering for the bind dlezcano-NmTC/0ZBporQT0dZR+AlfA
[not found] ` <20070904171528.704108193-lUQnSZrVijcklpeYT4thRqpRWpusSO0yQ3R/GR7Q8HurIzol8Bc5pA@public.gmane.org>
2007-09-05 16:18 ` Serge E. Hallyn
[not found] ` <20070905161848.GN1403-6s5zFf/epYLPQpwDFJZrxKsjOiXwFzmk@public.gmane.org>
2007-09-05 16:38 ` Daniel Lezcano
[not found] ` <46DEDBA1.9010706-juSfH4iHXoxBDgjK7y7TUQ@public.gmane.org>
2007-09-10 13:23 ` Serge E. Hallyn
[not found] ` <20070910132330.GB9565-6s5zFf/epYLPQpwDFJZrxKsjOiXwFzmk@public.gmane.org>
2007-09-10 13:52 ` Daniel Lezcano
[not found] ` <46E54C11.1050403-NmTC/0ZBporQT0dZR+AlfA@public.gmane.org>
2007-09-10 15:46 ` Serge E. Hallyn
[not found] ` <20070910154630.GA3905-6s5zFf/epYLPQpwDFJZrxKsjOiXwFzmk@public.gmane.org>
2007-09-10 17:49 ` [Devel] " Paul Menage
[not found] ` <6599ad830709101049g5ea45749k66e362326264b4b0-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2007-09-10 18:11 ` Serge E. Hallyn
[not found] ` <20070910181131.GB31638-6s5zFf/epYLPQpwDFJZrxKsjOiXwFzmk@public.gmane.org>
2007-09-10 18:15 ` Paul Menage
[not found] ` <20070904170022.964253374-lUQnSZrVijcklpeYT4thRqpRWpusSO0yQ3R/GR7Q8HurIzol8Bc5pA@public.gmane.org>
2007-09-05 14:05 ` [RFC][patch 0/3] Network container subsystem - bind filtering Benjamin Thery
2007-09-05 15:37 ` Serge E. Hallyn
[not found] ` <20070905153741.GK1403-6s5zFf/epYLPQpwDFJZrxKsjOiXwFzmk@public.gmane.org>
2007-09-05 15:41 ` Daniel Lezcano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46DEA474.7070603@meiosys.com \
--to=dlezcano-jusfh4ihxoxbdgjk7y7tuq@public.gmane.org \
--cc=benjamin.thery-6ktuUTfB/bM@public.gmane.org \
--cc=containers-qjLDD68F18O7TbgM5vRIOg@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.