Linux Container Development
 help / color / mirror / Atom feed
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 
> 
> 

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox