]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/conf.c
compilation warning in confile.c
[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
541 if (errno != EBUSY) {
542 SYSERROR("failed to umount '%s'", (char *)iterator->elem);
543 return -1;
544 }
545
546 still_mounted++;
547 }
548 } while (still_mounted > 0 && still_mounted != last_still_mounted);
549
550 if (still_mounted) {
551 ERROR("could not umount %d mounts", still_mounted);
552 return -1;
553 }
554
555 /* umount old root fs */
556 if (umount(pivotdir)) {
557 SYSERROR("could not unmount old rootfs");
558 return -1;
559 }
560 DEBUG("umounted '%s'", pivotdir);
561
562 /* remove temporary mount point */
563 if (pivotdir_is_temp) {
564 if (rmdir(pivotdir)) {
565 SYSERROR("can't remove temporary mountpoint");
566 return -1;
567 }
568
569 }
570
571 INFO("pivoted to '%s'", rootfs);
572 return 0;
573}
574
575static int setup_rootfs(const char *rootfs, const char *pivotdir)
0ad19a3f 576{
c69bd12f
DL
577 char *tmpname;
578 int ret = -1;
0ad19a3f 579
c69bd12f
DL
580 if (!rootfs)
581 return 0;
0ad19a3f 582
c69bd12f
DL
583 tmpname = tempnam("/tmp", "lxc-rootfs");
584 if (!tmpname) {
585 SYSERROR("failed to generate temporary name");
c3f0a28c 586 return -1;
587 }
0ad19a3f 588
c69bd12f
DL
589 if (mkdir(tmpname, 0700)) {
590 SYSERROR("failed to create temporary directory '%s'", tmpname);
591 return -1;
592 }
593
594 if (mount(rootfs, tmpname, "none", MS_BIND|MS_REC, NULL)) {
595 SYSERROR("failed to mount '%s'->'%s'", rootfs, tmpname);
596 goto out;
597 }
598
bf601689
MH
599 if (setup_rootfs_pivot_root(tmpname, pivotdir)) {
600 ERROR("failed to pivot_root to '%s'", rootfs);
c69bd12f
DL
601 goto out;
602 }
603
c69bd12f
DL
604 ret = 0;
605out:
606 rmdir(tmpname);
607 return ret;
0ad19a3f 608}
609
d852c78c 610static int setup_pts(int pts)
3c26f34e 611{
d852c78c
DL
612 if (!pts)
613 return 0;
3c26f34e 614
615 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
36eb9bde 616 SYSERROR("failed to umount 'dev/pts'");
3c26f34e 617 return -1;
618 }
619
d852c78c 620 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance")) {
36eb9bde 621 SYSERROR("failed to mount a new instance of '/dev/pts'");
3c26f34e 622 return -1;
623 }
624
625 if (chmod("/dev/pts/ptmx", 0666)) {
36eb9bde 626 SYSERROR("failed to set permission for '/dev/pts/ptmx'");
3c26f34e 627 return -1;
628 }
629
630 if (access("/dev/ptmx", F_OK)) {
631 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
632 goto out;
36eb9bde 633 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 634 return -1;
635 }
636
637 /* fallback here, /dev/pts/ptmx exists just mount bind */
638 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
36eb9bde 639 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
3c26f34e 640 return -1;
641 }
cd54d859
DL
642
643 INFO("created new pts instance");
d852c78c 644
3c26f34e 645out:
646 return 0;
647}
648
52e35957 649static int setup_console(const char *rootfs, const char *tty)
6e590161 650{
ed502555 651 char console[MAXPATHLEN];
652
52e35957
DL
653 snprintf(console, sizeof(console), "%s/dev/console",
654 rootfs ? rootfs : "");
655
656 /* we have the rootfs with /dev/console but no tty
657 * to be used as console, let's remap /dev/console
658 * to /dev/null to avoid to log to the system console
659 */
660 if (rootfs && !tty[0]) {
661
662 if (!access(console, F_OK)) {
663
664 if (mount("/dev/null", console, "none", MS_BIND, 0)) {
665 SYSERROR("failed to mount '/dev/null'->'%s'",
666 console);
667 return -1;
668 }
669 }
670 }
671
672 if (!tty[0])
673 return 0;
ed502555 674
675 if (access(console, R_OK|W_OK))
6e590161 676 return 0;
13954cce 677
ed502555 678 if (mount(tty, console, "none", MS_BIND, 0)) {
36eb9bde 679 ERROR("failed to mount the console");
6e590161 680 return -1;
681 }
682
cd54d859
DL
683 INFO("console '%s' mounted to '%s'", tty, console);
684
6e590161 685 return 0;
686}
687
102a5303 688static int setup_cgroup(const char *name, struct lxc_list *cgroups)
576f946d 689{
102a5303
DL
690 struct lxc_list *iterator;
691 struct lxc_cgroup *cg;
88329c69 692 int ret = -1;
6f4a3756 693
102a5303
DL
694 if (lxc_list_empty(cgroups))
695 return 0;
6f4a3756 696
102a5303 697 lxc_list_for_each(iterator, cgroups) {
13954cce 698
102a5303 699 cg = iterator->elem;
6f4a3756 700
102a5303 701 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
88329c69 702 goto out;
6f4a3756 703
102a5303 704 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
6f4a3756 705 }
13954cce 706
88329c69 707 ret = 0;
cd54d859 708 INFO("cgroup has been setup");
88329c69
MN
709out:
710 return ret;
576f946d 711}
712
998ac676
RT
713static void parse_mntopt(char *opt, unsigned long *flags, char **data)
714{
715 struct mount_opt *mo;
716
717 /* If opt is found in mount_opt, set or clear flags.
718 * Otherwise append it to data. */
719
720 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
721 if (!strncmp(opt, mo->name, strlen(mo->name))) {
722 if (mo->clear)
723 *flags &= ~mo->flag;
724 else
725 *flags |= mo->flag;
726 return;
727 }
728 }
729
730 if (strlen(*data))
731 strcat(*data, ",");
732 strcat(*data, opt);
733}
734
735static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
736 char **mntdata)
737{
738 char *s, *data;
739 char *p, *saveptr = NULL;
740
741 if (!mntent->mnt_opts)
742 return 0;
743
744 s = strdup(mntent->mnt_opts);
745 if (!s) {
36eb9bde 746 SYSERROR("failed to allocate memory");
998ac676
RT
747 return -1;
748 }
749
750 data = malloc(strlen(s) + 1);
751 if (!data) {
36eb9bde 752 SYSERROR("failed to allocate memory");
998ac676
RT
753 free(s);
754 return -1;
755 }
756 *data = 0;
757
758 for (p = strtok_r(s, ",", &saveptr); p != NULL;
759 p = strtok_r(NULL, ",", &saveptr))
760 parse_mntopt(p, mntflags, &data);
761
762 if (*data)
763 *mntdata = data;
764 else
765 free(data);
766 free(s);
767
768 return 0;
769}
770
e7938e9e 771static int mount_file_entries(FILE *file)
0ad19a3f 772{
0ad19a3f 773 struct mntent *mntent;
0ad19a3f 774 int ret = -1;
998ac676
RT
775 unsigned long mntflags;
776 char *mntdata;
0ad19a3f 777
998ac676 778 while ((mntent = getmntent(file))) {
1bc60a65 779
998ac676
RT
780 mntflags = 0;
781 mntdata = NULL;
782 if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
36eb9bde 783 ERROR("failed to parse mount option '%s'",
998ac676
RT
784 mntent->mnt_opts);
785 goto out;
786 }
0ad19a3f 787
788 if (mount(mntent->mnt_fsname, mntent->mnt_dir,
998ac676 789 mntent->mnt_type, mntflags, mntdata)) {
36eb9bde 790 SYSERROR("failed to mount '%s' on '%s'",
0ad19a3f 791 mntent->mnt_fsname, mntent->mnt_dir);
792 goto out;
793 }
998ac676 794
cd54d859
DL
795 DEBUG("mounted %s on %s, type %s", mntent->mnt_fsname,
796 mntent->mnt_dir, mntent->mnt_type);
797
998ac676 798 free(mntdata);
0ad19a3f 799 }
cd54d859 800
0ad19a3f 801 ret = 0;
cd54d859
DL
802
803 INFO("mount points have been setup");
0ad19a3f 804out:
e7938e9e
MN
805 return ret;
806}
807
808static int setup_mount(const char *fstab)
809{
810 FILE *file;
811 int ret;
812
813 if (!fstab)
814 return 0;
815
816 file = setmntent(fstab, "r");
817 if (!file) {
818 SYSERROR("failed to use '%s'", fstab);
819 return -1;
820 }
821
822 ret = mount_file_entries(file);
823
0ad19a3f 824 endmntent(file);
825 return ret;
826}
827
e7938e9e
MN
828static int setup_mount_entries(struct lxc_list *mount)
829{
830 FILE *file;
831 struct lxc_list *iterator;
832 char *mount_entry;
833 int ret;
834
835 file = tmpfile();
836 if (!file) {
837 ERROR("tmpfile error: %m");
838 return -1;
839 }
840
841 lxc_list_for_each(iterator, mount) {
842 mount_entry = iterator->elem;
1d6b1976 843 fprintf(file, "%s\n", mount_entry);
e7938e9e
MN
844 }
845
846 rewind(file);
847
848 ret = mount_file_entries(file);
849
850 fclose(file);
851 return ret;
852}
853
81810dd1
DL
854static int setup_caps(struct lxc_list *caps)
855{
856 struct lxc_list *iterator;
857 char *drop_entry;
858 int i, capid;
859
860 lxc_list_for_each(iterator, caps) {
861
862 drop_entry = iterator->elem;
863
864 capid = -1;
865
866 for (i = 0; i < sizeof(caps_opt)/sizeof(caps_opt[0]); i++) {
867
868 if (strcmp(drop_entry, caps_opt[i].name))
869 continue;
870
871 capid = caps_opt[i].value;
872 break;
873 }
874
875 if (capid < 0) {
1e11be34
DL
876 ERROR("unknown capability %s", drop_entry);
877 return -1;
81810dd1
DL
878 }
879
880 DEBUG("drop capability '%s' (%d)", drop_entry, capid);
881
882 if (prctl(PR_CAPBSET_DROP, capid, 0, 0, 0)) {
883 SYSERROR("failed to remove %s capability", drop_entry);
884 return -1;
885 }
886
887 }
888
889 DEBUG("capabilities has been setup");
890
891 return 0;
892}
893
0ad19a3f 894static int setup_hw_addr(char *hwaddr, const char *ifname)
895{
896 struct sockaddr sockaddr;
897 struct ifreq ifr;
898 int ret, fd;
899
900 if (lxc_convert_mac(hwaddr, &sockaddr)) {
3ab87b66 901 ERROR("conversion has failed");
0ad19a3f 902 return -1;
903 }
904
905 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
906 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
907
908 fd = socket(AF_INET, SOCK_DGRAM, 0);
909 if (fd < 0) {
3ab87b66 910 ERROR("socket failure : %s", strerror(errno));
0ad19a3f 911 return -1;
912 }
913
914 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
915 close(fd);
916 if (ret)
3ab87b66 917 ERROR("ioctl failure : %s", strerror(errno));
0ad19a3f 918
cd54d859
DL
919 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
920
0ad19a3f 921 return ret;
922}
923
82d5ae15 924static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 925{
82d5ae15
DL
926 struct lxc_list *iterator;
927 struct lxc_inetdev *inetdev;
0ad19a3f 928
82d5ae15
DL
929 lxc_list_for_each(iterator, ip) {
930
931 inetdev = iterator->elem;
932
4bf1968d
DL
933 if (lxc_ip_addr_add(AF_INET, ifindex,
934 &inetdev->addr, inetdev->prefix)) {
82d5ae15
DL
935 return -1;
936 }
937 }
938
939 return 0;
0ad19a3f 940}
941
82d5ae15 942static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
0ad19a3f 943{
82d5ae15 944 struct lxc_list *iterator;
7fa9074f 945 struct lxc_inet6dev *inet6dev;
0ad19a3f 946
82d5ae15
DL
947 lxc_list_for_each(iterator, ip) {
948
949 inet6dev = iterator->elem;
950
4bf1968d
DL
951 if (lxc_ip_addr_add(AF_INET6, ifindex,
952 & inet6dev->addr, inet6dev->prefix))
82d5ae15 953 return -1;
82d5ae15
DL
954 }
955
956 return 0;
0ad19a3f 957}
958
82d5ae15 959static int setup_netdev(struct lxc_netdev *netdev)
0ad19a3f 960{
0ad19a3f 961 char ifname[IFNAMSIZ];
0ad19a3f 962 char *current_ifname = ifname;
0ad19a3f 963
82d5ae15
DL
964 /* empty network namespace */
965 if (!netdev->ifindex) {
966 if (netdev->flags | IFF_UP) {
967 if (lxc_device_up("lo")) {
968 ERROR("failed to set the loopback up");
969 return -1;
970 }
971 return 0;
972 }
0ad19a3f 973 }
13954cce 974
82d5ae15
DL
975 /* retrieve the name of the interface */
976 if (!if_indextoname(netdev->ifindex, current_ifname)) {
36eb9bde 977 ERROR("no interface corresponding to index '%d'",
82d5ae15 978 netdev->ifindex);
0ad19a3f 979 return -1;
980 }
13954cce 981
018ef520 982 /* default: let the system to choose one interface name */
9d083402
MT
983 if (!netdev->name)
984 netdev->name = "eth%d";
018ef520 985
82d5ae15 986 /* rename the interface name */
9d083402 987 if (lxc_device_rename(ifname, netdev->name)) {
018ef520
DL
988 ERROR("failed to rename %s->%s", ifname, current_ifname);
989 return -1;
990 }
991
992 /* Re-read the name of the interface because its name has changed
993 * and would be automatically allocated by the system
994 */
82d5ae15 995 if (!if_indextoname(netdev->ifindex, current_ifname)) {
018ef520 996 ERROR("no interface corresponding to index '%d'",
82d5ae15 997 netdev->ifindex);
018ef520 998 return -1;
0ad19a3f 999 }
1000
82d5ae15
DL
1001 /* set a mac address */
1002 if (netdev->hwaddr) {
1003 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
36eb9bde 1004 ERROR("failed to setup hw address for '%s'",
82d5ae15 1005 current_ifname);
0ad19a3f 1006 return -1;
1007 }
1008 }
1009
82d5ae15
DL
1010 /* setup ipv4 addresses on the interface */
1011 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
36eb9bde 1012 ERROR("failed to setup ip addresses for '%s'",
0ad19a3f 1013 ifname);
1014 return -1;
1015 }
1016
82d5ae15
DL
1017 /* setup ipv6 addresses on the interface */
1018 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
36eb9bde 1019 ERROR("failed to setup ipv6 addresses for '%s'",
0ad19a3f 1020 ifname);
1021 return -1;
1022 }
1023
82d5ae15
DL
1024 /* set the network device up */
1025 if (netdev->flags | IFF_UP) {
497353b6 1026 if (lxc_device_up(current_ifname)) {
36eb9bde 1027 ERROR("failed to set '%s' up", current_ifname);
0ad19a3f 1028 return -1;
1029 }
1030
1031 /* the network is up, make the loopback up too */
497353b6 1032 if (lxc_device_up("lo")) {
36eb9bde 1033 ERROR("failed to set the loopback up");
0ad19a3f 1034 return -1;
1035 }
1036 }
1037
cd54d859
DL
1038 DEBUG("'%s' has been setup", current_ifname);
1039
0ad19a3f 1040 return 0;
1041}
1042
5f4535a3 1043static int setup_network(struct lxc_list *network)
0ad19a3f 1044{
82d5ae15 1045 struct lxc_list *iterator;
82d5ae15 1046 struct lxc_netdev *netdev;
0ad19a3f 1047
5f4535a3 1048 lxc_list_for_each(iterator, network) {
cd54d859 1049
5f4535a3 1050 netdev = iterator->elem;
82d5ae15
DL
1051
1052 if (setup_netdev(netdev)) {
1053 ERROR("failed to setup netdev");
1054 return -1;
1055 }
1056 }
cd54d859 1057
5f4535a3
DL
1058 if (!lxc_list_empty(network))
1059 INFO("network has been setup");
cd54d859
DL
1060
1061 return 0;
0ad19a3f 1062}
1063
7b379ab3 1064struct lxc_conf *lxc_conf_init(void)
089cd8b8 1065{
7b379ab3
MN
1066 struct lxc_conf *new;
1067
1068 new = malloc(sizeof(*new));
1069 if (!new) {
1070 ERROR("lxc_conf_init : %m");
1071 return NULL;
1072 }
1073 memset(new, 0, sizeof(*new));
1074
1075 new->rootfs = NULL;
bf601689 1076 new->pivotdir = NULL;
7b379ab3
MN
1077 new->fstab = NULL;
1078 new->utsname = NULL;
1079 new->tty = 0;
1080 new->pts = 0;
1081 new->console[0] = '\0';
1082 lxc_list_init(&new->cgroup);
1083 lxc_list_init(&new->network);
1084 lxc_list_init(&new->mount_list);
81810dd1 1085 lxc_list_init(&new->caps);
7b379ab3
MN
1086
1087 return new;
089cd8b8
DL
1088}
1089
82d5ae15 1090static int instanciate_veth(struct lxc_netdev *netdev)
0ad19a3f 1091{
8634bc19 1092 char veth1buf[IFNAMSIZ], *veth1;
82d5ae15 1093 char veth2[IFNAMSIZ];
13954cce 1094
e892973e
DL
1095 if (netdev->priv.veth_attr.pair)
1096 veth1 = netdev->priv.veth_attr.pair;
8634bc19
MT
1097 else {
1098 snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
1099 mktemp(veth1buf);
1100 veth1 = veth1buf;
1101 }
82d5ae15 1102
8634bc19 1103 snprintf(veth2, sizeof(veth2), "vethXXXXXX");
82d5ae15
DL
1104 mktemp(veth2);
1105
1106 if (!strlen(veth1) || !strlen(veth2)) {
1107 ERROR("failed to allocate a temporary name");
1108 return -1;
0ad19a3f 1109 }
1110
eb14c10a 1111 if (lxc_veth_create(veth1, veth2)) {
734915ac 1112 ERROR("failed to create %s-%s", veth1, veth2);
6ab9ab6d 1113 return -1;
0ad19a3f 1114 }
13954cce 1115
82d5ae15 1116 if (netdev->mtu) {
6ab9ab6d
MT
1117 if (lxc_device_set_mtu(veth1, atoi(netdev->mtu)) ||
1118 lxc_device_set_mtu(veth2, atoi(netdev->mtu))) {
1119 ERROR("failed to set mtu '%s' for %s-%s",
1120 netdev->mtu, veth1, veth2);
eb14c10a 1121 goto out_delete;
75d09f83
DL
1122 }
1123 }
1124
734915ac 1125 if (netdev->link && lxc_bridge_attach(netdev->link, veth1)) {
36eb9bde 1126 ERROR("failed to attach '%s' to the bridge '%s'",
9d083402 1127 veth1, netdev->link);
eb14c10a
DL
1128 goto out_delete;
1129 }
1130
82d5ae15
DL
1131 netdev->ifindex = if_nametoindex(veth2);
1132 if (!netdev->ifindex) {
36eb9bde 1133 ERROR("failed to retrieve the index for %s", veth2);
eb14c10a
DL
1134 goto out_delete;
1135 }
1136
82d5ae15 1137 if (netdev->flags & IFF_UP) {
497353b6 1138 if (lxc_device_up(veth1)) {
36eb9bde 1139 ERROR("failed to set %s up", veth1);
eb14c10a 1140 goto out_delete;
0ad19a3f 1141 }
1142 }
1143
82d5ae15
DL
1144 DEBUG("instanciated veth '%s/%s', index is '%d'",
1145 veth1, veth2, netdev->ifindex);
1146
6ab9ab6d 1147 return 0;
eb14c10a
DL
1148
1149out_delete:
1150 lxc_device_delete(veth1);
6ab9ab6d 1151 return -1;
13954cce 1152}
d957ae2d 1153
82d5ae15 1154static int instanciate_macvlan(struct lxc_netdev *netdev)
0ad19a3f 1155{
82d5ae15 1156 char peer[IFNAMSIZ];
d957ae2d
MT
1157
1158 if (!netdev->link) {
1159 ERROR("no link specified for macvlan netdev");
1160 return -1;
1161 }
13954cce 1162
82d5ae15 1163 snprintf(peer, sizeof(peer), "mcXXXXXX");
22ebac19 1164
82d5ae15
DL
1165 mktemp(peer);
1166
1167 if (!strlen(peer)) {
1168 ERROR("failed to make a temporary name");
1169 return -1;
0ad19a3f 1170 }
1171
e892973e
DL
1172 if (lxc_macvlan_create(netdev->link, peer,
1173 netdev->priv.macvlan_attr.mode)) {
36eb9bde 1174 ERROR("failed to create macvlan interface '%s' on '%s'",
9d083402 1175 peer, netdev->link);
d957ae2d 1176 return -1;
0ad19a3f 1177 }
1178
82d5ae15
DL
1179 netdev->ifindex = if_nametoindex(peer);
1180 if (!netdev->ifindex) {
36eb9bde 1181 ERROR("failed to retrieve the index for %s", peer);
d957ae2d
MT
1182 lxc_device_delete(peer);
1183 return -1;
22ebac19 1184 }
1185
e892973e
DL
1186 DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
1187 peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
0ad19a3f 1188
d957ae2d 1189 return 0;
0ad19a3f 1190}
1191
26c39028
JHS
1192/* XXX: merge with instanciate_macvlan */
1193static int instanciate_vlan(struct lxc_netdev *netdev)
1194{
1195 char peer[IFNAMSIZ];
1196
1197 if (!netdev->link) {
1198 ERROR("no link specified for vlan netdev");
1199 return -1;
1200 }
1201
e892973e 1202 snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
26c39028 1203
f6cc1de1 1204 if (lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid)) {
26c39028
JHS
1205 ERROR("failed to create vlan interface '%s' on '%s'",
1206 peer, netdev->link);
1207 return -1;
1208 }
1209
1210 netdev->ifindex = if_nametoindex(peer);
1211 if (!netdev->ifindex) {
1212 ERROR("failed to retrieve the ifindex for %s", peer);
1213 lxc_device_delete(peer);
1214 return -1;
1215 }
1216
e892973e
DL
1217 DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
1218 netdev->ifindex);
1219
26c39028
JHS
1220 return 0;
1221}
1222
82d5ae15 1223static int instanciate_phys(struct lxc_netdev *netdev)
0ad19a3f 1224{
9d083402 1225 netdev->ifindex = if_nametoindex(netdev->link);
82d5ae15 1226 if (!netdev->ifindex) {
9d083402 1227 ERROR("failed to retrieve the index for %s", netdev->link);
0ad19a3f 1228 return -1;
1229 }
1230
82d5ae15 1231 return 0;
0ad19a3f 1232}
1233
82d5ae15 1234static int instanciate_empty(struct lxc_netdev *netdev)
0ad19a3f 1235{
82d5ae15
DL
1236 netdev->ifindex = 0;
1237 return 0;
0ad19a3f 1238}
1239
5f4535a3 1240int lxc_create_network(struct lxc_list *network)
0ad19a3f 1241{
82d5ae15 1242 struct lxc_list *iterator;
82d5ae15 1243 struct lxc_netdev *netdev;
0ad19a3f 1244
5f4535a3 1245 lxc_list_for_each(iterator, network) {
0ad19a3f 1246
5f4535a3 1247 netdev = iterator->elem;
13954cce 1248
5f4535a3 1249 if (netdev->type < 0 || netdev->type > MAXCONFTYPE) {
82d5ae15 1250 ERROR("invalid network configuration type '%d'",
5f4535a3 1251 netdev->type);
82d5ae15
DL
1252 return -1;
1253 }
0ad19a3f 1254
5f4535a3 1255 if (netdev_conf[netdev->type](netdev)) {
82d5ae15
DL
1256 ERROR("failed to create netdev");
1257 return -1;
1258 }
0ad19a3f 1259 }
1260
1261 return 0;
1262}
1263
5f4535a3 1264int lxc_assign_network(struct lxc_list *network, pid_t pid)
0ad19a3f 1265{
82d5ae15 1266 struct lxc_list *iterator;
82d5ae15 1267 struct lxc_netdev *netdev;
0ad19a3f 1268
5f4535a3 1269 lxc_list_for_each(iterator, network) {
82d5ae15 1270
5f4535a3 1271 netdev = iterator->elem;
82d5ae15
DL
1272
1273 if (lxc_device_move(netdev->ifindex, pid)) {
1274 ERROR("failed to move '%s' to the container",
9d083402 1275 netdev->link);
82d5ae15
DL
1276 return -1;
1277 }
1278
9d083402 1279 DEBUG("move '%s' to '%d'", netdev->link, pid);
0ad19a3f 1280 }
1281
1282 return 0;
1283}
1284
5e4a62bf 1285int lxc_create_tty(const char *name, struct lxc_conf *conf)
b0a33c1e 1286{
5e4a62bf 1287 struct lxc_tty_info *tty_info = &conf->tty_info;
985d15b1 1288 int i;
b0a33c1e 1289
5e4a62bf
DL
1290 /* no tty in the configuration */
1291 if (!conf->tty)
b0a33c1e 1292 return 0;
1293
13954cce 1294 tty_info->pty_info =
e4e7d59d 1295 malloc(sizeof(*tty_info->pty_info)*conf->tty);
b0a33c1e 1296 if (!tty_info->pty_info) {
36eb9bde 1297 SYSERROR("failed to allocate pty_info");
985d15b1 1298 return -1;
b0a33c1e 1299 }
1300
985d15b1 1301 for (i = 0; i < conf->tty; i++) {
13954cce 1302
b0a33c1e 1303 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1304
13954cce 1305 if (openpty(&pty_info->master, &pty_info->slave,
b0a33c1e 1306 pty_info->name, NULL, NULL)) {
36eb9bde 1307 SYSERROR("failed to create pty #%d", i);
985d15b1
MT
1308 tty_info->nbtty = i;
1309 lxc_delete_tty(tty_info);
1310 return -1;
b0a33c1e 1311 }
1312
b035ad62
MS
1313 /* Prevent leaking the file descriptors to the container */
1314 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
1315 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
1316
b0a33c1e 1317 pty_info->busy = 0;
1318 }
1319
985d15b1 1320 tty_info->nbtty = conf->tty;
1ac470c0
DL
1321
1322 INFO("tty's configured");
1323
985d15b1 1324 return 0;
b0a33c1e 1325}
1326
1327void lxc_delete_tty(struct lxc_tty_info *tty_info)
1328{
1329 int i;
1330
1331 for (i = 0; i < tty_info->nbtty; i++) {
1332 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1333
1334 close(pty_info->master);
1335 close(pty_info->slave);
1336 }
1337
1338 free(tty_info->pty_info);
1339 tty_info->nbtty = 0;
1340}
1341
571e6ec8 1342int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
0ad19a3f 1343{
571e6ec8 1344 if (setup_utsname(lxc_conf->utsname)) {
36eb9bde 1345 ERROR("failed to setup the utsname for '%s'", name);
95b5ffaf 1346 return -1;
0ad19a3f 1347 }
1348
5f4535a3 1349 if (setup_network(&lxc_conf->network)) {
36eb9bde 1350 ERROR("failed to setup the network for '%s'", name);
95b5ffaf 1351 return -1;
0ad19a3f 1352 }
1353
571e6ec8 1354 if (setup_cgroup(name, &lxc_conf->cgroup)) {
36eb9bde 1355 ERROR("failed to setup the cgroups for '%s'", name);
95b5ffaf 1356 return -1;
0ad19a3f 1357 }
1358
571e6ec8 1359 if (setup_mount(lxc_conf->fstab)) {
36eb9bde 1360 ERROR("failed to setup the mounts for '%s'", name);
95b5ffaf 1361 return -1;
576f946d 1362 }
1363
e7938e9e
MN
1364 if (setup_mount_entries(&lxc_conf->mount_list)) {
1365 ERROR("failed to setup the mount entries for '%s'", name);
1366 return -1;
1367 }
1368
571e6ec8 1369 if (setup_console(lxc_conf->rootfs, lxc_conf->console)) {
36eb9bde 1370 ERROR("failed to setup the console for '%s'", name);
95b5ffaf 1371 return -1;
6e590161 1372 }
1373
571e6ec8 1374 if (setup_tty(lxc_conf->rootfs, &lxc_conf->tty_info)) {
36eb9bde 1375 ERROR("failed to setup the ttys for '%s'", name);
95b5ffaf 1376 return -1;
b0a33c1e 1377 }
1378
bf601689 1379 if (setup_rootfs(lxc_conf->rootfs, lxc_conf->pivotdir)) {
36eb9bde 1380 ERROR("failed to set rootfs for '%s'", name);
95b5ffaf 1381 return -1;
ed502555 1382 }
1383
571e6ec8 1384 if (setup_pts(lxc_conf->pts)) {
36eb9bde 1385 ERROR("failed to setup the new pts instance");
95b5ffaf 1386 return -1;
3c26f34e 1387 }
1388
81810dd1
DL
1389 if (setup_caps(&lxc_conf->caps)) {
1390 ERROR("failed to drop capabilities");
1391 return -1;
1392 }
1393
cd54d859
DL
1394 NOTICE("'%s' is setup.", name);
1395
0ad19a3f 1396 return 0;
1397}