]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/conf.c
fix tab vs space indentation
[mirror_lxc.git] / src / lxc / conf.c
CommitLineData
0ad19a3f 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#define _GNU_SOURCE
24#include <stdio.h>
25#undef _GNU_SOURCE
26#include <stdlib.h>
27#include <errno.h>
28#include <string.h>
29#include <dirent.h>
30#include <mntent.h>
31#include <unistd.h>
b0a33c1e 32#include <pty.h>
0ad19a3f 33
34#include <sys/types.h>
35#include <sys/utsname.h>
36#include <sys/param.h>
37#include <sys/stat.h>
38#include <sys/socket.h>
39#include <sys/mount.h>
40#include <sys/mman.h>
81810dd1
DL
41#include <sys/prctl.h>
42#include <sys/capability.h>
0ad19a3f 43
44#include <arpa/inet.h>
45#include <fcntl.h>
46#include <netinet/in.h>
47#include <net/if.h>
6f4a3756 48#include <libgen.h>
0ad19a3f 49
e5bda9ee 50#include "network.h"
51#include "error.h"
b2718c72 52#include "parse.h"
881450bb 53#include "config.h"
e5bda9ee 54
00b3c2e2 55#include <lxc/conf.h>
36eb9bde 56#include <lxc/log.h>
00b3c2e2 57#include <lxc/lxc.h> /* for lxc_cgroup_set() */
36eb9bde
CLG
58
59lxc_log_define(lxc_conf, lxc);
e5bda9ee 60
0ad19a3f 61#define MAXHWLEN 18
62#define MAXINDEXLEN 20
442cbbe6 63#define MAXMTULEN 16
0ad19a3f 64#define MAXLINELEN 128
65
fdc03323
DL
66#ifndef MS_REC
67#define MS_REC 16384
68#endif
69
bf601689
MH
70extern int pivot_root(const char * new_root, const char * put_old);
71
82d5ae15 72typedef int (*instanciate_cb)(struct lxc_netdev *);
0ad19a3f 73
998ac676
RT
74struct mount_opt {
75 char *name;
76 int clear;
77 int flag;
78};
79
81810dd1
DL
80struct caps_opt {
81 char *name;
82 int value;
83};
84
82d5ae15
DL
85static int instanciate_veth(struct lxc_netdev *);
86static int instanciate_macvlan(struct lxc_netdev *);
26c39028 87static int instanciate_vlan(struct lxc_netdev *);
82d5ae15
DL
88static int instanciate_phys(struct lxc_netdev *);
89static int instanciate_empty(struct lxc_netdev *);
90
91static instanciate_cb netdev_conf[MAXCONFTYPE + 1] = {
92 [VETH] = instanciate_veth,
93 [MACVLAN] = instanciate_macvlan,
26c39028 94 [VLAN] = instanciate_vlan,
82d5ae15
DL
95 [PHYS] = instanciate_phys,
96 [EMPTY] = instanciate_empty,
0ad19a3f 97};
98
998ac676
RT
99static struct mount_opt mount_opt[] = {
100 { "defaults", 0, 0 },
101 { "ro", 0, MS_RDONLY },
102 { "rw", 1, MS_RDONLY },
103 { "suid", 1, MS_NOSUID },
104 { "nosuid", 0, MS_NOSUID },
105 { "dev", 1, MS_NODEV },
106 { "nodev", 0, MS_NODEV },
107 { "exec", 1, MS_NOEXEC },
108 { "noexec", 0, MS_NOEXEC },
109 { "sync", 0, MS_SYNCHRONOUS },
110 { "async", 1, MS_SYNCHRONOUS },
111 { "remount", 0, MS_REMOUNT },
112 { "mand", 0, MS_MANDLOCK },
113 { "nomand", 1, MS_MANDLOCK },
114 { "atime", 1, MS_NOATIME },
115 { "noatime", 0, MS_NOATIME },
116 { "diratime", 1, MS_NODIRATIME },
117 { "nodiratime", 0, MS_NODIRATIME },
118 { "bind", 0, MS_BIND },
119 { "rbind", 0, MS_BIND|MS_REC },
120 { NULL, 0, 0 },
121};
122
81810dd1 123static struct caps_opt caps_opt[] = {
1e11be34
DL
124 { "chown", CAP_CHOWN },
125 { "dac_override", CAP_DAC_OVERRIDE },
126 { "dac_read_search", CAP_DAC_READ_SEARCH },
127 { "fowner", CAP_FOWNER },
128 { "fsetid", CAP_FSETID },
81810dd1
DL
129 { "kill", CAP_KILL },
130 { "setgid", CAP_SETGID },
131 { "setuid", CAP_SETUID },
132 { "setpcap", CAP_SETPCAP },
133 { "linux_immutable", CAP_LINUX_IMMUTABLE },
134 { "net_bind_service", CAP_NET_BIND_SERVICE },
135 { "net_broadcast", CAP_NET_BROADCAST },
136 { "net_admin", CAP_NET_ADMIN },
137 { "net_raw", CAP_NET_RAW },
138 { "ipc_lock", CAP_IPC_LOCK },
139 { "ipc_owner", CAP_IPC_OWNER },
140 { "sys_module", CAP_SYS_MODULE },
141 { "sys_rawio", CAP_SYS_RAWIO },
142 { "sys_chroot", CAP_SYS_CHROOT },
143 { "sys_ptrace", CAP_SYS_PTRACE },
144 { "sys_pacct", CAP_SYS_PACCT },
145 { "sys_admin", CAP_SYS_ADMIN },
146 { "sys_boot", CAP_SYS_BOOT },
147 { "sys_nice", CAP_SYS_NICE },
148 { "sys_resource", CAP_SYS_RESOURCE },
149 { "sys_time", CAP_SYS_TIME },
150 { "sys_tty_config", CAP_SYS_TTY_CONFIG },
151 { "mknod", CAP_MKNOD },
152 { "lease", CAP_LEASE },
153 { "audit_write", CAP_AUDIT_WRITE },
154 { "audit_control", CAP_AUDIT_CONTROL },
155 { "setfcap", CAP_SETFCAP },
156 { "mac_override", CAP_MAC_OVERRIDE },
157 { "mac_admin", CAP_MAC_ADMIN },
81810dd1
DL
158};
159
160
7a7ff0c6 161static int configure_find_fstype_cb(char* buffer, void *data)
78ae2fcc 162{
163 struct cbarg {
164 const char *rootfs;
165 const char *testdir;
166 char *fstype;
167 int mntopt;
168 } *cbarg = data;
169
170 char *fstype;
171
172 /* we don't try 'nodev' entries */
173 if (strstr(buffer, "nodev"))
174 return 0;
175
176 fstype = buffer;
b2718c72 177 fstype += lxc_char_left_gc(fstype, strlen(fstype));
178 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
78ae2fcc 179
180 if (mount(cbarg->rootfs, cbarg->testdir, fstype, cbarg->mntopt, NULL))
181 return 0;
182
183 /* found ! */
184 umount(cbarg->testdir);
185 strcpy(cbarg->fstype, fstype);
186
187 return 1;
188}
189
190/* find the filesystem type with brute force */
191static int configure_find_fstype(const char *rootfs, char *fstype, int mntopt)
192{
193 int i, found;
78ae2fcc 194
195 struct cbarg {
196 const char *rootfs;
197 const char *testdir;
198 char *fstype;
199 int mntopt;
200 } cbarg = {
201 .rootfs = rootfs,
202 .fstype = fstype,
203 .mntopt = mntopt,
204 };
205
206 /* first we check with /etc/filesystems, in case the modules
207 * are auto-loaded and fall back to the supported kernel fs
208 */
209 char *fsfile[] = {
210 "/etc/filesystems",
211 "/proc/filesystems",
212 };
213
214 cbarg.testdir = tempnam("/tmp", "lxc-");
215 if (!cbarg.testdir) {
36eb9bde 216 SYSERROR("failed to build a temp name");
78ae2fcc 217 return -1;
218 }
219
220 if (mkdir(cbarg.testdir, 0755)) {
36eb9bde 221 SYSERROR("failed to create temporary directory");
78ae2fcc 222 return -1;
223 }
224
225 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
226
b2718c72 227 found = lxc_file_for_each_line(fsfile[i],
228 configure_find_fstype_cb,
2382ecff 229 &cbarg);
78ae2fcc 230
231 if (found < 0) {
36eb9bde 232 SYSERROR("failed to read '%s'", fsfile[i]);
78ae2fcc 233 goto out;
234 }
235
236 if (found)
237 break;
238 }
239
240 if (!found) {
36eb9bde 241 ERROR("failed to determine fs type for '%s'", rootfs);
78ae2fcc 242 goto out;
243 }
244
245out:
246 rmdir(cbarg.testdir);
247 return found - 1;
248}
249
250static int configure_rootfs_dir_cb(const char *rootfs, const char *absrootfs,
251 FILE *f)
252{
fdc03323 253 return fprintf(f, "%s %s none rbind 0 0\n", absrootfs, rootfs);
78ae2fcc 254}
255
256static int configure_rootfs_blk_cb(const char *rootfs, const char *absrootfs,
257 FILE *f)
258{
259 char fstype[MAXPATHLEN];
260
261 if (configure_find_fstype(absrootfs, fstype, 0)) {
36eb9bde 262 ERROR("failed to configure mount for block device '%s'",
78ae2fcc 263 absrootfs);
264 return -1;
265 }
266
267 return fprintf(f, "%s %s %s defaults 0 0\n", absrootfs, rootfs, fstype);
268}
269
eae6543d 270static int configure_rootfs(const char *name, const char *rootfs)
0ad19a3f 271{
272 char path[MAXPATHLEN];
b09ef133 273 char absrootfs[MAXPATHLEN];
9b0f0477 274 char fstab[MAXPATHLEN];
78ae2fcc 275 struct stat s;
9b0f0477 276 FILE *f;
78ae2fcc 277 int i, ret;
278
279 typedef int (*rootfs_cb)(const char *, const char *, FILE *);
280
281 struct rootfs_type {
282 int type;
283 rootfs_cb cb;
284 } rtfs_type[] = {
285 { __S_IFDIR, configure_rootfs_dir_cb },
286 { __S_IFBLK, configure_rootfs_blk_cb },
287 };
0ad19a3f 288
4c8ab83b 289 if (!realpath(rootfs, absrootfs)) {
36eb9bde 290 SYSERROR("failed to get real path for '%s'", rootfs);
4c8ab83b 291 return -1;
292 }
b09ef133 293
4c8ab83b 294 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
b09ef133 295
78ae2fcc 296 if (mkdir(path, 0755)) {
36eb9bde 297 SYSERROR("failed to create the '%s' directory", path);
78ae2fcc 298 return -1;
299 }
300
b09ef133 301 if (access(absrootfs, F_OK)) {
36eb9bde 302 SYSERROR("'%s' is not accessible", absrootfs);
b09ef133 303 return -1;
304 }
305
78ae2fcc 306 if (stat(absrootfs, &s)) {
36eb9bde 307 SYSERROR("failed to stat '%s'", absrootfs);
9b0f0477 308 return -1;
309 }
310
78ae2fcc 311 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
9b0f0477 312
78ae2fcc 313 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
314 continue;
9b0f0477 315
78ae2fcc 316 snprintf(fstab, MAXPATHLEN, LXCPATH "/%s/fstab", name);
4c8ab83b 317
78ae2fcc 318 f = fopen(fstab, "a+");
319 if (!f) {
36eb9bde 320 SYSERROR("failed to open fstab file");
78ae2fcc 321 return -1;
322 }
9b0f0477 323
78ae2fcc 324 ret = rtfs_type[i].cb(path, absrootfs, f);
9b0f0477 325
78ae2fcc 326 fclose(f);
327
328 if (ret < 0) {
36eb9bde 329 ERROR("failed to add rootfs mount in fstab");
78ae2fcc 330 return -1;
331 }
332
333 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs/rootfs", name);
334
335 return symlink(absrootfs, path);
336 }
9b0f0477 337
36eb9bde 338 ERROR("unsupported rootfs type for '%s'", absrootfs);
78ae2fcc 339 return -1;
0ad19a3f 340}
341
4e5440c6 342static int setup_utsname(struct utsname *utsname)
0ad19a3f 343{
4e5440c6
DL
344 if (!utsname)
345 return 0;
0ad19a3f 346
4e5440c6
DL
347 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
348 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
0ad19a3f 349 return -1;
350 }
351
4e5440c6 352 INFO("'%s' hostname has been setup", utsname->nodename);
cd54d859 353
0ad19a3f 354 return 0;
355}
356
52e35957 357static int setup_tty(const char *rootfs, const struct lxc_tty_info *tty_info)
b0a33c1e 358{
359 char path[MAXPATHLEN];
360 int i;
361
362 for (i = 0; i < tty_info->nbtty; i++) {
363
364 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
365
52e35957
DL
366 snprintf(path, sizeof(path), "%s/dev/tty%d",
367 rootfs ? rootfs : "", i + 1);
b0a33c1e 368
13954cce 369 /* At this point I can not use the "access" function
b0a33c1e 370 * to check the file is present or not because it fails
371 * with EACCES errno and I don't know why :( */
13954cce 372
b0a33c1e 373 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
36eb9bde 374 WARN("failed to mount '%s'->'%s'",
52e35957 375 pty_info->name, path);
b0a33c1e 376 continue;
377 }
378 }
379
cd54d859
DL
380 INFO("%d tty(s) has been setup", tty_info->nbtty);
381
b0a33c1e 382 return 0;
383}
384
7a7ff0c6 385static int setup_rootfs_pivot_root_cb(char *buffer, void *data)
bf601689
MH
386{
387 struct lxc_list *mountlist, *listentry, *iterator;
388 char *pivotdir, *mountpoint, *mountentry;
389 int found;
390 void **cbparm;
391
392 mountentry = buffer;
393 cbparm = (void **)data;
394
395 mountlist = cbparm[0];
396 pivotdir = cbparm[1];
397
398 /* parse entry, first field is mountname, ignore */
399 mountpoint = strtok(mountentry, " ");
400 if (!mountpoint)
401 return -1;
402
403 /* second field is mountpoint */
404 mountpoint = strtok(NULL, " ");
405 if (!mountpoint)
406 return -1;
407
408 /* only consider mountpoints below old root fs */
409 if (strncmp(mountpoint, pivotdir, strlen(pivotdir)))
410 return 0;
411
412 /* filter duplicate mountpoints */
413 found = 0;
414 lxc_list_for_each(iterator, mountlist) {
415 if (!strcmp(iterator->elem, mountpoint)) {
416 found = 1;
417 break;
418 }
419 }
420 if (found)
421 return 0;
422
423 /* add entry to list */
424 listentry = malloc(sizeof(*listentry));
425 if (!listentry) {
426 SYSERROR("malloc for mountpoint listentry failed");
427 return -1;
428 }
429
430 listentry->elem = strdup(mountpoint);
431 if (!listentry->elem) {
432 SYSERROR("strdup failed");
433 return -1;
434 }
435 lxc_list_add_tail(mountlist, listentry);
436
437 return 0;
438}
439
440
441static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
442{
2382ecff 443 char path[MAXPATHLEN];
bf601689
MH
444 void *cbparm[2];
445 struct lxc_list mountlist, *iterator;
446 int ok, still_mounted, last_still_mounted;
447 int pivotdir_is_temp = 0;
448
449 /* change into new root fs */
450 if (chdir(rootfs)) {
451 SYSERROR("can't chroot to new rootfs '%s'", rootfs);
452 return -1;
453 }
454
455 /* create temporary mountpoint if none specified */
456 if (!pivotdir) {
457
458 snprintf(path, sizeof(path), "./lxc-oldrootfs-XXXXXX" );
459 if (!mkdtemp(path)) {
460 SYSERROR("can't make temporary mountpoint");
461 return -1;
462 }
463
464 pivotdir = strdup(&path[1]); /* get rid of leading dot */
465 if (!pivotdir) {
466 SYSERROR("strdup failed");
467 return -1;
468 }
469
470 pivotdir_is_temp = 1;
471 }
472 else {
473 snprintf(path, sizeof(path), ".%s", pivotdir);
474 }
475
476 DEBUG("temporary mountpoint for old rootfs is '%s'", path);
477
478 /* pivot_root into our new root fs */
479
480 if (pivot_root(".", path)) {
481 SYSERROR("pivot_root syscall failed");
482 return -1;
483 }
484
485 if (chdir("/")) {
486 SYSERROR("can't chroot to / after pivot_root");
487 return -1;
488 }
489
490 DEBUG("pivot_root syscall to '%s' successful", pivotdir);
491
492 /* read and parse /proc/mounts in old root fs */
493 lxc_list_init(&mountlist);
494
495 snprintf(path, sizeof(path), "%s/", pivotdir);
496 cbparm[0] = &mountlist;
497 cbparm[1] = strdup(path);
498
499 if (!cbparm[1]) {
500 SYSERROR("strdup failed");
501 return -1;
502 }
503
504 snprintf(path, sizeof(path), "/%s/proc/mounts", pivotdir);
2382ecff 505 ok = lxc_file_for_each_line(path, setup_rootfs_pivot_root_cb, &cbparm);
bf601689
MH
506 if (ok < 0) {
507 SYSERROR("failed to read or parse mount list '%s'", path);
508 return -1;
509 }
510
511 /* umount filesystems until none left or list no longer shrinks */
512 still_mounted = 0;
513 do {
514 last_still_mounted = still_mounted;
515 still_mounted = 0;
516
517 lxc_list_for_each(iterator, &mountlist) {
518
519 if (!umount(iterator->elem)) {
520 DEBUG("umounted '%s'", (char *)iterator->elem);
521 lxc_list_del(iterator);
522 continue;
523 }
524
525 if (errno != EBUSY) {
526 SYSERROR("failed to umount '%s'", (char *)iterator->elem);
527 return -1;
528 }
529
530 still_mounted++;
531 }
532 } while (still_mounted > 0 && still_mounted != last_still_mounted);
533
534 if (still_mounted) {
535 ERROR("could not umount %d mounts", still_mounted);
536 return -1;
537 }
538
539 /* umount old root fs */
540 if (umount(pivotdir)) {
541 SYSERROR("could not unmount old rootfs");
542 return -1;
543 }
544 DEBUG("umounted '%s'", pivotdir);
545
546 /* remove temporary mount point */
547 if (pivotdir_is_temp) {
548 if (rmdir(pivotdir)) {
549 SYSERROR("can't remove temporary mountpoint");
550 return -1;
551 }
552
553 }
554
555 INFO("pivoted to '%s'", rootfs);
556 return 0;
557}
558
559static int setup_rootfs(const char *rootfs, const char *pivotdir)
0ad19a3f 560{
c69bd12f
DL
561 char *tmpname;
562 int ret = -1;
0ad19a3f 563
c69bd12f
DL
564 if (!rootfs)
565 return 0;
0ad19a3f 566
c69bd12f
DL
567 tmpname = tempnam("/tmp", "lxc-rootfs");
568 if (!tmpname) {
569 SYSERROR("failed to generate temporary name");
c3f0a28c 570 return -1;
571 }
0ad19a3f 572
c69bd12f
DL
573 if (mkdir(tmpname, 0700)) {
574 SYSERROR("failed to create temporary directory '%s'", tmpname);
575 return -1;
576 }
577
578 if (mount(rootfs, tmpname, "none", MS_BIND|MS_REC, NULL)) {
579 SYSERROR("failed to mount '%s'->'%s'", rootfs, tmpname);
580 goto out;
581 }
582
bf601689
MH
583 if (setup_rootfs_pivot_root(tmpname, pivotdir)) {
584 ERROR("failed to pivot_root to '%s'", rootfs);
c69bd12f
DL
585 goto out;
586 }
587
c69bd12f
DL
588 ret = 0;
589out:
590 rmdir(tmpname);
591 return ret;
0ad19a3f 592}
593
d852c78c 594static int setup_pts(int pts)
3c26f34e 595{
d852c78c
DL
596 if (!pts)
597 return 0;
3c26f34e 598
599 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
36eb9bde 600 SYSERROR("failed to umount 'dev/pts'");
3c26f34e 601 return -1;
602 }
603
d852c78c 604 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance")) {
36eb9bde 605 SYSERROR("failed to mount a new instance of '/dev/pts'");
3c26f34e 606 return -1;
607 }
608
609 if (chmod("/dev/pts/ptmx", 0666)) {
36eb9bde 610 SYSERROR("failed to set permission for '/dev/pts/ptmx'");
3c26f34e 611 return -1;
612 }
613
614 if (access("/dev/ptmx", F_OK)) {
615 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
616 goto out;
36eb9bde 617 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 618 return -1;
619 }
620
621 /* fallback here, /dev/pts/ptmx exists just mount bind */
622 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
36eb9bde 623 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 624 return -1;
625 }
cd54d859
DL
626
627 INFO("created new pts instance");
d852c78c 628
3c26f34e 629out:
630 return 0;
631}
632
52e35957 633static int setup_console(const char *rootfs, const char *tty)
6e590161 634{
ed502555 635 char console[MAXPATHLEN];
636
52e35957
DL
637 snprintf(console, sizeof(console), "%s/dev/console",
638 rootfs ? rootfs : "");
639
640 /* we have the rootfs with /dev/console but no tty
641 * to be used as console, let's remap /dev/console
642 * to /dev/null to avoid to log to the system console
643 */
644 if (rootfs && !tty[0]) {
645
646 if (!access(console, F_OK)) {
647
648 if (mount("/dev/null", console, "none", MS_BIND, 0)) {
649 SYSERROR("failed to mount '/dev/null'->'%s'",
650 console);
651 return -1;
652 }
653 }
654 }
655
656 if (!tty[0])
657 return 0;
ed502555 658
659 if (access(console, R_OK|W_OK))
6e590161 660 return 0;
13954cce 661
ed502555 662 if (mount(tty, console, "none", MS_BIND, 0)) {
36eb9bde 663 ERROR("failed to mount the console");
6e590161 664 return -1;
665 }
666
cd54d859
DL
667 INFO("console '%s' mounted to '%s'", tty, console);
668
6e590161 669 return 0;
670}
671
102a5303 672static int setup_cgroup(const char *name, struct lxc_list *cgroups)
576f946d 673{
102a5303
DL
674 struct lxc_list *iterator;
675 struct lxc_cgroup *cg;
88329c69 676 int ret = -1;
6f4a3756 677
102a5303
DL
678 if (lxc_list_empty(cgroups))
679 return 0;
6f4a3756 680
102a5303 681 lxc_list_for_each(iterator, cgroups) {
13954cce 682
102a5303 683 cg = iterator->elem;
6f4a3756 684
102a5303 685 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
88329c69 686 goto out;
6f4a3756 687
102a5303 688 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
6f4a3756 689 }
13954cce 690
88329c69 691 ret = 0;
cd54d859 692 INFO("cgroup has been setup");
88329c69
MN
693out:
694 return ret;
576f946d 695}
696
998ac676
RT
697static void parse_mntopt(char *opt, unsigned long *flags, char **data)
698{
699 struct mount_opt *mo;
700
701 /* If opt is found in mount_opt, set or clear flags.
702 * Otherwise append it to data. */
703
704 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
705 if (!strncmp(opt, mo->name, strlen(mo->name))) {
706 if (mo->clear)
707 *flags &= ~mo->flag;
708 else
709 *flags |= mo->flag;
710 return;
711 }
712 }
713
714 if (strlen(*data))
715 strcat(*data, ",");
716 strcat(*data, opt);
717}
718
719static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
720 char **mntdata)
721{
722 char *s, *data;
723 char *p, *saveptr = NULL;
724
725 if (!mntent->mnt_opts)
726 return 0;
727
728 s = strdup(mntent->mnt_opts);
729 if (!s) {
36eb9bde 730 SYSERROR("failed to allocate memory");
998ac676
RT
731 return -1;
732 }
733
734 data = malloc(strlen(s) + 1);
735 if (!data) {
36eb9bde 736 SYSERROR("failed to allocate memory");
998ac676
RT
737 free(s);
738 return -1;
739 }
740 *data = 0;
741
742 for (p = strtok_r(s, ",", &saveptr); p != NULL;
743 p = strtok_r(NULL, ",", &saveptr))
744 parse_mntopt(p, mntflags, &data);
745
746 if (*data)
747 *mntdata = data;
748 else
749 free(data);
750 free(s);
751
752 return 0;
753}
754
e7938e9e 755static int mount_file_entries(FILE *file)
0ad19a3f 756{
0ad19a3f 757 struct mntent *mntent;
0ad19a3f 758 int ret = -1;
998ac676
RT
759 unsigned long mntflags;
760 char *mntdata;
0ad19a3f 761
998ac676 762 while ((mntent = getmntent(file))) {
1bc60a65 763
998ac676
RT
764 mntflags = 0;
765 mntdata = NULL;
766 if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
36eb9bde 767 ERROR("failed to parse mount option '%s'",
998ac676
RT
768 mntent->mnt_opts);
769 goto out;
770 }
0ad19a3f 771
772 if (mount(mntent->mnt_fsname, mntent->mnt_dir,
998ac676 773 mntent->mnt_type, mntflags, mntdata)) {
36eb9bde 774 SYSERROR("failed to mount '%s' on '%s'",
0ad19a3f 775 mntent->mnt_fsname, mntent->mnt_dir);
776 goto out;
777 }
998ac676 778
cd54d859
DL
779 DEBUG("mounted %s on %s, type %s", mntent->mnt_fsname,
780 mntent->mnt_dir, mntent->mnt_type);
781
998ac676 782 free(mntdata);
0ad19a3f 783 }
cd54d859 784
0ad19a3f 785 ret = 0;
cd54d859
DL
786
787 INFO("mount points have been setup");
0ad19a3f 788out:
e7938e9e
MN
789 return ret;
790}
791
792static int setup_mount(const char *fstab)
793{
794 FILE *file;
795 int ret;
796
797 if (!fstab)
798 return 0;
799
800 file = setmntent(fstab, "r");
801 if (!file) {
802 SYSERROR("failed to use '%s'", fstab);
803 return -1;
804 }
805
806 ret = mount_file_entries(file);
807
0ad19a3f 808 endmntent(file);
809 return ret;
810}
811
e7938e9e
MN
812static int setup_mount_entries(struct lxc_list *mount)
813{
814 FILE *file;
815 struct lxc_list *iterator;
816 char *mount_entry;
817 int ret;
818
819 file = tmpfile();
820 if (!file) {
821 ERROR("tmpfile error: %m");
822 return -1;
823 }
824
825 lxc_list_for_each(iterator, mount) {
826 mount_entry = iterator->elem;
1d6b1976 827 fprintf(file, "%s\n", mount_entry);
e7938e9e
MN
828 }
829
830 rewind(file);
831
832 ret = mount_file_entries(file);
833
834 fclose(file);
835 return ret;
836}
837
81810dd1
DL
838static int setup_caps(struct lxc_list *caps)
839{
840 struct lxc_list *iterator;
841 char *drop_entry;
842 int i, capid;
843
844 lxc_list_for_each(iterator, caps) {
845
846 drop_entry = iterator->elem;
847
848 capid = -1;
849
850 for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
851
852 if (strcmp(drop_entry, caps_opt[i].name))
853 continue;
854
855 capid = caps_opt[i].value;
856 break;
857 }
858
859 if (capid < 0) {
1e11be34
DL
860 ERROR("unknown capability %s", drop_entry);
861 return -1;
81810dd1
DL
862 }
863
864 DEBUG("drop capability '%s' (%d)", drop_entry, capid);
865
866 if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
867 SYSERROR("failed to remove %s capability", drop_entry);
868 return -1;
869 }
870
871 }
872
873 DEBUG("capabilities has been setup");
874
875 return 0;
876}
877
0ad19a3f 878static int setup_hw_addr(char *hwaddr, const char *ifname)
879{
880 struct sockaddr sockaddr;
881 struct ifreq ifr;
882 int ret, fd;
883
884 if (lxc_convert_mac(hwaddr, &sockaddr)) {
3ab87b66 885 ERROR("conversion has failed");
0ad19a3f 886 return -1;
887 }
888
889 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
890 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
891
892 fd = socket(AF_INET, SOCK_DGRAM, 0);
893 if (fd < 0) {
3ab87b66 894 ERROR("socket failure : %s", strerror(errno));
0ad19a3f 895 return -1;
896 }
897
898 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
899 close(fd);
900 if (ret)
3ab87b66 901 ERROR("ioctl failure : %s", strerror(errno));
0ad19a3f 902
cd54d859
DL
903 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
904
0ad19a3f 905 return ret;
906}
907
82d5ae15 908static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 909{
82d5ae15
DL
910 struct lxc_list *iterator;
911 struct lxc_inetdev *inetdev;
0ad19a3f 912
82d5ae15
DL
913 lxc_list_for_each(iterator, ip) {
914
915 inetdev = iterator->elem;
916
4bf1968d
DL
917 if (lxc_ip_addr_add(AF_INET, ifindex,
918 &inetdev->addr, inetdev->prefix)) {
82d5ae15
DL
919 return -1;
920 }
921 }
922
923 return 0;
0ad19a3f 924}
925
82d5ae15 926static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 927{
82d5ae15 928 struct lxc_list *iterator;
7fa9074f 929 struct lxc_inet6dev *inet6dev;
0ad19a3f 930
82d5ae15
DL
931 lxc_list_for_each(iterator, ip) {
932
933 inet6dev = iterator->elem;
934
4bf1968d
DL
935 if (lxc_ip_addr_add(AF_INET6, ifindex,
936 & inet6dev->addr, inet6dev->prefix))
82d5ae15 937 return -1;
82d5ae15
DL
938 }
939
940 return 0;
0ad19a3f 941}
942
82d5ae15 943static int setup_netdev(struct lxc_netdev *netdev)
0ad19a3f 944{
0ad19a3f 945 char ifname[IFNAMSIZ];
0ad19a3f 946 char *current_ifname = ifname;
0ad19a3f 947
82d5ae15
DL
948 /* empty network namespace */
949 if (!netdev->ifindex) {
950 if (netdev->flags | IFF_UP) {
951 if (lxc_device_up("lo")) {
952 ERROR("failed to set the loopback up");
953 return -1;
954 }
955 return 0;
956 }
0ad19a3f 957 }
13954cce 958
82d5ae15
DL
959 /* retrieve the name of the interface */
960 if (!if_indextoname(netdev->ifindex, current_ifname)) {
36eb9bde 961 ERROR("no interface corresponding to index '%d'",
82d5ae15 962 netdev->ifindex);
0ad19a3f 963 return -1;
964 }
13954cce 965
018ef520 966 /* default: let the system to choose one interface name */
9d083402
MT
967 if (!netdev->name)
968 netdev->name = "eth%d";
018ef520 969
82d5ae15 970 /* rename the interface name */
9d083402 971 if (lxc_device_rename(ifname, netdev->name)) {
018ef520
DL
972 ERROR("failed to rename %s->%s", ifname, current_ifname);
973 return -1;
974 }
975
976 /* Re-read the name of the interface because its name has changed
977 * and would be automatically allocated by the system
978 */
82d5ae15 979 if (!if_indextoname(netdev->ifindex, current_ifname)) {
018ef520 980 ERROR("no interface corresponding to index '%d'",
82d5ae15 981 netdev->ifindex);
018ef520 982 return -1;
0ad19a3f 983 }
984
82d5ae15
DL
985 /* set a mac address */
986 if (netdev->hwaddr) {
987 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
36eb9bde 988 ERROR("failed to setup hw address for '%s'",
82d5ae15 989 current_ifname);
0ad19a3f 990 return -1;
991 }
992 }
993
82d5ae15
DL
994 /* setup ipv4 addresses on the interface */
995 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
36eb9bde 996 ERROR("failed to setup ip addresses for '%s'",
0ad19a3f 997 ifname);
998 return -1;
999 }
1000
82d5ae15
DL
1001 /* setup ipv6 addresses on the interface */
1002 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
36eb9bde 1003 ERROR("failed to setup ipv6 addresses for '%s'",
0ad19a3f 1004 ifname);
1005 return -1;
1006 }
1007
82d5ae15
DL
1008 /* set the network device up */
1009 if (netdev->flags | IFF_UP) {
497353b6 1010 if (lxc_device_up(current_ifname)) {
36eb9bde 1011 ERROR("failed to set '%s' up", current_ifname);
0ad19a3f 1012 return -1;
1013 }
1014
1015 /* the network is up, make the loopback up too */
497353b6 1016 if (lxc_device_up("lo")) {
36eb9bde 1017 ERROR("failed to set the loopback up");
0ad19a3f 1018 return -1;
1019 }
1020 }
1021
cd54d859
DL
1022 DEBUG("'%s' has been setup", current_ifname);
1023
0ad19a3f 1024 return 0;
1025}
1026
5f4535a3 1027static int setup_network(struct lxc_list *network)
0ad19a3f 1028{
82d5ae15 1029 struct lxc_list *iterator;
82d5ae15 1030 struct lxc_netdev *netdev;
0ad19a3f 1031
5f4535a3 1032 lxc_list_for_each(iterator, network) {
cd54d859 1033
5f4535a3 1034 netdev = iterator->elem;
82d5ae15
DL
1035
1036 if (setup_netdev(netdev)) {
1037 ERROR("failed to setup netdev");
1038 return -1;
1039 }
1040 }
cd54d859 1041
5f4535a3
DL
1042 if (!lxc_list_empty(network))
1043 INFO("network has been setup");
cd54d859
DL
1044
1045 return 0;
0ad19a3f 1046}
1047
7b379ab3 1048struct lxc_conf *lxc_conf_init(void)
089cd8b8 1049{
7b379ab3
MN
1050 struct lxc_conf *new;
1051
1052 new = malloc(sizeof(*new));
1053 if (!new) {
1054 ERROR("lxc_conf_init : %m");
1055 return NULL;
1056 }
1057 memset(new, 0, sizeof(*new));
1058
1059 new->rootfs = NULL;
bf601689 1060 new->pivotdir = NULL;
7b379ab3
MN
1061 new->fstab = NULL;
1062 new->utsname = NULL;
1063 new->tty = 0;
1064 new->pts = 0;
1065 new->console[0] = '\0';
1066 lxc_list_init(&new->cgroup);
1067 lxc_list_init(&new->network);
1068 lxc_list_init(&new->mount_list);
81810dd1 1069 lxc_list_init(&new->caps);
7b379ab3
MN
1070
1071 return new;
089cd8b8
DL
1072}
1073
82d5ae15 1074static int instanciate_veth(struct lxc_netdev *netdev)
0ad19a3f 1075{
8634bc19 1076 char veth1buf[IFNAMSIZ], *veth1;
82d5ae15 1077 char veth2[IFNAMSIZ];
13954cce 1078
e892973e
DL
1079 if (netdev->priv.veth_attr.pair)
1080 veth1 = netdev->priv.veth_attr.pair;
8634bc19
MT
1081 else {
1082 snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
1083 mktemp(veth1buf);
1084 veth1 = veth1buf;
1085 }
82d5ae15 1086
8634bc19 1087 snprintf(veth2, sizeof(veth2), "vethXXXXXX");
82d5ae15
DL
1088 mktemp(veth2);
1089
1090 if (!strlen(veth1) || !strlen(veth2)) {
1091 ERROR("failed to allocate a temporary name");
1092 return -1;
0ad19a3f 1093 }
1094
eb14c10a 1095 if (lxc_veth_create(veth1, veth2)) {
734915ac 1096 ERROR("failed to create %s-%s", veth1, veth2);
6ab9ab6d 1097 return -1;
0ad19a3f 1098 }
13954cce 1099
82d5ae15 1100 if (netdev->mtu) {
6ab9ab6d
MT
1101 if (lxc_device_set_mtu(veth1, atoi(netdev->mtu)) ||
1102 lxc_device_set_mtu(veth2, atoi(netdev->mtu))) {
1103 ERROR("failed to set mtu '%s' for %s-%s",
1104 netdev->mtu, veth1, veth2);
eb14c10a 1105 goto out_delete;
75d09f83
DL
1106 }
1107 }
1108
734915ac 1109 if (netdev->link && lxc_bridge_attach(netdev->link, veth1)) {
36eb9bde 1110 ERROR("failed to attach '%s' to the bridge '%s'",
9d083402 1111 veth1, netdev->link);
eb14c10a
DL
1112 goto out_delete;
1113 }
1114
82d5ae15
DL
1115 netdev->ifindex = if_nametoindex(veth2);
1116 if (!netdev->ifindex) {
36eb9bde 1117 ERROR("failed to retrieve the index for %s", veth2);
eb14c10a
DL
1118 goto out_delete;
1119 }
1120
82d5ae15 1121 if (netdev->flags & IFF_UP) {
497353b6 1122 if (lxc_device_up(veth1)) {
36eb9bde 1123 ERROR("failed to set %s up", veth1);
eb14c10a 1124 goto out_delete;
0ad19a3f 1125 }
1126 }
1127
82d5ae15
DL
1128 DEBUG("instanciated veth '%s/%s', index is '%d'",
1129 veth1, veth2, netdev->ifindex);
1130
6ab9ab6d 1131 return 0;
eb14c10a
DL
1132
1133out_delete:
1134 lxc_device_delete(veth1);
6ab9ab6d 1135 return -1;
13954cce 1136}
d957ae2d 1137
82d5ae15 1138static int instanciate_macvlan(struct lxc_netdev *netdev)
0ad19a3f 1139{
82d5ae15 1140 char peer[IFNAMSIZ];
d957ae2d
MT
1141
1142 if (!netdev->link) {
1143 ERROR("no link specified for macvlan netdev");
1144 return -1;
1145 }
13954cce 1146
82d5ae15 1147 snprintf(peer, sizeof(peer), "mcXXXXXX");
22ebac19 1148
82d5ae15
DL
1149 mktemp(peer);
1150
1151 if (!strlen(peer)) {
1152 ERROR("failed to make a temporary name");
1153 return -1;
0ad19a3f 1154 }
1155
e892973e
DL
1156 if (lxc_macvlan_create(netdev->link, peer,
1157 netdev->priv.macvlan_attr.mode)) {
36eb9bde 1158 ERROR("failed to create macvlan interface '%s' on '%s'",
9d083402 1159 peer, netdev->link);
d957ae2d 1160 return -1;
0ad19a3f 1161 }
1162
82d5ae15
DL
1163 netdev->ifindex = if_nametoindex(peer);
1164 if (!netdev->ifindex) {
36eb9bde 1165 ERROR("failed to retrieve the index for %s", peer);
d957ae2d
MT
1166 lxc_device_delete(peer);
1167 return -1;
22ebac19 1168 }
1169
e892973e
DL
1170 DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
1171 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
0ad19a3f 1172
d957ae2d 1173 return 0;
0ad19a3f 1174}
1175
26c39028
JHS
1176/* XXX: merge with instanciate_macvlan */
1177static int instanciate_vlan(struct lxc_netdev *netdev)
1178{
1179 char peer[IFNAMSIZ];
1180
1181 if (!netdev->link) {
1182 ERROR("no link specified for vlan netdev");
1183 return -1;
1184 }
1185
e892973e 1186 snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
26c39028 1187
f6cc1de1 1188 if (lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid)) {
26c39028
JHS
1189 ERROR("failed to create vlan interface '%s' on '%s'",
1190 peer, netdev->link);
1191 return -1;
1192 }
1193
1194 netdev->ifindex = if_nametoindex(peer);
1195 if (!netdev->ifindex) {
1196 ERROR("failed to retrieve the ifindex for %s", peer);
1197 lxc_device_delete(peer);
1198 return -1;
1199 }
1200
e892973e
DL
1201 DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
1202 netdev->ifindex);
1203
26c39028
JHS
1204 return 0;
1205}
1206
82d5ae15 1207static int instanciate_phys(struct lxc_netdev *netdev)
0ad19a3f 1208{
9d083402 1209 netdev->ifindex = if_nametoindex(netdev->link);
82d5ae15 1210 if (!netdev->ifindex) {
9d083402 1211 ERROR("failed to retrieve the index for %s", netdev->link);
0ad19a3f 1212 return -1;
1213 }
1214
82d5ae15 1215 return 0;
0ad19a3f 1216}
1217
82d5ae15 1218static int instanciate_empty(struct lxc_netdev *netdev)
0ad19a3f 1219{
82d5ae15
DL
1220 netdev->ifindex = 0;
1221 return 0;
0ad19a3f 1222}
1223
5f4535a3 1224int lxc_create_network(struct lxc_list *network)
0ad19a3f 1225{
82d5ae15 1226 struct lxc_list *iterator;
82d5ae15 1227 struct lxc_netdev *netdev;
0ad19a3f 1228
5f4535a3 1229 lxc_list_for_each(iterator, network) {
0ad19a3f 1230
5f4535a3 1231 netdev = iterator->elem;
13954cce 1232
5f4535a3 1233 if (netdev->type < 0 || netdev->type > MAXCONFTYPE) {
82d5ae15 1234 ERROR("invalid network configuration type '%d'",
5f4535a3 1235 netdev->type);
82d5ae15
DL
1236 return -1;
1237 }
0ad19a3f 1238
5f4535a3 1239 if (netdev_conf[netdev->type](netdev)) {
82d5ae15
DL
1240 ERROR("failed to create netdev");
1241 return -1;
1242 }
0ad19a3f 1243 }
1244
1245 return 0;
1246}
1247
5f4535a3 1248int lxc_assign_network(struct lxc_list *network, pid_t pid)
0ad19a3f 1249{
82d5ae15 1250 struct lxc_list *iterator;
82d5ae15 1251 struct lxc_netdev *netdev;
0ad19a3f 1252
5f4535a3 1253 lxc_list_for_each(iterator, network) {
82d5ae15 1254
5f4535a3 1255 netdev = iterator->elem;
82d5ae15
DL
1256
1257 if (lxc_device_move(netdev->ifindex, pid)) {
1258 ERROR("failed to move '%s' to the container",
9d083402 1259 netdev->link);
82d5ae15
DL
1260 return -1;
1261 }
1262
9d083402 1263 DEBUG("move '%s' to '%d'", netdev->link, pid);
0ad19a3f 1264 }
1265
1266 return 0;
1267}
1268
5e4a62bf 1269int lxc_create_tty(const char *name, struct lxc_conf *conf)
b0a33c1e 1270{
5e4a62bf 1271 struct lxc_tty_info *tty_info = &conf->tty_info;
985d15b1 1272 int i;
b0a33c1e 1273
5e4a62bf
DL
1274 /* no tty in the configuration */
1275 if (!conf->tty)
b0a33c1e 1276 return 0;
1277
13954cce 1278 tty_info->pty_info =
e4e7d59d 1279 malloc(sizeof(*tty_info->pty_info)*conf->tty);
b0a33c1e 1280 if (!tty_info->pty_info) {
36eb9bde 1281 SYSERROR("failed to allocate pty_info");
985d15b1 1282 return -1;
b0a33c1e 1283 }
1284
985d15b1 1285 for (i = 0; i < conf->tty; i++) {
13954cce 1286
b0a33c1e 1287 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1288
13954cce 1289 if (openpty(&pty_info->master, &pty_info->slave,
b0a33c1e 1290 pty_info->name, NULL, NULL)) {
36eb9bde 1291 SYSERROR("failed to create pty #%d", i);
985d15b1
MT
1292 tty_info->nbtty = i;
1293 lxc_delete_tty(tty_info);
1294 return -1;
b0a33c1e 1295 }
1296
b035ad62
MS
1297 /* Prevent leaking the file descriptors to the container */
1298 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
1299 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
1300
b0a33c1e 1301 pty_info->busy = 0;
1302 }
1303
985d15b1 1304 tty_info->nbtty = conf->tty;
1ac470c0
DL
1305
1306 INFO("tty's configured");
1307
985d15b1 1308 return 0;
b0a33c1e 1309}
1310
1311void lxc_delete_tty(struct lxc_tty_info *tty_info)
1312{
1313 int i;
1314
1315 for (i = 0; i < tty_info->nbtty; i++) {
1316 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1317
1318 close(pty_info->master);
1319 close(pty_info->slave);
1320 }
1321
1322 free(tty_info->pty_info);
1323 tty_info->nbtty = 0;
1324}
1325
571e6ec8 1326int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
0ad19a3f 1327{
571e6ec8 1328 if (setup_utsname(lxc_conf->utsname)) {
36eb9bde 1329 ERROR("failed to setup the utsname for '%s'", name);
95b5ffaf 1330 return -1;
0ad19a3f 1331 }
1332
5f4535a3 1333 if (setup_network(&lxc_conf->network)) {
36eb9bde 1334 ERROR("failed to setup the network for '%s'", name);
95b5ffaf 1335 return -1;
0ad19a3f 1336 }
1337
571e6ec8 1338 if (setup_cgroup(name, &lxc_conf->cgroup)) {
36eb9bde 1339 ERROR("failed to setup the cgroups for '%s'", name);
95b5ffaf 1340 return -1;
0ad19a3f 1341 }
1342
571e6ec8 1343 if (setup_mount(lxc_conf->fstab)) {
36eb9bde 1344 ERROR("failed to setup the mounts for '%s'", name);
95b5ffaf 1345 return -1;
576f946d 1346 }
1347
e7938e9e
MN
1348 if (setup_mount_entries(&lxc_conf->mount_list)) {
1349 ERROR("failed to setup the mount entries for '%s'", name);
1350 return -1;
1351 }
1352
571e6ec8 1353 if (setup_console(lxc_conf->rootfs, lxc_conf->console)) {
36eb9bde 1354 ERROR("failed to setup the console for '%s'", name);
95b5ffaf 1355 return -1;
6e590161 1356 }
1357
571e6ec8 1358 if (setup_tty(lxc_conf->rootfs, &lxc_conf->tty_info)) {
36eb9bde 1359 ERROR("failed to setup the ttys for '%s'", name);
95b5ffaf 1360 return -1;
b0a33c1e 1361 }
1362
bf601689 1363 if (setup_rootfs(lxc_conf->rootfs, lxc_conf->pivotdir)) {
36eb9bde 1364 ERROR("failed to set rootfs for '%s'", name);
95b5ffaf 1365 return -1;
ed502555 1366 }
1367
571e6ec8 1368 if (setup_pts(lxc_conf->pts)) {
36eb9bde 1369 ERROR("failed to setup the new pts instance");
95b5ffaf 1370 return -1;
3c26f34e 1371 }
1372
81810dd1
DL
1373 if (setup_caps(&lxc_conf->caps)) {
1374 ERROR("failed to drop capabilities");
1375 return -1;
1376 }
1377
cd54d859
DL
1378 NOTICE("'%s' is setup.", name);
1379
0ad19a3f 1380 return 0;
1381}