]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/conf.c
lxc: avoid memory corruption on ppc and s390 V4
[mirror_lxc.git] / src / lxc / conf.c
index 2517fb3d6f3b9629dc34d89a6d19d04c2cf67430..b56e880e594f03144281443f22cdbfde295fc886 100644 (file)
 #include "network.h"
 #include "error.h"
 #include "parse.h"
+#include "config.h"
 
-#include <lxc/lxc.h>
+#include <lxc/conf.h>
 #include <lxc/log.h>
+#include <lxc/lxc.h>   /* for lxc_cgroup_set() */
 
 lxc_log_define(lxc_conf, lxc);
 
@@ -63,14 +65,7 @@ lxc_log_define(lxc_conf, lxc);
 #define MS_REC 16384
 #endif
 
-typedef int (*instanciate_cb)(const char *directory,
-                             const char *file, pid_t pid);
-
-struct netdev_conf {
-       const char *type;
-       instanciate_cb cb;
-       int count;
-};
+typedef int (*instanciate_cb)(struct lxc_netdev *);
 
 struct mount_opt {
        char *name;
@@ -78,17 +73,18 @@ struct mount_opt {
        int flag;
 };
 
-static int instanciate_veth(const char *, const char *, pid_t);
-static int instanciate_macvlan(const char *, const char *, pid_t);
-static int instanciate_phys(const char *, const char *, pid_t);
-static int instanciate_empty(const char *, const char *, pid_t);
-static int unconfigure_cgroup(const char *name);
-
-static struct netdev_conf netdev_conf[MAXCONFTYPE + 1] = {
-       [VETH]    = { "veth",    instanciate_veth,    0  },
-       [MACVLAN] = { "macvlan", instanciate_macvlan, 0, },
-       [PHYS]    = { "phys",    instanciate_phys,    0, },
-       [EMPTY]   = { "empty",   instanciate_empty,   0, },
+static int instanciate_veth(struct lxc_netdev *);
+static int instanciate_macvlan(struct lxc_netdev *);
+static int instanciate_vlan(struct lxc_netdev *);
+static int instanciate_phys(struct lxc_netdev *);
+static int instanciate_empty(struct lxc_netdev *);
+
+static  instanciate_cb netdev_conf[MAXCONFTYPE + 1] = {
+       [VETH]    = instanciate_veth,
+       [MACVLAN] = instanciate_macvlan,
+       [VLAN]    = instanciate_vlan,
+       [PHYS]    = instanciate_phys,
+       [EMPTY]   = instanciate_empty,
 };
 
 static struct mount_opt mount_opt[] = {
@@ -115,328 +111,6 @@ static struct mount_opt mount_opt[] = {
        { NULL,         0, 0              },
 };
 
-static int write_info(const char *path, const char *file, const char *info)
-{
-       int fd, err = -1;
-       char f[MAXPATHLEN];
-
-       snprintf(f, MAXPATHLEN, "%s/%s", path, file);
-       fd = creat(f, 0755);
-       if (fd < 0)
-               goto out;
-
-       if (write(fd, info, strlen(info)) < 0 ||
-           write(fd, "\n", strlen("\n") + 1) < 0)
-               goto out_write;
-       err = 0;
-out:
-       close(fd);
-       return err;
-
-out_write:
-       unlink(f);
-       goto out;
-}
-
-static int read_info(const char *path, const char *file, char *info, size_t len)
-{
-       int fd, ret = -1;
-       char f[MAXPATHLEN], *token;
-
-       snprintf(f, MAXPATHLEN, "%s/%s", path, file);
-       fd = open(f, O_RDONLY);
-       if (fd < 0) {
-               if (errno == ENOENT)
-                       ret = 1;
-               goto out;
-       }
-
-       ret = read(fd, info, len);
-       if (ret < 0)
-               goto out;
-
-       token = strstr(info, "\n");
-       if (token)
-               *token = '\0';
-       ret = 0;
-out:
-       close(fd);
-       return ret;
-}
-
-static int delete_info(const char *path, const char *file)
-{
-       char info[MAXPATHLEN];
-       int ret;
-
-       snprintf(info, MAXPATHLEN, "%s/%s", path, file);
-       ret = unlink(info);
-
-       return ret;
-}
-
-static int configure_ip4addr(int fd, struct lxc_inetdev *in)
-{
-       char addr[INET6_ADDRSTRLEN];
-       char bcast[INET_ADDRSTRLEN];
-       char line[MAXLINELEN];
-       int err = -1;
-
-       if (!inet_ntop(AF_INET, &in->addr, addr, sizeof(addr))) {
-               SYSERROR("failed to convert ipv4 address");
-               goto err;
-       }
-
-       if (!inet_ntop(AF_INET, &in->bcast, bcast, sizeof(bcast))) {
-               SYSERROR("failed to convert ipv4 broadcast");
-               goto err;
-       }
-
-       if (in->prefix)
-               snprintf(line, MAXLINELEN, "%s/%d %s\n", addr, in->prefix, bcast);
-       else
-               snprintf(line, MAXLINELEN, "%s %s\n", addr, bcast);
-
-       if (write(fd, line, strlen(line)) < 0) {
-               SYSERROR("failed to write address info");
-               goto err;
-       }
-
-       err = 0;
-err:
-       return err;
-}
-
-static int configure_ip6addr(int fd, struct lxc_inet6dev *in6)
-{
-       char addr[INET6_ADDRSTRLEN];
-       char line[MAXLINELEN];
-       int err = -1;
-
-       if (!inet_ntop(AF_INET6, &in6->addr, addr, sizeof(addr))) {
-               SYSERROR("failed to convert ipv4 address");
-               goto err;
-       }
-
-       snprintf(line, MAXLINELEN, "%s/%d\n", addr, in6->prefix?in6->prefix:64);
-
-       if (write(fd, line, strlen(line)) < 0) {
-               SYSERROR("failed to write address info");
-               goto err;
-       }
-
-       err = 0;
-err:
-       return err;
-}
-
-static int configure_ip_address(const char *path, struct lxc_list *ip, int family)
-{
-       char file[MAXPATHLEN];
-       struct lxc_list *iterator;
-       int fd, err = -1;
-
-       if (mkdir(path, 0755)) {
-               SYSERROR("failed to create directory %s", path);
-               return -1;
-       }
-
-       snprintf(file, MAXPATHLEN, "%s/addresses", path);
-       fd = creat(file, 0755);
-       if (fd < 0) {
-               SYSERROR("failed to create %s file", file);
-               goto err;
-       }
-
-       lxc_list_for_each(iterator, ip) {
-               err = family == AF_INET?
-                       configure_ip4addr(fd, iterator->elem):
-                       configure_ip6addr(fd, iterator->elem);
-               if (err)
-                       goto err;
-       }
-out:
-       close(fd);
-       return err;
-err:
-       unlink(file);
-       rmdir(path);
-       goto out;
-}
-
-static int configure_netdev(const char *path, struct lxc_netdev *netdev)
-{
-       int err = -1;
-       char dir[MAXPATHLEN];
-
-       if (mkdir(path, 0755)) {
-               SYSERROR("failed to create %s directory", path);
-               return -1;
-       }
-
-       if (netdev->ifname) {
-               if (write_info(path, "link", netdev->ifname))
-                       goto out_link;
-       }
-
-       if (netdev->newname) {
-               if (write_info(path, "name", netdev->newname))
-                       goto out_newname;
-       }
-
-       if (netdev->hwaddr) {
-               if (write_info(path, "hwaddr", netdev->hwaddr))
-                       goto out_hwaddr;
-       }
-
-       if (netdev->mtu) {
-               if (write_info(path, "mtu", netdev->mtu))
-                       goto out_mtu;
-       }
-
-       if (netdev->flags & IFF_UP) {
-               if (write_info(path, "up", ""))
-                       goto out_up;
-       }
-
-       if (!lxc_list_empty(&netdev->ipv4)) {
-               snprintf(dir, MAXPATHLEN, "%s/ipv4", path);
-               if (configure_ip_address(dir, &netdev->ipv4, AF_INET))
-                       goto out_ipv4;
-       }
-
-       if (!lxc_list_empty(&netdev->ipv6)) {
-               snprintf(dir, MAXPATHLEN, "%s/ipv6", path);
-               if (configure_ip_address(dir, &netdev->ipv6, AF_INET6))
-                       goto out_ipv6;
-       }
-       err = 0;
-out:
-       return err;
-out_ipv6:
-       delete_info(path, "ipv4");
-out_ipv4:
-       delete_info(path, "up");
-out_up:
-       delete_info(path, "mtu");
-out_mtu:
-       delete_info(path, "hwaddr");
-out_hwaddr:
-       delete_info(path, "name");
-out_newname:
-       delete_info(path, "link");
-out_link:
-       rmdir(path);
-       goto out;
-}
-
-static int configure_utsname(const char *name, struct utsname *utsname)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-
-       if (write_info(path, "utsname", utsname->nodename)) {
-               ERROR("failed to write the utsname info");
-               return -1;
-       }
-
-       return 0;
-}
-
-static int configure_network(const char *name, struct lxc_list *network)
-{
-       struct lxc_list *iterator;
-       struct lxc_network *n;
-       char networkpath[MAXPATHLEN];
-       char path[MAXPATHLEN];
-       int err = -1;
-
-       if (lxc_list_empty(network))
-               return 0;
-
-       snprintf(networkpath, MAXPATHLEN, LXCPATH "/%s/network", name);
-       if (mkdir(networkpath, 0755)) {
-               SYSERROR("failed to create %s directory", networkpath);
-               goto out;
-       }
-
-       lxc_list_for_each(iterator, network) {
-
-               n = iterator->elem;
-
-               if (n->type < 0 || n->type > MAXCONFTYPE) {
-                       ERROR("invalid network configuration type '%d'",
-                                     n->type);
-                       goto out;
-               }
-
-               snprintf(path, MAXPATHLEN, "%s/%s%d", networkpath,
-                        netdev_conf[n->type].type,
-                        netdev_conf[n->type].count++);
-
-               if (configure_netdev(path, lxc_list_first_elem(&n->netdev))) {
-                       ERROR("failed to configure network type %s",
-                                     netdev_conf[n->type].type);
-                       goto out;
-               }
-       }
-
-       err = 0;
-out:
-       return err;
-}
-
-static int configure_cgroup(const char *name, struct lxc_list *cgroup)
-{
-       char path[MAXPATHLEN];
-       struct lxc_list *iterator;
-       struct lxc_cgroup *cg;
-       FILE *file;
-
-       if (lxc_list_empty(cgroup))
-               return 0;
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
-
-       file = fopen(path, "w+");
-       if (!file) {
-               SYSERROR("failed to open '%s'", path);
-               return -1;
-       }
-
-       lxc_list_for_each(iterator, cgroup) {
-               cg = iterator->elem;
-               fprintf(file, "%s=%s\n", cg->subsystem, cg->value);
-       }
-
-       fclose(file);
-
-       return 0;
-}
-
-static int configure_tty(const char *name, int tty)
-{
-       char path[MAXPATHLEN];
-       char *nbtty;
-       int ret;
-
-       if (asprintf(&nbtty, "%d", tty) < 0) {
-               ERROR("failed to convert tty number");
-               return -1;
-       }
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-
-       ret = write_info(path, "tty", nbtty);
-       if (ret)
-               ERROR("failed to write the tty info");
-
-       free(nbtty);
-
-       return ret;
-}
-
 static int configure_find_fstype_cb(void* buffer, void *data)
 {
        struct cbarg {
@@ -619,199 +293,22 @@ static int configure_rootfs(const char *name, const char *rootfs)
        return -1;
 }
 
-static int configure_pts(const char *name, int pts)
-{
-       char path[MAXPATHLEN];
-       char *maxpts;
-       int ret;
-
-       if (asprintf(&maxpts, "%d", pts) < 0) {
-               ERROR("failed to convert max pts number");
-               return -1;
-       }
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-
-       ret = write_info(path, "pts", maxpts);
-       if (ret)
-               ERROR("failed to write the pts info");
-
-       free(maxpts);
-
-       return ret;
-}
-
-static int configure_mount(const char *name, const char *fstab)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
-
-       if (lxc_copy_file(fstab, path)) {
-               ERROR("failed to copy the fstab file");
-               return -1;
-       }
-
-       return 0;
-}
-
-static int unconfigure_ip_addresses(const char *directory)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, "%s/ipv4", directory);
-       delete_info(path, "addresses");
-       rmdir(path);
-
-       snprintf(path, MAXPATHLEN, "%s/ipv6", directory);
-       delete_info(path, "addresses");
-       rmdir(path);
-
-       return 0;
-}
-
-static int unconfigure_network_cb(const char *name, const char *directory,
-                                 const char *file, void *data)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
-       delete_info(path, "ifindex");
-       delete_info(path, "name");
-       delete_info(path, "addr");
-       delete_info(path, "link");
-       delete_info(path, "hwaddr");
-       delete_info(path, "mtu");
-       delete_info(path, "up");
-       unconfigure_ip_addresses(path);
-       rmdir(path);
-
-       return 0;
-}
-
-static int unconfigure_network(const char *name)
-{
-       char directory[MAXPATHLEN];
-
-       snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
-       lxc_dir_for_each(name, directory, unconfigure_network_cb, NULL);
-       rmdir(directory);
-
-       return 0;
-}
-
-static int unconfigure_cgroup_cb(const char *name, const char *directory,
-                                 const char *file, void *data)
-{
-       return delete_info(directory, file);
-}
-
-static int unconfigure_cgroup(const char *name)
-{
-       char filename[MAXPATHLEN];
-       struct stat s;
-
-       snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
-
-       if (stat(filename, &s)) {
-               SYSERROR("failed to stat '%s'", filename);
-               return -1;
-       }
-
-       if (S_ISDIR(s.st_mode)) {
-               /* old cgroup configuration */
-               lxc_dir_for_each(name, filename, unconfigure_cgroup_cb, NULL);
-               rmdir(filename);
-       } else {
-               unlink(filename);
-       }
-
-       return 0;
-}
-
-static int unconfigure_rootfs(const char *name)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
-
-#warning deprecated code to be removed in the next version
-
-       /* ugly but for backward compatibily, */
-       delete_info(path, "rootfs");
-       rmdir(path);
-       unlink(path);
-
-       return 0;
-}
-
-static int unconfigure_pts(const char *name)
+static int setup_utsname(struct utsname *utsname)
 {
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-       delete_info(path, "pts");
-
-       return 0;
-}
-
-static int unconfigure_tty(const char *name)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-       delete_info(path, "tty");
-
-       return 0;
-}
-
-static int unconfigure_mount(const char *name)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-       delete_info(path, "fstab");
-
-       return 0;
-}
-
-static int unconfigure_utsname(const char *name)
-{
-       char path[MAXPATHLEN];
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-       delete_info(path, "utsname");
-
-       return 0;
-}
-
-static int setup_utsname(const char *name)
-{
-       int ret;
-       char path[MAXPATHLEN];
-       struct utsname utsname;
-
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-
-       ret = read_info(path, "utsname", utsname.nodename,
-                       sizeof(utsname.nodename));
-       if (ret < 0) {
-               SYSERROR("failed to read utsname info");
-               return -1;
-       }
+       if (!utsname)
+               return 0;
 
-       if (!ret && sethostname(utsname.nodename, strlen(utsname.nodename))) {
-               SYSERROR("failed to set the hostname to '%s'",
-                                utsname.nodename);
+       if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
+               SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
                return -1;
        }
 
-       INFO("'%s' hostname has been setup", utsname.nodename);
+       INFO("'%s' hostname has been setup", utsname->nodename);
 
        return 0;
 }
 
