]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/conf.c
use the configuration structure for the cgroup
[mirror_lxc.git] / src / lxc / conf.c
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>
32 #include <pty.h>
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>
41
42 #include <arpa/inet.h>
43 #include <fcntl.h>
44 #include <netinet/in.h>
45 #include <net/if.h>
46 #include <libgen.h>
47
48 #include "network.h"
49 #include "error.h"
50 #include "parse.h"
51
52 #include <lxc/lxc.h>
53 #include <lxc/log.h>
54
55 lxc_log_define(lxc_conf, lxc);
56
57 #define MAXHWLEN 18
58 #define MAXINDEXLEN 20
59 #define MAXMTULEN 16
60 #define MAXLINELEN 128
61
62 #ifndef MS_REC
63 #define MS_REC 16384
64 #endif
65
66 typedef int (*instanciate_cb)(const char *directory,
67 const char *file, pid_t pid);
68
69 struct netdev_conf {
70 const char *type;
71 instanciate_cb cb;
72 int count;
73 };
74
75 struct mount_opt {
76 char *name;
77 int clear;
78 int flag;
79 };
80
81 static int instanciate_veth(const char *, const char *, pid_t);
82 static int instanciate_macvlan(const char *, const char *, pid_t);
83 static int instanciate_phys(const char *, const char *, pid_t);
84 static int instanciate_empty(const char *, const char *, pid_t);
85 static int unconfigure_cgroup(const char *name);
86
87 static struct netdev_conf netdev_conf[MAXCONFTYPE + 1] = {
88 [VETH] = { "veth", instanciate_veth, 0 },
89 [MACVLAN] = { "macvlan", instanciate_macvlan, 0, },
90 [PHYS] = { "phys", instanciate_phys, 0, },
91 [EMPTY] = { "empty", instanciate_empty, 0, },
92 };
93
94 static struct mount_opt mount_opt[] = {
95 { "defaults", 0, 0 },
96 { "ro", 0, MS_RDONLY },
97 { "rw", 1, MS_RDONLY },
98 { "suid", 1, MS_NOSUID },
99 { "nosuid", 0, MS_NOSUID },
100 { "dev", 1, MS_NODEV },
101 { "nodev", 0, MS_NODEV },
102 { "exec", 1, MS_NOEXEC },
103 { "noexec", 0, MS_NOEXEC },
104 { "sync", 0, MS_SYNCHRONOUS },
105 { "async", 1, MS_SYNCHRONOUS },
106 { "remount", 0, MS_REMOUNT },
107 { "mand", 0, MS_MANDLOCK },
108 { "nomand", 1, MS_MANDLOCK },
109 { "atime", 1, MS_NOATIME },
110 { "noatime", 0, MS_NOATIME },
111 { "diratime", 1, MS_NODIRATIME },
112 { "nodiratime", 0, MS_NODIRATIME },
113 { "bind", 0, MS_BIND },
114 { "rbind", 0, MS_BIND|MS_REC },
115 { NULL, 0, 0 },
116 };
117
118 static int write_info(const char *path, const char *file, const char *info)
119 {
120 int fd, err = -1;
121 char f[MAXPATHLEN];
122
123 snprintf(f, MAXPATHLEN, "%s/%s", path, file);
124 fd = creat(f, 0755);
125 if (fd < 0)
126 goto out;
127
128 if (write(fd, info, strlen(info)) < 0 ||
129 write(fd, "\n", strlen("\n") + 1) < 0)
130 goto out_write;
131 err = 0;
132 out:
133 close(fd);
134 return err;
135
136 out_write:
137 unlink(f);
138 goto out;
139 }
140
141 static int read_info(const char *path, const char *file, char *info, size_t len)
142 {
143 int fd, ret = -1;
144 char f[MAXPATHLEN], *token;
145
146 snprintf(f, MAXPATHLEN, "%s/%s", path, file);
147 fd = open(f, O_RDONLY);
148 if (fd < 0) {
149 if (errno == ENOENT)
150 ret = 1;
151 goto out;
152 }
153
154 ret = read(fd, info, len);
155 if (ret < 0)
156 goto out;
157
158 token = strstr(info, "\n");
159 if (token)
160 *token = '\0';
161 ret = 0;
162 out:
163 close(fd);
164 return ret;
165 }
166
167 static int delete_info(const char *path, const char *file)
168 {
169 char info[MAXPATHLEN];
170 int ret;
171
172 snprintf(info, MAXPATHLEN, "%s/%s", path, file);
173 ret = unlink(info);
174
175 return ret;
176 }
177
178 static int configure_ip4addr(int fd, struct lxc_inetdev *in)
179 {
180 char addr[INET6_ADDRSTRLEN];
181 char bcast[INET_ADDRSTRLEN];
182 char line[MAXLINELEN];
183 int err = -1;
184
185 if (!inet_ntop(AF_INET, &in->addr, addr, sizeof(addr))) {
186 SYSERROR("failed to convert ipv4 address");
187 goto err;
188 }
189
190 if (!inet_ntop(AF_INET, &in->bcast, bcast, sizeof(bcast))) {
191 SYSERROR("failed to convert ipv4 broadcast");
192 goto err;
193 }
194
195 if (in->prefix)
196 snprintf(line, MAXLINELEN, "%s/%d %s\n", addr, in->prefix, bcast);
197 else
198 snprintf(line, MAXLINELEN, "%s %s\n", addr, bcast);
199
200 if (write(fd, line, strlen(line)) < 0) {
201 SYSERROR("failed to write address info");
202 goto err;
203 }
204
205 err = 0;
206 err:
207 return err;
208 }
209
210 static int configure_ip6addr(int fd, struct lxc_inet6dev *in6)
211 {
212 char addr[INET6_ADDRSTRLEN];
213 char line[MAXLINELEN];
214 int err = -1;
215
216 if (!inet_ntop(AF_INET6, &in6->addr, addr, sizeof(addr))) {
217 SYSERROR("failed to convert ipv4 address");
218 goto err;
219 }
220
221 snprintf(line, MAXLINELEN, "%s/%d\n", addr, in6->prefix?in6->prefix:64);
222
223 if (write(fd, line, strlen(line)) < 0) {
224 SYSERROR("failed to write address info");
225 goto err;
226 }
227
228 err = 0;
229 err:
230 return err;
231 }
232
233 static int configure_ip_address(const char *path, struct lxc_list *ip, int family)
234 {
235 char file[MAXPATHLEN];
236 struct lxc_list *iterator;
237 int fd, err = -1;
238
239 if (mkdir(path, 0755)) {
240 SYSERROR("failed to create directory %s", path);
241 return -1;
242 }
243
244 snprintf(file, MAXPATHLEN, "%s/addresses", path);
245 fd = creat(file, 0755);
246 if (fd < 0) {
247 SYSERROR("failed to create %s file", file);
248 goto err;
249 }
250
251 lxc_list_for_each(iterator, ip) {
252 err = family == AF_INET?
253 configure_ip4addr(fd, iterator->elem):
254 configure_ip6addr(fd, iterator->elem);
255 if (err)
256 goto err;
257 }
258 out:
259 close(fd);
260 return err;
261 err:
262 unlink(file);
263 rmdir(path);
264 goto out;
265 }
266
267 static int configure_netdev(const char *path, struct lxc_netdev *netdev)
268 {
269 int err = -1;
270 char dir[MAXPATHLEN];
271
272 if (mkdir(path, 0755)) {
273 SYSERROR("failed to create %s directory", path);
274 return -1;
275 }
276
277 if (netdev->ifname) {
278 if (write_info(path, "link", netdev->ifname))
279 goto out_link;
280 }
281
282 if (netdev->newname) {
283 if (write_info(path, "name", netdev->newname))
284 goto out_newname;
285 }
286
287 if (netdev->hwaddr) {
288 if (write_info(path, "hwaddr", netdev->hwaddr))
289 goto out_hwaddr;
290 }
291
292 if (netdev->mtu) {
293 if (write_info(path, "mtu", netdev->mtu))
294 goto out_mtu;
295 }
296
297 if (netdev->flags & IFF_UP) {
298 if (write_info(path, "up", ""))
299 goto out_up;
300 }
301
302 if (!lxc_list_empty(&netdev->ipv4)) {
303 snprintf(dir, MAXPATHLEN, "%s/ipv4", path);
304 if (configure_ip_address(dir, &netdev->ipv4, AF_INET))
305 goto out_ipv4;
306 }
307
308 if (!lxc_list_empty(&netdev->ipv6)) {
309 snprintf(dir, MAXPATHLEN, "%s/ipv6", path);
310 if (configure_ip_address(dir, &netdev->ipv6, AF_INET6))
311 goto out_ipv6;
312 }
313 err = 0;
314 out:
315 return err;
316 out_ipv6:
317 delete_info(path, "ipv4");
318 out_ipv4:
319 delete_info(path, "up");
320 out_up:
321 delete_info(path, "mtu");
322 out_mtu:
323 delete_info(path, "hwaddr");
324 out_hwaddr:
325 delete_info(path, "name");
326 out_newname:
327 delete_info(path, "link");
328 out_link:
329 rmdir(path);
330 goto out;
331 }
332
333 static int configure_network(const char *name, struct lxc_list *network)
334 {
335 struct lxc_list *iterator;
336 struct lxc_network *n;
337 char networkpath[MAXPATHLEN];
338 char path[MAXPATHLEN];
339 int err = -1;
340
341 if (lxc_list_empty(network))
342 return 0;
343
344 snprintf(networkpath, MAXPATHLEN, LXCPATH "/%s/network", name);
345 if (mkdir(networkpath, 0755)) {
346 SYSERROR("failed to create %s directory", networkpath);
347 goto out;
348 }
349
350 lxc_list_for_each(iterator, network) {
351
352 n = iterator->elem;
353
354 if (n->type < 0 || n->type > MAXCONFTYPE) {
355 ERROR("invalid network configuration type '%d'",
356 n->type);
357 goto out;
358 }
359
360 snprintf(path, MAXPATHLEN, "%s/%s%d", networkpath,
361 netdev_conf[n->type].type,
362 netdev_conf[n->type].count++);
363
364 if (configure_netdev(path, lxc_list_first_elem(&n->netdev))) {
365 ERROR("failed to configure network type %s",
366 netdev_conf[n->type].type);
367 goto out;
368 }
369 }
370
371 err = 0;
372 out:
373 return err;
374 }
375
376 static int configure_find_fstype_cb(void* buffer, void *data)
377 {
378 struct cbarg {
379 const char *rootfs;
380 const char *testdir;
381 char *fstype;
382 int mntopt;
383 } *cbarg = data;
384
385 char *fstype;
386
387 /* we don't try 'nodev' entries */
388 if (strstr(buffer, "nodev"))
389 return 0;
390
391 fstype = buffer;
392 fstype += lxc_char_left_gc(fstype, strlen(fstype));
393 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
394
395 if (mount(cbarg->rootfs, cbarg->testdir, fstype, cbarg->mntopt, NULL))
396 return 0;
397
398 /* found ! */
399 umount(cbarg->testdir);
400 strcpy(cbarg->fstype, fstype);
401
402 return 1;
403 }
404
405 /* find the filesystem type with brute force */
406 static int configure_find_fstype(const char *rootfs, char *fstype, int mntopt)
407 {
408 int i, found;
409 char buffer[MAXPATHLEN];
410
411 struct cbarg {
412 const char *rootfs;
413 const char *testdir;
414 char *fstype;
415 int mntopt;
416 } cbarg = {
417 .rootfs = rootfs,
418 .fstype = fstype,
419 .mntopt = mntopt,
420 };
421
422 /* first we check with /etc/filesystems, in case the modules
423 * are auto-loaded and fall back to the supported kernel fs
424 */
425 char *fsfile[] = {
426 "/etc/filesystems",
427 "/proc/filesystems",
428 };
429
430 cbarg.testdir = tempnam("/tmp", "lxc-");
431 if (!cbarg.testdir) {
432 SYSERROR("failed to build a temp name");
433 return -1;
434 }
435
436 if (mkdir(cbarg.testdir, 0755)) {
437 SYSERROR("failed to create temporary directory");
438 return -1;
439 }
440
441 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
442
443 found = lxc_file_for_each_line(fsfile[i],
444 configure_find_fstype_cb,
445 buffer, sizeof(buffer), &cbarg);
446
447 if (found < 0) {
448 SYSERROR("failed to read '%s'", fsfile[i]);
449 goto out;
450 }
451
452 if (found)
453 break;
454 }
455
456 if (!found) {
457 ERROR("failed to determine fs type for '%s'", rootfs);
458 goto out;
459 }
460
461 out:
462 rmdir(cbarg.testdir);
463 return found - 1;
464 }
465
466 static int configure_rootfs_dir_cb(const char *rootfs, const char *absrootfs,
467 FILE *f)
468 {
469 return fprintf(f, "%s %s none rbind 0 0\n", absrootfs, rootfs);
470 }
471
472 static int configure_rootfs_blk_cb(const char *rootfs, const char *absrootfs,
473 FILE *f)
474 {
475 char fstype[MAXPATHLEN];
476
477 if (configure_find_fstype(absrootfs, fstype, 0)) {
478 ERROR("failed to configure mount for block device '%s'",
479 absrootfs);
480 return -1;
481 }
482
483 return fprintf(f, "%s %s %s defaults 0 0\n", absrootfs, rootfs, fstype);
484 }
485
486 static int configure_rootfs(const char *name, const char *rootfs)
487 {
488 char path[MAXPATHLEN];
489 char absrootfs[MAXPATHLEN];
490 char fstab[MAXPATHLEN];
491 struct stat s;
492 FILE *f;
493 int i, ret;
494
495 typedef int (*rootfs_cb)(const char *, const char *, FILE *);
496
497 struct rootfs_type {
498 int type;
499 rootfs_cb cb;
500 } rtfs_type[] = {
501 { __S_IFDIR, configure_rootfs_dir_cb },
502 { __S_IFBLK, configure_rootfs_blk_cb },
503 };
504
505 if (!realpath(rootfs, absrootfs)) {
506 SYSERROR("failed to get real path for '%s'", rootfs);
507 return -1;
508 }
509
510 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
511
512 if (mkdir(path, 0755)) {
513 SYSERROR("failed to create the '%s' directory", path);
514 return -1;
515 }
516
517 if (access(absrootfs, F_OK)) {
518 SYSERROR("'%s' is not accessible", absrootfs);
519 return -1;
520 }
521
522 if (stat(absrootfs, &s)) {
523 SYSERROR("failed to stat '%s'", absrootfs);
524 return -1;
525 }
526
527 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
528
529 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
530 continue;
531
532 snprintf(fstab, MAXPATHLEN, LXCPATH "/%s/fstab", name);
533
534 f = fopen(fstab, "a+");
535 if (!f) {
536 SYSERROR("failed to open fstab file");
537 return -1;
538 }
539
540 ret = rtfs_type[i].cb(path, absrootfs, f);
541
542 fclose(f);
543
544 if (ret < 0) {
545 ERROR("failed to add rootfs mount in fstab");
546 return -1;
547 }
548
549 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs/rootfs", name);
550
551 return symlink(absrootfs, path);
552 }
553
554 ERROR("unsupported rootfs type for '%s'", absrootfs);
555 return -1;
556 }
557
558 static int unconfigure_ip_addresses(const char *directory)
559 {
560 char path[MAXPATHLEN];
561
562 snprintf(path, MAXPATHLEN, "%s/ipv4", directory);
563 delete_info(path, "addresses");
564 rmdir(path);
565
566 snprintf(path, MAXPATHLEN, "%s/ipv6", directory);
567 delete_info(path, "addresses");
568 rmdir(path);
569
570 return 0;
571 }
572
573 static int unconfigure_network_cb(const char *name, const char *directory,
574 const char *file, void *data)
575 {
576 char path[MAXPATHLEN];
577
578 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
579 delete_info(path, "ifindex");
580 delete_info(path, "name");
581 delete_info(path, "addr");
582 delete_info(path, "link");
583 delete_info(path, "hwaddr");
584 delete_info(path, "mtu");
585 delete_info(path, "up");
586 unconfigure_ip_addresses(path);
587 rmdir(path);
588
589 return 0;
590 }
591
592 static int unconfigure_network(const char *name)
593 {
594 char directory[MAXPATHLEN];
595
596 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
597 lxc_dir_for_each(name, directory, unconfigure_network_cb, NULL);
598 rmdir(directory);
599
600 return 0;
601 }
602
603 static int unconfigure_cgroup_cb(const char *name, const char *directory,
604 const char *file, void *data)
605 {
606 return delete_info(directory, file);
607 }
608
609 static int unconfigure_cgroup(const char *name)
610 {
611 char filename[MAXPATHLEN];
612 struct stat s;
613
614 snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
615
616 if (stat(filename, &s)) {
617 SYSERROR("failed to stat '%s'", filename);
618 return -1;
619 }
620
621 if (S_ISDIR(s.st_mode)) {
622 /* old cgroup configuration */
623 lxc_dir_for_each(name, filename, unconfigure_cgroup_cb, NULL);
624 rmdir(filename);
625 } else {
626 unlink(filename);
627 }
628
629 return 0;
630 }
631
632 static int unconfigure_rootfs(const char *name)
633 {
634 char path[MAXPATHLEN];
635
636 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
637
638 #warning deprecated code to be removed in the next version
639
640 /* ugly but for backward compatibily, */
641 delete_info(path, "rootfs");
642 rmdir(path);
643 unlink(path);
644
645 return 0;
646 }
647
648 static int unconfigure_pts(const char *name)
649 {
650 char path[MAXPATHLEN];
651
652 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
653 delete_info(path, "pts");
654
655 return 0;
656 }
657
658 static int unconfigure_tty(const char *name)
659 {
660 char path[MAXPATHLEN];
661
662 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
663 delete_info(path, "tty");
664
665 return 0;
666 }
667
668 static int unconfigure_mount(const char *name)
669 {
670 char path[MAXPATHLEN];
671
672 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
673 delete_info(path, "fstab");
674
675 return 0;
676 }
677
678 static int unconfigure_utsname(const char *name)
679 {
680 char path[MAXPATHLEN];
681
682 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
683 delete_info(path, "utsname");
684
685 return 0;
686 }
687
688 static int setup_utsname(struct utsname *utsname)
689 {
690 if (!utsname)
691 return 0;
692
693 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
694 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
695 return -1;
696 }
697
698 INFO("'%s' hostname has been setup", utsname->nodename);
699
700 return 0;
701 }
702
703 static int setup_tty(const char *rootfs, const struct lxc_tty_info *tty_info)
704 {
705 char path[MAXPATHLEN];
706 int i;
707
708 for (i = 0; i < tty_info->nbtty; i++) {
709
710 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
711
712 snprintf(path, sizeof(path), "%s/dev/tty%d",
713 rootfs ? rootfs : "", i + 1);
714
715 /* At this point I can not use the "access" function
716 * to check the file is present or not because it fails
717 * with EACCES errno and I don't know why :( */
718
719 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
720 WARN("failed to mount '%s'->'%s'",
721 pty_info->name, path);
722 continue;
723 }
724 }
725
726 INFO("%d tty(s) has been setup", tty_info->nbtty);
727
728 return 0;
729 }
730
731 static int setup_rootfs(const char *rootfs)
732 {
733 char *tmpname;
734 int ret = -1;
735
736 if (!rootfs)
737 return 0;
738
739 tmpname = tempnam("/tmp", "lxc-rootfs");
740 if (!tmpname) {
741 SYSERROR("failed to generate temporary name");
742 return -1;
743 }
744
745 if (mkdir(tmpname, 0700)) {
746 SYSERROR("failed to create temporary directory '%s'", tmpname);
747 return -1;
748 }
749
750 if (mount(rootfs, tmpname, "none", MS_BIND|MS_REC, NULL)) {
751 SYSERROR("failed to mount '%s'->'%s'", rootfs, tmpname);
752 goto out;
753 }
754
755 if (chroot(tmpname)) {
756 SYSERROR("failed to set chroot %s", tmpname);
757 goto out;
758 }
759
760 if (chdir(getenv("HOME")) && chdir("/")) {
761 SYSERROR("failed to change to home directory");
762 goto out;
763 }
764
765 INFO("chrooted to '%s'", rootfs);
766
767 ret = 0;
768 out:
769 rmdir(tmpname);
770 return ret;
771 }
772
773 static int setup_pts(int pts)
774 {
775 if (!pts)
776 return 0;
777
778 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
779 SYSERROR("failed to umount 'dev/pts'");
780 return -1;
781 }
782
783 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance")) {
784 SYSERROR("failed to mount a new instance of '/dev/pts'");
785 return -1;
786 }
787
788 if (chmod("/dev/pts/ptmx", 0666)) {
789 SYSERROR("failed to set permission for '/dev/pts/ptmx'");
790 return -1;
791 }
792
793 if (access("/dev/ptmx", F_OK)) {
794 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
795 goto out;
796 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
797 return -1;
798 }
799
800 /* fallback here, /dev/pts/ptmx exists just mount bind */
801 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
802 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
803 return -1;
804 }
805
806 INFO("created new pts instance");
807
808 out:
809 return 0;
810 }
811
812 static int setup_console(const char *rootfs, const char *tty)
813 {
814 char console[MAXPATHLEN];
815
816 snprintf(console, sizeof(console), "%s/dev/console",
817 rootfs ? rootfs : "");
818
819 /* we have the rootfs with /dev/console but no tty
820 * to be used as console, let's remap /dev/console
821 * to /dev/null to avoid to log to the system console
822 */
823 if (rootfs && !tty[0]) {
824
825 if (!access(console, F_OK)) {
826
827 if (mount("/dev/null", console, "none", MS_BIND, 0)) {
828 SYSERROR("failed to mount '/dev/null'->'%s'",
829 console);
830 return -1;
831 }
832 }
833 }
834
835 if (!tty[0])
836 return 0;
837
838 if (access(console, R_OK|W_OK))
839 return 0;
840
841 if (mount(tty, console, "none", MS_BIND, 0)) {
842 ERROR("failed to mount the console");
843 return -1;
844 }
845
846 INFO("console '%s' mounted to '%s'", tty, console);
847
848 return 0;
849 }
850
851 static int setup_cgroup(const char *name, struct lxc_list *cgroups)
852 {
853 struct lxc_list *iterator;
854 struct lxc_cgroup *cg;
855
856 if (lxc_list_empty(cgroups))
857 return 0;
858
859 lxc_list_for_each(iterator, cgroups) {
860
861 cg = iterator->elem;
862
863 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
864 break;
865
866 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
867 }
868
869 INFO("cgroup has been setup");
870
871 return 0;
872 }
873
874 static void parse_mntopt(char *opt, unsigned long *flags, char **data)
875 {
876 struct mount_opt *mo;
877
878 /* If opt is found in mount_opt, set or clear flags.
879 * Otherwise append it to data. */
880
881 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
882 if (!strncmp(opt, mo->name, strlen(mo->name))) {
883 if (mo->clear)
884 *flags &= ~mo->flag;
885 else
886 *flags |= mo->flag;
887 return;
888 }
889 }
890
891 if (strlen(*data))
892 strcat(*data, ",");
893 strcat(*data, opt);
894 }
895
896 static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
897 char **mntdata)
898 {
899 char *s, *data;
900 char *p, *saveptr = NULL;
901
902 if (!mntent->mnt_opts)
903 return 0;
904
905 s = strdup(mntent->mnt_opts);
906 if (!s) {
907 SYSERROR("failed to allocate memory");
908 return -1;
909 }
910
911 data = malloc(strlen(s) + 1);
912 if (!data) {
913 SYSERROR("failed to allocate memory");
914 free(s);
915 return -1;
916 }
917 *data = 0;
918
919 for (p = strtok_r(s, ",", &saveptr); p != NULL;
920 p = strtok_r(NULL, ",", &saveptr))
921 parse_mntopt(p, mntflags, &data);
922
923 if (*data)
924 *mntdata = data;
925 else
926 free(data);
927 free(s);
928
929 return 0;
930 }
931
932 static int setup_mount(const char *fstab)
933 {
934 struct mntent *mntent;
935 FILE *file;
936 int ret = -1;
937 unsigned long mntflags;
938 char *mntdata;
939
940 if (!fstab)
941 return 0;
942
943 file = setmntent(fstab, "r");
944 if (!file) {
945 SYSERROR("failed to use '%s'", fstab);
946 return -1;
947 }
948
949 while ((mntent = getmntent(file))) {
950
951 mntflags = 0;
952 mntdata = NULL;
953 if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
954 ERROR("failed to parse mount option '%s'",
955 mntent->mnt_opts);
956 goto out;
957 }
958
959 if (mount(mntent->mnt_fsname, mntent->mnt_dir,
960 mntent->mnt_type, mntflags, mntdata)) {
961 SYSERROR("failed to mount '%s' on '%s'",
962 mntent->mnt_fsname, mntent->mnt_dir);
963 goto out;
964 }
965
966 DEBUG("mounted %s on %s, type %s", mntent->mnt_fsname,
967 mntent->mnt_dir, mntent->mnt_type);
968
969 free(mntdata);
970 }
971
972 ret = 0;
973
974 INFO("mount points have been setup");
975 out:
976 endmntent(file);
977 return ret;
978 }
979
980 static int setup_ipv4_addr_cb(void *buffer, void *data)
981 {
982 char *ifname = data;
983 char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
984 int p = 24;
985
986 addr = buffer;
987 cursor = strstr(addr, " ");
988 if (cursor) {
989 *cursor = '\0';
990 bcast = cursor + 1;
991 cursor = strstr(bcast, "\n");
992 if (cursor)
993 *cursor = '\0';
994 }
995
996 slash = strstr(addr, "/");
997 if (slash) {
998 *slash = '\0';
999 prefix = slash + 1;
1000 }
1001
1002 if (prefix)
1003 p = atoi(prefix);
1004
1005 if (lxc_ip_addr_add(ifname, addr, p, bcast)) {
1006 ERROR("failed to set %s to addr %s/%d %s", ifname,
1007 addr, p, bcast?bcast:"");
1008 return -1;
1009 }
1010
1011 DEBUG("address '%s/%s' on '%s' has been setup", addr, prefix, ifname);
1012
1013 return 0;
1014 }
1015
1016 static int setup_ipv6_addr_cb(void *buffer, void *data)
1017 {
1018 char *ifname = data;
1019 char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
1020 int p = 24;
1021
1022 addr = buffer;
1023 cursor = strstr(addr, " ");
1024 if (cursor) {
1025 *cursor = '\0';
1026 bcast = cursor + 1;
1027 cursor = strstr(bcast, "\n");
1028 if (cursor)
1029 *cursor = '\0';
1030 }
1031
1032 slash = strstr(addr, "/");
1033 if (slash) {
1034 *slash = '\0';
1035 prefix = slash + 1;
1036 }
1037
1038 if (prefix)
1039 p = atoi(prefix);
1040
1041 if (lxc_ip6_addr_add(ifname, addr, p, bcast)) {
1042 ERROR("failed to set %s to addr %s/%d %s", ifname,
1043 addr, p, bcast?bcast:"");
1044 return -1;
1045 }
1046
1047 INFO("address '%s/%s' on '%s' has been setup", addr, prefix, ifname);
1048
1049 return 0;
1050 }
1051
1052 static int setup_hw_addr(char *hwaddr, const char *ifname)
1053 {
1054 struct sockaddr sockaddr;
1055 struct ifreq ifr;
1056 int ret, fd;
1057
1058 if (lxc_convert_mac(hwaddr, &sockaddr)) {
1059 ERROR("conversion has failed");
1060 return -1;
1061 }
1062
1063 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1064 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1065
1066 fd = socket(AF_INET, SOCK_DGRAM, 0);
1067 if (fd < 0) {
1068 ERROR("socket failure : %s", strerror(errno));
1069 return -1;
1070 }
1071
1072 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1073 close(fd);
1074 if (ret)
1075 ERROR("ioctl failure : %s", strerror(errno));
1076
1077 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
1078
1079 return ret;
1080 }
1081
1082 static int setup_ip_addr(const char *directory, const char *ifname)
1083 {
1084 char path[MAXPATHLEN], line[MAXLINELEN];
1085 struct stat s;
1086 int ret = 0;
1087
1088 snprintf(path, MAXPATHLEN, "%s/ipv4/addresses", directory);
1089 if (!stat(path, &s))
1090 ret = lxc_file_for_each_line(path, setup_ipv4_addr_cb,
1091 line, MAXPATHLEN, (void*)ifname);
1092 return ret;
1093 }
1094
1095 static int setup_ip6_addr(const char *directory, const char *ifname)
1096 {
1097 char path[MAXPATHLEN], line[MAXLINELEN];
1098 struct stat s;
1099 int ret = 0;
1100
1101 snprintf(path, MAXLINELEN, "%s/ipv6/addresses", directory);
1102 if (!stat(path, &s))
1103 ret = lxc_file_for_each_line(path, setup_ipv6_addr_cb,
1104 line, MAXPATHLEN, (void*)ifname);
1105 return ret;
1106 }
1107
1108 static int setup_network_cb(const char *name, const char *directory,
1109 const char *file, void *data)
1110 {
1111 char path[MAXPATHLEN];
1112 char strindex[MAXINDEXLEN];
1113 char ifname[IFNAMSIZ];
1114 char newname[IFNAMSIZ];
1115 char hwaddr[MAXHWLEN];
1116 char *current_ifname = ifname;
1117 int ifindex;
1118
1119 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1120
1121 if (read_info(path, "ifindex", strindex, sizeof(strindex))) {
1122 ERROR("failed to read ifindex info");
1123 return -1;
1124 }
1125
1126 ifindex = atoi(strindex);
1127 if (!ifindex) {
1128 if (!read_info(path, "up", strindex, sizeof(strindex)))
1129 if (lxc_device_up("lo")) {
1130 ERROR("failed to set the loopback up");
1131 return -1;
1132 }
1133 return 0;
1134 }
1135
1136 if (!if_indextoname(ifindex, current_ifname)) {
1137 ERROR("no interface corresponding to index '%d'",
1138 ifindex);
1139 return -1;
1140 }
1141
1142 /* default: let the system to choose one interface name */
1143 if (read_info(path, "name", newname, sizeof(newname)))
1144 strcpy(newname, "eth%d");
1145
1146 if (lxc_device_rename(ifname, newname)) {
1147 ERROR("failed to rename %s->%s", ifname, current_ifname);
1148 return -1;
1149 }
1150
1151 /* Re-read the name of the interface because its name has changed
1152 * and would be automatically allocated by the system
1153 */
1154 if (!if_indextoname(ifindex, current_ifname)) {
1155 ERROR("no interface corresponding to index '%d'",
1156 ifindex);
1157 return -1;
1158 }
1159
1160 if (!read_info(path, "hwaddr", hwaddr, sizeof(hwaddr))) {
1161 if (setup_hw_addr(hwaddr, current_ifname)) {
1162 ERROR("failed to setup hw address for '%s'",
1163 current_ifname);
1164 return -1;
1165 }
1166 }
1167
1168 if (setup_ip_addr(path, current_ifname)) {
1169 ERROR("failed to setup ip addresses for '%s'",
1170 ifname);
1171 return -1;
1172 }
1173
1174 if (setup_ip6_addr(path, current_ifname)) {
1175 ERROR("failed to setup ipv6 addresses for '%s'",
1176 ifname);
1177 return -1;
1178 }
1179
1180 if (!read_info(path, "up", strindex, sizeof(strindex))) {
1181 if (lxc_device_up(current_ifname)) {
1182 ERROR("failed to set '%s' up", current_ifname);
1183 return -1;
1184 }
1185
1186 /* the network is up, make the loopback up too */
1187 if (lxc_device_up("lo")) {
1188 ERROR("failed to set the loopback up");
1189 return -1;
1190 }
1191 }
1192
1193 DEBUG("'%s' has been setup", current_ifname);
1194
1195 return 0;
1196 }
1197
1198 static int setup_network(const char *name)
1199 {
1200 char directory[MAXPATHLEN];
1201 int ret;
1202
1203 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
1204
1205 ret = lxc_dir_for_each(name, directory, setup_network_cb, NULL);
1206 if (ret)
1207 return ret;
1208
1209 INFO("network has been setup");
1210
1211 return 0;
1212 }
1213
1214 int conf_has(const char *name, const char *info)
1215 {
1216 int ret = 0;
1217 char path[MAXPATHLEN];
1218 struct stat st;
1219
1220 snprintf(path, MAXPATHLEN, LXCPATH "/%s/%s", name, info);
1221
1222 if (!stat(path, &st) || !lstat(path, &st)) {
1223 ret = 1;
1224 goto out;
1225 }
1226
1227 if (errno == ENOENT) {
1228 ret = 0;
1229 goto out;
1230 }
1231
1232 SYSERROR("failed to stat %s info", info);
1233 out:
1234 return ret;
1235 }
1236
1237 int lxc_conf_init(struct lxc_conf *conf)
1238 {
1239 conf->rcfile = NULL;
1240 conf->rootfs = NULL;
1241 conf->fstab = NULL;
1242 conf->utsname = NULL;
1243 conf->tty = 0;
1244 conf->pts = 0;
1245 lxc_list_init(&conf->cgroup);
1246 lxc_list_init(&conf->networks);
1247 return 0;
1248 }
1249
1250 int lxc_configure(const char *name, struct lxc_conf *conf)
1251 {
1252 if (!conf)
1253 return 0;
1254
1255 if (configure_network(name, &conf->networks)) {
1256 ERROR("failed to configure the network");
1257 return -1;
1258 }
1259
1260 return 0;
1261 }
1262
1263 int lxc_unconfigure(const char *name)
1264 {
1265 if (conf_has_utsname(name) && unconfigure_utsname(name))
1266 ERROR("failed to cleanup utsname");
1267
1268 if (conf_has_network(name) && unconfigure_network(name))
1269 ERROR("failed to cleanup the network");
1270
1271 if (conf_has_cgroup(name) && unconfigure_cgroup(name))
1272 ERROR("failed to cleanup cgroup");
1273
1274 if (conf_has_tty(name) && unconfigure_tty(name))
1275 ERROR("failed to cleanup tty");
1276
1277 if (conf_has_rootfs(name) && unconfigure_rootfs(name))
1278 ERROR("failed to cleanup rootfs");
1279
1280 if (conf_has_fstab(name) && unconfigure_mount(name))
1281 ERROR("failed to cleanup mount");
1282
1283 if (conf_has_pts(name) && unconfigure_pts(name))
1284 ERROR("failed to cleanup pts");
1285
1286 return 0;
1287 }
1288
1289 static int instanciate_veth(const char *directory, const char *file, pid_t pid)
1290 {
1291 char *path = NULL, *strindex = NULL, *veth1 = NULL, *veth2 = NULL;
1292 char bridge[IFNAMSIZ];
1293 char strmtu[MAXMTULEN];
1294 int ifindex, mtu = 0, ret = -1;
1295
1296 if (!asprintf(&veth1, "%s_%d", file, pid) ||
1297 !asprintf(&veth2, "%s~%d", file, pid) ||
1298 !asprintf(&path, "%s/%s", directory, file)) {
1299 SYSERROR("failed to allocate memory");
1300 goto out;
1301 }
1302
1303 if (read_info(path, "link", bridge, IFNAMSIZ)) {
1304 ERROR("failed to read bridge info");
1305 goto out;
1306 }
1307
1308 if (lxc_veth_create(veth1, veth2)) {
1309 ERROR("failed to create %s-%s/%s", veth1, veth2, bridge);
1310 goto out;
1311 }
1312
1313 if (!read_info(path, "mtu", strmtu, MAXMTULEN)) {
1314 if (sscanf(strmtu, "%u", &mtu) < 1) {
1315 ERROR("invalid mtu size '%d'", mtu);
1316 goto out_delete;
1317 }
1318
1319 if (lxc_device_set_mtu(veth1, mtu)) {
1320 ERROR("failed to set mtu for '%s'", veth1);
1321 goto out_delete;
1322 }
1323
1324 if (lxc_device_set_mtu(veth2, mtu)) {
1325 ERROR("failed to set mtu for '%s'", veth2);
1326 goto out_delete;
1327 }
1328 }
1329
1330 if (lxc_bridge_attach(bridge, veth1)) {
1331 ERROR("failed to attach '%s' to the bridge '%s'",
1332 veth1, bridge);
1333 goto out_delete;
1334 }
1335
1336 ifindex = if_nametoindex(veth2);
1337 if (!ifindex) {
1338 ERROR("failed to retrieve the index for %s", veth2);
1339 goto out_delete;
1340 }
1341
1342 if (!asprintf(&strindex, "%d", ifindex)) {
1343 SYSERROR("failed to allocate memory");
1344 goto out_delete;
1345 }
1346
1347 if (write_info(path, "ifindex", strindex)) {
1348 ERROR("failed to write interface index to %s", path);
1349 goto out_delete;
1350 }
1351
1352 if (!read_info(path, "up", strindex, sizeof(strindex))) {
1353 if (lxc_device_up(veth1)) {
1354 ERROR("failed to set %s up", veth1);
1355 goto out_delete;
1356 }
1357 }
1358
1359 ret = 0;
1360 out:
1361 free(path);
1362 free(strindex);
1363 free(veth1);
1364 free(veth2);
1365 return ret;
1366
1367 out_delete:
1368 lxc_device_delete(veth1);
1369 goto out;
1370 }
1371 static int instanciate_macvlan(const char *directory, const char *file, pid_t pid)
1372 {
1373 char path[MAXPATHLEN], *strindex = NULL, *peer = NULL;
1374 char link[IFNAMSIZ];
1375 int ifindex, ret = -1;
1376
1377 if (!asprintf(&peer, "%s~%d", file, pid)) {
1378 SYSERROR("failed to allocate memory");
1379 return -1;
1380 }
1381
1382 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1383 if (read_info(path, "link", link, IFNAMSIZ)) {
1384 ERROR("failed to read bridge info");
1385 goto out;
1386 }
1387
1388 if (lxc_macvlan_create(link, peer)) {
1389 ERROR("failed to create macvlan interface '%s' on '%s'",
1390 peer, link);
1391 goto out;
1392 }
1393
1394 ifindex = if_nametoindex(peer);
1395 if (!ifindex) {
1396 ERROR("failed to retrieve the index for %s", peer);
1397 goto out;
1398 }
1399
1400 if (!asprintf(&strindex, "%d", ifindex)) {
1401 SYSERROR("failed to allocate memory");
1402 return -1;
1403 }
1404
1405 if (write_info(path, "ifindex", strindex)) {
1406 ERROR("failed to write interface index to %s", path);
1407 goto out;
1408 }
1409
1410 ret = 0;
1411 out:
1412 free(strindex);
1413 free(peer);
1414 return ret;
1415 }
1416
1417 static int instanciate_phys(const char *directory, const char *file, pid_t pid)
1418 {
1419 char path[MAXPATHLEN], *strindex = NULL;
1420 char link[IFNAMSIZ];
1421 int ifindex, ret = -1;
1422
1423 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1424 if (read_info(path, "link", link, IFNAMSIZ)) {
1425 ERROR("failed to read link info");
1426 goto out;
1427 }
1428
1429 ifindex = if_nametoindex(link);
1430 if (!ifindex) {
1431 ERROR("failed to retrieve the index for %s", link);
1432 goto out;
1433 }
1434
1435 if (!asprintf(&strindex, "%d", ifindex)) {
1436 SYSERROR("failed to allocate memory");
1437 return -1;
1438 }
1439
1440 if (write_info(path, "ifindex", strindex)) {
1441 ERROR("failed to write interface index to %s", path);
1442 goto out;
1443 }
1444
1445 ret = 0;
1446 out:
1447 free(strindex);
1448 return ret;
1449 }
1450
1451 static int instanciate_empty(const char *directory, const char *file, pid_t pid)
1452 {
1453 char path[MAXPATHLEN], *strindex = NULL;
1454 int ret = -1;
1455
1456 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1457 if (!asprintf(&strindex, "%d", 0)) {
1458 ERROR("not enough memory");
1459 return -1;
1460 }
1461
1462 if (write_info(path, "ifindex", strindex)) {
1463 ERROR("failed to write interface index to %s", path);
1464 goto out;
1465 }
1466
1467 ret = 0;
1468 out:
1469 free(strindex);
1470 return ret;
1471 }
1472
1473 static int instanciate_netdev_cb(const char *name, const char *directory,
1474 const char *file, void *data)
1475 {
1476 pid_t *pid = data;
1477
1478 if (!strncmp("veth", file, strlen("veth")))
1479 return instanciate_veth(directory, file, *pid);
1480 else if (!strncmp("macvlan", file, strlen("macvlan")))
1481 return instanciate_macvlan(directory, file, *pid);
1482 else if (!strncmp("phys", file, strlen("phys")))
1483 return instanciate_phys(directory, file, *pid);
1484 else if (!strncmp("empty", file, strlen("empty")))
1485 return instanciate_empty(directory, file, *pid);
1486
1487 return -1;
1488 }
1489
1490 static int instanciate_netdev(const char *name, pid_t pid)
1491 {
1492 char directory[MAXPATHLEN];
1493
1494 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
1495 return lxc_dir_for_each(name, directory, instanciate_netdev_cb, &pid);
1496 }
1497
1498 static int move_netdev_cb(const char *name, const char *directory,
1499 const char *file, void *data)
1500 {
1501 char path[MAXPATHLEN], ifname[IFNAMSIZ], strindex[MAXINDEXLEN];
1502 pid_t *pid = data;
1503 int ifindex;
1504
1505 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1506 if (read_info(path, "ifindex", strindex, MAXINDEXLEN) < 0) {
1507 ERROR("failed to read index to from %s", path);
1508 return -1;
1509 }
1510
1511 ifindex = atoi(strindex);
1512 if (!ifindex)
1513 return 0;
1514
1515 if (!if_indextoname(ifindex, ifname)) {
1516 ERROR("interface with index %d does not exist",
1517 ifindex);
1518 return -1;
1519 }
1520
1521 if (lxc_device_move(ifname, *pid)) {
1522 ERROR("failed to move %s to %d", ifname, *pid);
1523 return -1;
1524 }
1525
1526 return 0;
1527 }
1528
1529 static int move_netdev(const char *name, pid_t pid)
1530 {
1531 char directory[MAXPATHLEN];
1532 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
1533 return lxc_dir_for_each(name, directory, move_netdev_cb, &pid);
1534 }
1535
1536 int conf_create_network(const char *name, pid_t pid)
1537 {
1538 if (instanciate_netdev(name, pid)) {
1539 ERROR("failed to instantiate the network devices");
1540 return -1;
1541 }
1542
1543 if (move_netdev(name, pid)) {
1544 ERROR("failed to move the netdev to the container");
1545 return -1;
1546 }
1547
1548 return 0;
1549 }
1550
1551 int lxc_create_tty(const char *name, struct lxc_tty_info *tty_info)
1552 {
1553 char path[MAXPATHLEN];
1554 char tty[4];
1555 int i, ret = -1;
1556
1557 tty_info->nbtty = 0;
1558
1559 if (!conf_has_tty(name))
1560 return 0;
1561
1562 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
1563
1564 if (read_info(path, "tty", tty, sizeof(tty)) < 0) {
1565 SYSERROR("failed to read tty info");
1566 goto out;
1567 }
1568
1569 tty_info->nbtty = atoi(tty);
1570 tty_info->pty_info =
1571 malloc(sizeof(*tty_info->pty_info)*tty_info->nbtty);
1572
1573 if (!tty_info->pty_info) {
1574 SYSERROR("failed to allocate pty_info");
1575 goto out;
1576 }
1577
1578 for (i = 0; i < tty_info->nbtty; i++) {
1579
1580 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1581
1582 if (openpty(&pty_info->master, &pty_info->slave,
1583 pty_info->name, NULL, NULL)) {
1584 SYSERROR("failed to create pty #%d", i);
1585 goto out_free;
1586 }
1587
1588 /* Prevent leaking the file descriptors to the container */
1589 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
1590 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
1591
1592 pty_info->busy = 0;
1593 }
1594
1595 ret = 0;
1596
1597 INFO("tty's configured");
1598
1599 out:
1600 return ret;
1601
1602 out_free:
1603 free(tty_info->pty_info);
1604 goto out;
1605 }
1606
1607 void lxc_delete_tty(struct lxc_tty_info *tty_info)
1608 {
1609 int i;
1610
1611 for (i = 0; i < tty_info->nbtty; i++) {
1612 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1613
1614 close(pty_info->master);
1615 close(pty_info->slave);
1616 }
1617
1618 free(tty_info->pty_info);
1619 tty_info->nbtty = 0;
1620 }
1621
1622 extern int lxc_config_read(const char *file, struct lxc_conf *conf);
1623
1624 int lxc_setup(const char *name, const char *cons,
1625 const struct lxc_tty_info *tty_info)
1626
1627 {
1628 struct lxc_conf lxc_conf;
1629 char path[MAXPATHLEN];
1630
1631 if (lxc_conf_init(&lxc_conf)) {
1632 ERROR("failed to initialize the configuration");
1633 return -1;
1634 }
1635
1636 snprintf(path, sizeof(path), LXCPATH "/%s/config", name);
1637
1638 if (!access(path, F_OK)) {
1639
1640 if (lxc_config_read(path, &lxc_conf)) {
1641 ERROR("failed to read the configuration file");
1642 return -1;
1643 }
1644 }
1645
1646 if (setup_utsname(lxc_conf.utsname)) {
1647 ERROR("failed to setup the utsname for '%s'", name);
1648 return -1;
1649 }
1650
1651 if (!lxc_list_empty(&lxc_conf.networks) && setup_network(name)) {
1652 ERROR("failed to setup the network for '%s'", name);
1653 return -1;
1654 }
1655
1656 if (setup_cgroup(name, &lxc_conf.cgroup)) {
1657 ERROR("failed to setup the cgroups for '%s'", name);
1658 return -1;
1659 }
1660
1661 if (setup_mount(lxc_conf.fstab)) {
1662 ERROR("failed to setup the mounts for '%s'", name);
1663 return -1;
1664 }
1665
1666 if (setup_console(lxc_conf.rootfs, cons)) {
1667 ERROR("failed to setup the console for '%s'", name);
1668 return -1;
1669 }
1670
1671 if (setup_tty(lxc_conf.rootfs, tty_info)) {
1672 ERROR("failed to setup the ttys for '%s'", name);
1673 return -1;
1674 }
1675
1676 if (setup_rootfs(lxc_conf.rootfs)) {
1677 ERROR("failed to set rootfs for '%s'", name);
1678 return -1;
1679 }
1680
1681 if (setup_pts(lxc_conf.pts)) {
1682 ERROR("failed to setup the new pts instance");
1683 return -1;
1684 }
1685
1686 NOTICE("'%s' is setup.", name);
1687
1688 return 0;
1689 }