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