-static int setup_tty(const char *name, const struct lxc_tty_info *tty_info)
+static int setup_tty(const char *rootfs, const struct lxc_tty_info *tty_info)
 {
        char path[MAXPATHLEN];
        int i;
@@ -820,11 +317,8 @@ static int setup_tty(const char *name, const struct lxc_tty_info *tty_info)
 
                struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 
-               if (conf_has_rootfs(name))
-                       snprintf(path, MAXPATHLEN,
-                                LXCPATH "/%s/rootfs/dev/tty%d", name, i + 1);
-               else
-                       snprintf(path, MAXPATHLEN, "/dev/tty%d", i + 1);
+               snprintf(path, sizeof(path), "%s/dev/tty%d",
+                        rootfs ? rootfs : "", i + 1);
 
                /* At this point I can not use the "access" function
                 * to check the file is present or not because it fails
@@ -832,7 +326,7 @@ static int setup_tty(const char *name, const struct lxc_tty_info *tty_info)
 
                if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
                        WARN("failed to mount '%s'->'%s'",
-                                       pty_info->name, path);
+                            pty_info->name, path);
                        continue;
                }
        }
@@ -842,39 +336,59 @@ static int setup_tty(const char *name, const struct lxc_tty_info *tty_info)
        return 0;
 }
 
-static int setup_rootfs(const char *name)
+static int setup_rootfs(const char *rootfs)
 {
-       char path[MAXPATHLEN];
+       char *tmpname;
+       int ret = -1;
 
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
+       if (!rootfs)
+               return 0;
+
+       tmpname = tempnam("/tmp", "lxc-rootfs");
+       if (!tmpname) {
+               SYSERROR("failed to generate temporary name");
+               return -1;
+       }
 
-       if (chroot(path)) {
-               SYSERROR("failed to set chroot %s", path);
+       if (mkdir(tmpname, 0700)) {
+               SYSERROR("failed to create temporary directory '%s'", tmpname);
                return -1;
        }
 
+       if (mount(rootfs, tmpname, "none", MS_BIND|MS_REC, NULL)) {
+               SYSERROR("failed to mount '%s'->'%s'", rootfs, tmpname);
+               goto out;
+       }
+
+       if (chroot(tmpname)) {
+               SYSERROR("failed to set chroot %s", tmpname);
+               goto out;
+       }
+
        if (chdir(getenv("HOME")) && chdir("/")) {
                SYSERROR("failed to change to home directory");
-               return -1;
+               goto out;
        }
 
-       INFO("chrooted to '%s'", path);
+       INFO("chrooted to '%s'", rootfs);
 
-       return 0;
+       ret = 0;
+out:
+       rmdir(tmpname);
+       return ret;
 }
 
-static int setup_pts(const char *name)
+static int setup_pts(int pts)
 {
-       char mountname[MAXPATHLEN];
+       if (!pts)
+               return 0;
 
        if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
                SYSERROR("failed to umount 'dev/pts'");
                return -1;
        }
 
-       snprintf(mountname, MAXPATHLEN, "%spts", name);
-
-       if (mount(mountname, "/dev/pts", "devpts", MS_MGC_VAL, "newinstance")) {
+       if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance")) {
                SYSERROR("failed to mount a new instance of '/dev/pts'");
                return -1;
        }
@@ -898,15 +412,36 @@ static int setup_pts(const char *name)
        }
 
        INFO("created new pts instance");
+
 out:
        return 0;
 }
 
-static int setup_console(const char *name, const char *tty)
+static int setup_console(const char *rootfs, const char *tty)
 {
        char console[MAXPATHLEN];
 
-       snprintf(console, MAXPATHLEN, LXCPATH "/%s/rootfs/dev/console", name);
+       snprintf(console, sizeof(console), "%s/dev/console",
+                rootfs ? rootfs : "");
+
+       /* we have the rootfs with /dev/console but no tty
+        * to be used as console, let's remap /dev/console
+        * to /dev/null to avoid to log to the system console
+        */
+       if (rootfs && !tty[0]) {
+
+               if (!access(console, F_OK)) {
+
+                       if (mount("/dev/null", console, "none", MS_BIND, 0)) {
+                               SYSERROR("failed to mount '/dev/null'->'%s'",
+                                        console);
+                               return -1;
+                       }
+               }
+       }
+
+       if (!tty[0])
+               return 0;
 
        if (access(console, R_OK|W_OK))
                return 0;
@@ -921,110 +456,29 @@ static int setup_console(const char *name, const char *tty)
        return 0;
 }
 
-static int setup_cgroup_cb(void* buffer, void *data)
+static int setup_cgroup(const char *name, struct lxc_list *cgroups)
 {
-       char *key = buffer, *value;
-       char *name = data;
-       int ret;
-
-       value = strchr(key, '=');
-       if (!value)
-               return -1;
-
-       *value = '\0';
-       value += 1;
-
-       /* remove spurious '\n'*/
-       if (value[strlen(value) - 1] == '\n')
-               value[strlen(value) - 1] = '\0';
-
-       ret = lxc_cgroup_set(name, key, value);
-       if (ret)
-               ERROR("failed to set cgroup '%s' = '%s' for '%s'",
-                     key, value, name);
-       else
-               DEBUG("cgroup '%s' set to '%s'", key, value);
-
-       return ret;
-}
-
-static int setup_convert_cgroup_cb(const char *name, const char *directory,
-                                  const char *file, void *data)
-{
-       FILE *f = data;
-       char line[MAXPATHLEN];
-
-       if (read_info(directory, file, line, MAXPATHLEN)) {
-               ERROR("failed to read %s", file);
-               return -1;
-       }
-
-       fprintf(f, "%s=%s\n", file, line);
-
-       return 0;
-}
-
-static int setup_convert_cgroup(const char *name, char *directory)
-{
-       char filename[MAXPATHLEN];
-       FILE *file;
-       int ret;
-
-       snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup.new", name);
-
-       file = fopen(filename, "w+");
-       if (!file)
-               return -1;
-
-       ret = lxc_dir_for_each(name, directory, setup_convert_cgroup_cb, file);
-       if (ret)
-               goto out_error;
-
-       ret = unconfigure_cgroup(name);
-       if (ret)
-               goto out_error;
-
-       ret = rename(filename, directory);
-       if (ret)
-               goto out_error;
-out:
-       fclose(file);
-       return ret;
+       struct lxc_list *iterator;
+       struct lxc_cgroup *cg;
+       int ret = -1;
 
-out_error:
-       unlink(filename);
-       goto out;
-}
+       if (lxc_list_empty(cgroups))
+               return 0;
 
-static int setup_cgroup(const char *name)
-{
-       char filename[MAXPATHLEN];
-       char line[MAXPATHLEN];
-       struct stat s;
-       int ret;
+       lxc_list_for_each(iterator, cgroups) {
 
-       snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
+               cg = iterator->elem;
 
-       if (stat(filename, &s)) {
-               SYSERROR("failed to stat '%s'", filename);
-               return -1;
-       }
+               if (lxc_cgroup_set(name, cg->subsystem, cg->value))
+                       goto out;
 
-       if (S_ISDIR(s.st_mode)) {
-               if (setup_convert_cgroup(name, filename)) {
-                       ERROR("failed to convert old cgroup configuration");
-                       return -1;
-               }
+               DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
        }
 
-       ret = lxc_file_for_each_line(filename, setup_cgroup_cb,
-                                    line, MAXPATHLEN, (void *)name);
-       if (ret)
-               return ret;
-
+       ret = 0;
        INFO("cgroup has been setup");
-
-       return 0;
+out:
+       return ret;
 }
 
 static void parse_mntopt(char *opt, unsigned long *flags, char **data)
@@ -1085,26 +539,15 @@ static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
        return 0;
 }
 
-static int setup_mount(const char *name)
+static int mount_file_entries(FILE *file)
 {
-       char path[MAXPATHLEN];
        struct mntent *mntent;
-       FILE *file;
        int ret = -1;
        unsigned long mntflags;
        char *mntdata;
 
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
-
-       file = setmntent(path, "r");
-       if (!file) {
-               if (errno == ENOENT)
-                       return 0;
-               SYSERROR("failed to open '%s'", path);
-               goto out;
-       }
-
        while ((mntent = getmntent(file))) {
+
                mntflags = 0;
                mntdata = NULL;
                if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
@@ -1130,80 +573,53 @@ static int setup_mount(const char *name)
 
        INFO("mount points have been setup");
 out:
-       endmntent(file);
        return ret;
 }
 
-static int setup_ipv4_addr_cb(void *buffer, void *data)
+static int setup_mount(const char *fstab)
 {
-       char *ifname = data;
-       char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
-       int p = 24;
-
-       addr = buffer;
-       cursor = strstr(addr, " ");
-       if (cursor) {
-               *cursor = '\0';
-               bcast = cursor + 1;
-               cursor = strstr(bcast, "\n");
-               if (cursor)
-                       *cursor = '\0';
-       }
-
-       slash = strstr(addr, "/");
-       if (slash) {
-               *slash = '\0';
-               prefix = slash + 1;
-       }
+       FILE *file;
+       int ret;
 
-       if (prefix)
-               p = atoi(prefix);
+       if (!fstab)
+               return 0;
 
-       if (lxc_ip_addr_add(ifname, addr, p, bcast)) {
-               ERROR("failed to set %s to addr %s/%d %s", ifname,
-                             addr, p, bcast?bcast:"");
+       file = setmntent(fstab, "r");
+       if (!file) {
+               SYSERROR("failed to use '%s'", fstab);
                return -1;
        }
 
-       DEBUG("address '%s/%s' on '%s' has been setup", addr, prefix, ifname);
+       ret = mount_file_entries(file);
 
-       return 0;
+       endmntent(file);
+       return ret;
 }
 
-static int setup_ipv6_addr_cb(void *buffer, void *data)
+static int setup_mount_entries(struct lxc_list *mount)
 {
-       char *ifname = data;
-       char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
-       int p = 24;
+       FILE *file;
+       struct lxc_list *iterator;
+       char *mount_entry;
+       int ret;
 
-       addr = buffer;
-       cursor = strstr(addr, " ");
-       if (cursor) {
-               *cursor = '\0';
-               bcast = cursor + 1;
-               cursor = strstr(bcast, "\n");
-               if (cursor)
-                       *cursor = '\0';
+       file = tmpfile();
+       if (!file) {
+               ERROR("tmpfile error: %m");
+               return -1;
        }
 
-       slash = strstr(addr, "/");
-       if (slash) {
-               *slash = '\0';
-               prefix = slash + 1;
+       lxc_list_for_each(iterator, mount) {
+               mount_entry = iterator->elem;
+               fprintf(file, "%s\n", mount_entry);
        }
 
-       if (prefix)
-               p = atoi(prefix);
-
-       if (lxc_ip6_addr_add(ifname, addr, p, bcast)) {
-               ERROR("failed to set %s to addr %s/%d %s", ifname,
-                             addr, p, bcast?bcast:"");
-               return -1;
-       }
+       rewind(file);
 
-       INFO("address '%s/%s' on '%s' has been setup", addr, prefix, ifname);
+       ret = mount_file_entries(file);
 
-       return 0;
+       fclose(file);
+       return ret;
 }
 
 static int setup_hw_addr(char *hwaddr, const char *ifname)
@@ -1236,71 +652,70 @@ static int setup_hw_addr(char *hwaddr, const char *ifname)
        return ret;
 }
 
-static int setup_ip_addr(const char *directory, const char *ifname)
+static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
 {
-       char path[MAXPATHLEN], line[MAXLINELEN];
-       struct stat s;
-       int ret = 0;
+       struct lxc_list *iterator;
+       struct lxc_inetdev *inetdev;
 
-       snprintf(path, MAXPATHLEN, "%s/ipv4/addresses", directory);
-       if (!stat(path, &s))
-               ret = lxc_file_for_each_line(path, setup_ipv4_addr_cb,
-                                            line, MAXPATHLEN, (void*)ifname);
-       return ret;
+       lxc_list_for_each(iterator, ip) {
+
+               inetdev = iterator->elem;
+
+               if (lxc_ip_addr_add(AF_INET, ifindex,
+                                   &inetdev->addr, inetdev->prefix)) {
+                       return -1;
+               }
+       }
+
+       return 0;
 }
 
-static int setup_ip6_addr(const char *directory, const char *ifname)
+static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
 {
-       char path[MAXPATHLEN], line[MAXLINELEN];
-       struct stat s;
-       int ret = 0;
+       struct lxc_list *iterator;
+       struct lxc_inet6dev *inet6dev;
 
-       snprintf(path, MAXLINELEN, "%s/ipv6/addresses", directory);
-       if (!stat(path, &s))
-               ret = lxc_file_for_each_line(path, setup_ipv6_addr_cb,
-                                            line, MAXPATHLEN, (void*)ifname);
-       return ret;
+       lxc_list_for_each(iterator, ip) {
+
+               inet6dev = iterator->elem;
+
+               if (lxc_ip_addr_add(AF_INET6, ifindex,
+                                   & inet6dev->addr, inet6dev->prefix))
+                       return -1;
+       }
+
+       return 0;
 }
 
-static int setup_network_cb(const char *name, const char *directory,
-                           const char *file, void *data)
+static int setup_netdev(struct lxc_netdev *netdev)
 {
-       char path[MAXPATHLEN];
-       char strindex[MAXINDEXLEN];
        char ifname[IFNAMSIZ];
-       char newname[IFNAMSIZ];
-       char hwaddr[MAXHWLEN];
        char *current_ifname = ifname;
-       int ifindex;
-
-       snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
-
-       if (read_info(path, "ifindex", strindex, sizeof(strindex))) {
-               ERROR("failed to read ifindex info");
-               return -1;
-       }
 
-       ifindex = atoi(strindex);
-       if (!ifindex) {
-               if (!read_info(path, "up", strindex, sizeof(strindex)))
-                   if (lxc_device_up("lo")) {
-                           ERROR("failed to set the loopback up");
-                           return -1;
-                   }
-                   return 0;
+       /* empty network namespace */
+       if (!netdev->ifindex) {
+               if (netdev->flags | IFF_UP) {
+                       if (lxc_device_up("lo")) {
+                               ERROR("failed to set the loopback up");
+                               return -1;
+                       }
+                       return 0;
+               }
        }
 
-       if (!if_indextoname(ifindex, current_ifname)) {
+       /* retrieve the name of the interface */
+       if (!if_indextoname(netdev->ifindex, current_ifname)) {
                ERROR("no interface corresponding to index '%d'",
-                             ifindex);
+                     netdev->ifindex);
                return -1;
        }
 
        /* default: let the system to choose one interface name */
-       if (read_info(path, "name", newname, sizeof(newname)))
-               strcpy(newname, "eth%d");
+       if (!netdev->name)
+               netdev->name = "eth%d";
 
-       if (lxc_device_rename(ifname, newname)) {
+       /* rename the interface name */
+       if (lxc_device_rename(ifname, netdev->name)) {
                ERROR("failed to rename %s->%s", ifname, current_ifname);
                return -1;
        }
@@ -1308,33 +723,37 @@ static int setup_network_cb(const char *name, const char *directory,
        /* Re-read the name of the interface because its name has changed
         * and would be automatically allocated by the system
         */
-       if (!if_indextoname(ifindex, current_ifname)) {
+       if (!if_indextoname(netdev->ifindex, current_ifname)) {
                ERROR("no interface corresponding to index '%d'",
-                             ifindex);
+                     netdev->ifindex);
                return -1;
        }
 
-       if (!read_info(path, "hwaddr", hwaddr, sizeof(hwaddr))) {
-               if (setup_hw_addr(hwaddr, current_ifname)) {
+       /* set a mac address */
+       if (netdev->hwaddr) {
+               if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
                        ERROR("failed to setup hw address for '%s'",
-                                     current_ifname);
+                             current_ifname);
                        return -1;
                }
        }
 
-       if (setup_ip_addr(path, current_ifname)) {
+       /* setup ipv4 addresses on the interface */
+       if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
                ERROR("failed to setup ip addresses for '%s'",
                              ifname);
                return -1;
        }
 
-       if (setup_ip6_addr(path, current_ifname)) {
+       /* setup ipv6 addresses on the interface */
+       if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
                ERROR("failed to setup ipv6 addresses for '%s'",
                              ifname);
                return -1;
        }
 
-       if (!read_info(path, "up", strindex, sizeof(strindex))) {
+       /* set the network device up */
+       if (netdev->flags | IFF_UP) {
                if (lxc_device_up(current_ifname)) {
                        ERROR("failed to set '%s' up", current_ifname);
                        return -1;
@@ -1352,18 +771,23 @@ static int setup_network_cb(const char *name, const char *directory,
        return 0;
 }
 
-static int setup_network(const char *name)
+static int setup_network(struct lxc_list *network)
 {
-       char directory[MAXPATHLEN];
-       int ret;
+       struct lxc_list *iterator;
+       struct lxc_netdev *netdev;
 
-       snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
+       lxc_list_for_each(iterator, network) {
 
-       ret = lxc_dir_for_each(name, directory, setup_network_cb, NULL);
-       if (ret)
-               return ret;
+               netdev = iterator->elem;
+
+               if (setup_netdev(netdev)) {
+                       ERROR("failed to setup netdev");
+                       return -1;
+               }
+       }
 
-       INFO("network has been setup");
+       if (!lxc_list_empty(network))
+               INFO("network has been setup");
 
        return 0;
 }
@@ -1391,385 +815,251 @@ out:
        return ret;
 }
 
-int lxc_conf_init(struct lxc_conf *conf)
+struct lxc_conf *lxc_conf_init(void)
 {
-       conf->rcfile = NULL;
-       conf->rootfs = NULL;
-       conf->fstab = NULL;
-       conf->utsname = NULL;
-       conf->tty = 0;
-       conf->pts = 0;
-       lxc_list_init(&conf->cgroup);
-       lxc_list_init(&conf->networks);
-       return 0;
+       struct lxc_conf *new;
+
+       new =   malloc(sizeof(*new));
+       if (!new) {
+               ERROR("lxc_conf_init : %m");
+               return NULL;
+       }
+       memset(new, 0, sizeof(*new));
+
+       new->rootfs = NULL;
+       new->fstab = NULL;
+       new->utsname = NULL;
+       new->tty = 0;
+       new->pts = 0;
+       new->console[0] = '\0';
+       lxc_list_init(&new->cgroup);
+       lxc_list_init(&new->network);
+       lxc_list_init(&new->mount_list);
+
+       return new;
 }
 
-int lxc_configure(const char *name, struct lxc_conf *conf)
+static int instanciate_veth(struct lxc_netdev *netdev)
 {
-       if (!conf)
-               return 0;
-
-       if (conf->utsname && configure_utsname(name, conf->utsname)) {
-               ERROR("failed to configure the utsname");
-               return -1;
-       }
-
-       if (configure_cgroup(name, &conf->cgroup)) {
-               ERROR("failed to configure the control group");
-               return -1;
-       }
-
-       if (configure_network(name, &conf->networks)) {
-               ERROR("failed to configure the network");
-               return -1;
-       }
-
-       if (conf->tty && configure_tty(name, conf->tty)) {
-               ERROR("failed to configure the tty");
-               return -1;
-       }
+       char veth1buf[IFNAMSIZ], *veth1;
+       char veth2[IFNAMSIZ];
 
-       if (conf->fstab && configure_mount(name, conf->fstab)) {
-               ERROR("failed to configure the mount points");
-               return -1;
+       if (netdev->priv.veth_attr.pair)
+               veth1 = netdev->priv.veth_attr.pair;
+       else {
+               snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
+               mktemp(veth1buf);
+               veth1 = veth1buf;
        }
 
-       if (conf->rootfs && configure_rootfs(name, conf->rootfs)) {
-               ERROR("failed to configure the rootfs");
-               return -1;
-       }
+       snprintf(veth2, sizeof(veth2), "vethXXXXXX");
+       mktemp(veth2);
 
-       if (conf->pts && configure_pts(name, conf->pts)) {
-               ERROR("failed to configure a new pts instance");
+       if (!strlen(veth1) || !strlen(veth2)) {
+               ERROR("failed to allocate a temporary name");
                return -1;
        }
 
-       return 0;
-}
-
-int lxc_unconfigure(const char *name)
-{
-       if (conf_has_utsname(name) && unconfigure_utsname(name))
-               ERROR("failed to cleanup utsname");
-
-       if (conf_has_network(name) && unconfigure_network(name))
-               ERROR("failed to cleanup the network");
-
-       if (conf_has_cgroup(name) && unconfigure_cgroup(name))
-               ERROR("failed to cleanup cgroup");
-
-       if (conf_has_tty(name) && unconfigure_tty(name))
-               ERROR("failed to cleanup tty");
-
-       if (conf_has_rootfs(name) && unconfigure_rootfs(name))
-               ERROR("failed to cleanup rootfs");
-
-       if (conf_has_fstab(name) && unconfigure_mount(name))
-               ERROR("failed to cleanup mount");
-
-       if (conf_has_pts(name) && unconfigure_pts(name))
-               ERROR("failed to cleanup pts");
-
-       return 0;
-}
-
-static int instanciate_veth(const char *directory, const char *file, pid_t pid)
-{
-       char *path = NULL, *strindex = NULL, *veth1 = NULL, *veth2 = NULL;
-       char bridge[IFNAMSIZ];
-       char strmtu[MAXMTULEN];
-       int ifindex, mtu = 0, ret = -1;
-
-       if (!asprintf(&veth1, "%s_%d", file, pid) ||
-           !asprintf(&veth2, "%s~%d", file, pid) ||
-           !asprintf(&path, "%s/%s", directory, file)) {
-               SYSERROR("failed to allocate memory");
-               goto out;
-       }
-
-       if (read_info(path, "link", bridge, IFNAMSIZ)) {
-               ERROR("failed to read bridge info");
-               goto out;
-       }
-
        if (lxc_veth_create(veth1, veth2)) {
-               ERROR("failed to create %s-%s/%s", veth1, veth2, bridge);
-               goto out;
+               ERROR("failed to create %s-%s", veth1, veth2);
+               return -1;
        }
 
-       if (!read_info(path, "mtu", strmtu, MAXMTULEN)) {
-               if (sscanf(strmtu, "%u", &mtu) < 1) {
-                       ERROR("invalid mtu size '%d'", mtu);
-                       goto out_delete;
-               }
-
-               if (lxc_device_set_mtu(veth1, mtu)) {
-                       ERROR("failed to set mtu for '%s'", veth1);
-                       goto out_delete;
-               }
-
-               if (lxc_device_set_mtu(veth2, mtu)) {
-                       ERROR("failed to set mtu for '%s'", veth2);
+       if (netdev->mtu) {
+               if (lxc_device_set_mtu(veth1, atoi(netdev->mtu)) ||
+                   lxc_device_set_mtu(veth2, atoi(netdev->mtu))) {
+                       ERROR("failed to set mtu '%s' for %s-%s",
+                             netdev->mtu, veth1, veth2);
                        goto out_delete;
                }
        }
 
-       if (lxc_bridge_attach(bridge, veth1)) {
+       if (netdev->link && lxc_bridge_attach(netdev->link, veth1)) {
                ERROR("failed to attach '%s' to the bridge '%s'",
-                             veth1, bridge);
+                             veth1, netdev->link);
                goto out_delete;
        }
 
-       ifindex = if_nametoindex(veth2);
-       if (!ifindex) {
+       netdev->ifindex = if_nametoindex(veth2);
+       if (!netdev->ifindex) {
                ERROR("failed to retrieve the index for %s", veth2);
                goto out_delete;
        }
 
-       if (!asprintf(&strindex, "%d", ifindex)) {
-               SYSERROR("failed to allocate memory");
-               goto out_delete;
-       }
-
-       if (write_info(path, "ifindex", strindex)) {
-               ERROR("failed to write interface index to %s", path);
-               goto out_delete;
-       }
-
-       if (!read_info(path, "up", strindex, sizeof(strindex))) {
+       if (netdev->flags & IFF_UP) {
                if (lxc_device_up(veth1)) {
                        ERROR("failed to set %s up", veth1);
                        goto out_delete;
                }
        }
 
-       ret = 0;
-out:
-       free(path);
-       free(strindex);
-       free(veth1);
-       free(veth2);
-       return ret;
+       DEBUG("instanciated veth '%s/%s', index is '%d'",
+             veth1, veth2, netdev->ifindex);
+
+       return 0;
 
 out_delete:
        lxc_device_delete(veth1);
-       goto out;
+       return -1;
 }
-static int instanciate_macvlan(const char *directory, const char *file, pid_t pid)
+
+static int instanciate_macvlan(struct lxc_netdev *netdev)
 {
-       char path[MAXPATHLEN], *strindex = NULL, *peer = NULL;
-       char link[IFNAMSIZ];
-       int ifindex, ret = -1;
+       char peer[IFNAMSIZ];
 
-       if (!asprintf(&peer, "%s~%d", file, pid)) {
-               SYSERROR("failed to allocate memory");
+       if (!netdev->link) {
+               ERROR("no link specified for macvlan netdev");
                return -1;
        }
 
-       snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
-       if (read_info(path, "link", link, IFNAMSIZ)) {
-               ERROR("failed to read bridge info");
-               goto out;
+       snprintf(peer, sizeof(peer), "mcXXXXXX");
+
+       mktemp(peer);
+
+       if (!strlen(peer)) {
+               ERROR("failed to make a temporary name");
+               return -1;
        }
 
-       if (lxc_macvlan_create(link, peer)) {
+       if (lxc_macvlan_create(netdev->link, peer,
+                              netdev->priv.macvlan_attr.mode)) {
                ERROR("failed to create macvlan interface '%s' on '%s'",
-                             peer, link);
-               goto out;
+                     peer, netdev->link);
+               return -1;
        }
 
-       ifindex = if_nametoindex(peer);
-       if (!ifindex) {
+       netdev->ifindex = if_nametoindex(peer);
+       if (!netdev->ifindex) {
                ERROR("failed to retrieve the index for %s", peer);
-               goto out;
-       }
-
-       if (!asprintf(&strindex, "%d", ifindex)) {
-               SYSERROR("failed to allocate memory");
+               lxc_device_delete(peer);
                return -1;
        }
 
-       if (write_info(path, "ifindex", strindex)) {
-               ERROR("failed to write interface index to %s", path);
-               goto out;
-       }
+       DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
+             peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
 
-       ret = 0;
-out:
-       free(strindex);
-       free(peer);
-       return ret;
+       return 0;
 }
 
-static int instanciate_phys(const char *directory, const char *file, pid_t pid)
+/* XXX: merge with instanciate_macvlan */
+static int instanciate_vlan(struct lxc_netdev *netdev)
 {
-       char path[MAXPATHLEN], *strindex = NULL;
-       char link[IFNAMSIZ];
-       int ifindex, ret = -1;
+       char peer[IFNAMSIZ];
 
-       snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
-       if (read_info(path, "link", link, IFNAMSIZ)) {
-               ERROR("failed to read link info");
-               goto out;
+       if (!netdev->link) {
+               ERROR("no link specified for vlan netdev");
+               return -1;
        }
 
-       ifindex = if_nametoindex(link);
-       if (!ifindex) {
-               ERROR("failed to retrieve the index for %s", link);
-               goto out;
-       }
+       snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
 
-       if (!asprintf(&strindex, "%d", ifindex)) {
-               SYSERROR("failed to allocate memory");
+       if (lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid)) {
+               ERROR("failed to create vlan interface '%s' on '%s'",
+                     peer, netdev->link);
                return -1;
        }
 
-       if (write_info(path, "ifindex", strindex)) {
-               ERROR("failed to write interface index to %s", path);
-               goto out;
-       }
-
-       ret = 0;
-out:
-       free(strindex);
-       return ret;
-}
-
-static int instanciate_empty(const char *directory, const char *file, pid_t pid)
-{
-       char path[MAXPATHLEN], *strindex = NULL;
-       int ret = -1;
-
-       snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
-       if (!asprintf(&strindex, "%d", 0)) {
-               ERROR("not enough memory");
+       netdev->ifindex = if_nametoindex(peer);
+       if (!netdev->ifindex) {
+               ERROR("failed to retrieve the ifindex for %s", peer);
+               lxc_device_delete(peer);
                return -1;
        }
 
-       if (write_info(path, "ifindex", strindex)) {
-               ERROR("failed to write interface index to %s", path);
-               goto out;
-       }
+       DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
+             netdev->ifindex);
 
-       ret = 0;
-out:
-       free(strindex);
-       return ret;
+       return 0;
 }
 
-static int instanciate_netdev_cb(const char *name, const char *directory,
-                                const char *file, void *data)
+static int instanciate_phys(struct lxc_netdev *netdev)
 {
-       pid_t *pid = data;
-
-       if (!strncmp("veth", file, strlen("veth")))
-               return instanciate_veth(directory, file, *pid);
-       else if (!strncmp("macvlan", file, strlen("macvlan")))
-               return instanciate_macvlan(directory, file, *pid);
-       else if (!strncmp("phys", file, strlen("phys")))
-               return instanciate_phys(directory, file, *pid);
-       else if (!strncmp("empty", file, strlen("empty")))
-                return instanciate_empty(directory, file, *pid);
+       netdev->ifindex = if_nametoindex(netdev->link);
+       if (!netdev->ifindex) {
+               ERROR("failed to retrieve the index for %s", netdev->link);
+               return -1;
+       }
 
-       return -1;
+       return 0;
 }
 
-static int instanciate_netdev(const char *name, pid_t pid)
+static int instanciate_empty(struct lxc_netdev *netdev)
 {
-       char directory[MAXPATHLEN];
-
-       snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
-       return lxc_dir_for_each(name, directory, instanciate_netdev_cb, &pid);
+       netdev->ifindex = 0;
+       return 0;
 }
 
-static int move_netdev_cb(const char *name, const char *directory,
-                         const char *file, void *data)
+int lxc_create_network(struct lxc_list *network)
 {
-       char path[MAXPATHLEN], ifname[IFNAMSIZ], strindex[MAXINDEXLEN];
-       pid_t *pid = data;
-       int ifindex;
+       struct lxc_list *iterator;
+       struct lxc_netdev *netdev;
 
-       snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
-       if (read_info(path, "ifindex", strindex, MAXINDEXLEN) < 0) {
-               ERROR("failed to read index to from %s", path);
-               return -1;
-       }
+       lxc_list_for_each(iterator, network) {
 
-       ifindex = atoi(strindex);
-       if (!ifindex)
-               return 0;
+               netdev = iterator->elem;
 
-       if (!if_indextoname(ifindex, ifname)) {
-               ERROR("interface with index %d does not exist",
-                             ifindex);
-               return -1;
-       }
+               if (netdev->type < 0 || netdev->type > MAXCONFTYPE) {
+                       ERROR("invalid network configuration type '%d'",
+                             netdev->type);
+                       return -1;
+               }
 
-       if (lxc_device_move(ifname, *pid)) {
-               ERROR("failed to move %s to %d", ifname, *pid);
-               return -1;
+               if (netdev_conf[netdev->type](netdev)) {
+                       ERROR("failed to create netdev");
+                       return -1;
+               }
        }
 
        return 0;
 }
 
-static int move_netdev(const char *name, pid_t pid)
+int lxc_assign_network(struct lxc_list *network, pid_t pid)
 {
-       char directory[MAXPATHLEN];
-       snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
-       return lxc_dir_for_each(name, directory, move_netdev_cb, &pid);
-}
+       struct lxc_list *iterator;
+       struct lxc_netdev *netdev;
 
-int conf_create_network(const char *name, pid_t pid)
-{
-       if (instanciate_netdev(name, pid)) {
-               ERROR("failed to instantiate the network devices");
-               return -1;
-       }
+       lxc_list_for_each(iterator, network) {
 
-       if (move_netdev(name, pid)) {
-               ERROR("failed to move the netdev to the container");
-               return -1;
+               netdev = iterator->elem;
+
+               if (lxc_device_move(netdev->ifindex, pid)) {
+                       ERROR("failed to move '%s' to the container",
+                             netdev->link);
+                       return -1;
+               }
+
+               DEBUG("move '%s' to '%d'", netdev->link, pid);
        }
 
        return 0;
 }
 
-int lxc_create_tty(const char *name, struct lxc_tty_info *tty_info)
+int lxc_create_tty(const char *name, struct lxc_conf *conf)
 {
-       char path[MAXPATHLEN];
-       char tty[4];
-       int i, ret = -1;
-
-       tty_info->nbtty = 0;
+       struct lxc_tty_info *tty_info = &conf->tty_info;
+       int i;
 
-       if (!conf_has_tty(name))
+       /* no tty in the configuration */
+       if (!conf->tty)
                return 0;
 
-       snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
-
-       if (read_info(path, "tty", tty, sizeof(tty)) < 0) {
-               SYSERROR("failed to read tty info");
-               goto out;
-       }
-
-       tty_info->nbtty = atoi(tty);
        tty_info->pty_info =
-               malloc(sizeof(*tty_info->pty_info)*tty_info->nbtty);
-
+               malloc(sizeof(*tty_info->pty_info)*conf->tty);
        if (!tty_info->pty_info) {
                SYSERROR("failed to allocate pty_info");
-               goto out;
+               return -1;
        }
 
-       for (i = 0; i < tty_info->nbtty; i++) {
+       for (i = 0; i < conf->tty; i++) {
 
                struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
 
                if (openpty(&pty_info->master, &pty_info->slave,
                            pty_info->name, NULL, NULL)) {
                        SYSERROR("failed to create pty #%d", i);
-                       goto out_free;
+                       tty_info->nbtty = i;
+                       lxc_delete_tty(tty_info);
+                       return -1;
                }
 
                 /* Prevent leaking the file descriptors to the container */
@@ -1779,16 +1069,11 @@ int lxc_create_tty(const char *name, struct lxc_tty_info *tty_info)
                pty_info->busy = 0;
        }
 
-       ret = 0;
+       tty_info->nbtty = conf->tty;
 
        INFO("tty's configured");
 
-out:
-       return ret;
-
-out_free:
-       free(tty_info->pty_info);
-       goto out;
+       return 0;
 }
 
 void lxc_delete_tty(struct lxc_tty_info *tty_info)
@@ -1806,66 +1091,49 @@ void lxc_delete_tty(struct lxc_tty_info *tty_info)
        tty_info->nbtty = 0;
 }
 
-extern int lxc_config_read(const char *file, struct lxc_conf *conf);
-
-int lxc_setup(const char *name, const char *cons,
-             const struct lxc_tty_info *tty_info)
-
+int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
 {
-       struct lxc_conf lxc_conf;
-       char path[MAXPATHLEN];
-
-       if (lxc_conf_init(&lxc_conf)) {
-               ERROR("failed to initialize the configuration");
-               return -1;
-       }
-
-       snprintf(path, sizeof(path), LXCPATH "/%s/config", name);
-
-       if (!access(path, F_OK)) {
-
-               if (lxc_config_read(path, &lxc_conf)) {
-                       ERROR("failed to read the configuration file");
-                       return -1;
-               }
-       }
-
-       if (lxc_conf.utsname && setup_utsname(name)) {
+       if (setup_utsname(lxc_conf->utsname)) {
                ERROR("failed to setup the utsname for '%s'", name);
                return -1;
        }
 
-       if (!lxc_list_empty(&lxc_conf.networks) && setup_network(name)) {
+       if (setup_network(&lxc_conf->network)) {
                ERROR("failed to setup the network for '%s'", name);
                return -1;
        }
 
-       if (!lxc_list_empty(&lxc_conf.cgroup) && setup_cgroup(name)) {
+       if (setup_cgroup(name, &lxc_conf->cgroup)) {
                ERROR("failed to setup the cgroups for '%s'", name);
                return -1;
        }
 
-       if (lxc_conf.fstab && setup_mount(name)) {
+       if (setup_mount(lxc_conf->fstab)) {
                ERROR("failed to setup the mounts for '%s'", name);
                return -1;
        }
 
-       if (cons[0] && setup_console(name, cons)) {
+       if (setup_mount_entries(&lxc_conf->mount_list)) {
+               ERROR("failed to setup the mount entries for '%s'", name);
+               return -1;
+       }
+
+       if (setup_console(lxc_conf->rootfs, lxc_conf->console)) {
                ERROR("failed to setup the console for '%s'", name);
                return -1;
        }
 
-       if (lxc_conf.tty && setup_tty(name, tty_info)) {
+       if (setup_tty(lxc_conf->rootfs, &lxc_conf->tty_info)) {
                ERROR("failed to setup the ttys for '%s'", name);
                return -1;
        }
 
-       if (lxc_conf.rootfs && setup_rootfs(name)) {
+       if (setup_rootfs(lxc_conf->rootfs)) {
                ERROR("failed to set rootfs for '%s'", name);
                return -1;
        }
 
-       if (lxc_conf.pts && setup_pts(name)) {
+       if (setup_pts(lxc_conf->pts)) {
                ERROR("failed to setup the new pts instance");
                return -1;
        }