]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/conf.c
clean up and factor out some code
[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)(struct lxc_netdev *);
67
68 struct mount_opt {
69 char *name;
70 int clear;
71 int flag;
72 };
73
74 static int instanciate_veth(struct lxc_netdev *);
75 static int instanciate_macvlan(struct lxc_netdev *);
76 static int instanciate_phys(struct lxc_netdev *);
77 static int instanciate_empty(struct lxc_netdev *);
78
79 static instanciate_cb netdev_conf[MAXCONFTYPE + 1] = {
80 [VETH] = instanciate_veth,
81 [MACVLAN] = instanciate_macvlan,
82 [PHYS] = instanciate_phys,
83 [EMPTY] = instanciate_empty,
84 };
85
86 static struct mount_opt mount_opt[] = {
87 { "defaults", 0, 0 },
88 { "ro", 0, MS_RDONLY },
89 { "rw", 1, MS_RDONLY },
90 { "suid", 1, MS_NOSUID },
91 { "nosuid", 0, MS_NOSUID },
92 { "dev", 1, MS_NODEV },
93 { "nodev", 0, MS_NODEV },
94 { "exec", 1, MS_NOEXEC },
95 { "noexec", 0, MS_NOEXEC },
96 { "sync", 0, MS_SYNCHRONOUS },
97 { "async", 1, MS_SYNCHRONOUS },
98 { "remount", 0, MS_REMOUNT },
99 { "mand", 0, MS_MANDLOCK },
100 { "nomand", 1, MS_MANDLOCK },
101 { "atime", 1, MS_NOATIME },
102 { "noatime", 0, MS_NOATIME },
103 { "diratime", 1, MS_NODIRATIME },
104 { "nodiratime", 0, MS_NODIRATIME },
105 { "bind", 0, MS_BIND },
106 { "rbind", 0, MS_BIND|MS_REC },
107 { NULL, 0, 0 },
108 };
109
110 static int delete_info(const char *path, const char *file)
111 {
112 char info[MAXPATHLEN];
113 int ret;
114
115 snprintf(info, MAXPATHLEN, "%s/%s", path, file);
116 ret = unlink(info);
117
118 return ret;
119 }
120
121 static int configure_find_fstype_cb(void* buffer, void *data)
122 {
123 struct cbarg {
124 const char *rootfs;
125 const char *testdir;
126 char *fstype;
127 int mntopt;
128 } *cbarg = data;
129
130 char *fstype;
131
132 /* we don't try 'nodev' entries */
133 if (strstr(buffer, "nodev"))
134 return 0;
135
136 fstype = buffer;
137 fstype += lxc_char_left_gc(fstype, strlen(fstype));
138 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
139
140 if (mount(cbarg->rootfs, cbarg->testdir, fstype, cbarg->mntopt, NULL))
141 return 0;
142
143 /* found ! */
144 umount(cbarg->testdir);
145 strcpy(cbarg->fstype, fstype);
146
147 return 1;
148 }
149
150 /* find the filesystem type with brute force */
151 static int configure_find_fstype(const char *rootfs, char *fstype, int mntopt)
152 {
153 int i, found;
154 char buffer[MAXPATHLEN];
155
156 struct cbarg {
157 const char *rootfs;
158 const char *testdir;
159 char *fstype;
160 int mntopt;
161 } cbarg = {
162 .rootfs = rootfs,
163 .fstype = fstype,
164 .mntopt = mntopt,
165 };
166
167 /* first we check with /etc/filesystems, in case the modules
168 * are auto-loaded and fall back to the supported kernel fs
169 */
170 char *fsfile[] = {
171 "/etc/filesystems",
172 "/proc/filesystems",
173 };
174
175 cbarg.testdir = tempnam("/tmp", "lxc-");
176 if (!cbarg.testdir) {
177 SYSERROR("failed to build a temp name");
178 return -1;
179 }
180
181 if (mkdir(cbarg.testdir, 0755)) {
182 SYSERROR("failed to create temporary directory");
183 return -1;
184 }
185
186 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
187
188 found = lxc_file_for_each_line(fsfile[i],
189 configure_find_fstype_cb,
190 buffer, sizeof(buffer), &cbarg);
191
192 if (found < 0) {
193 SYSERROR("failed to read '%s'", fsfile[i]);
194 goto out;
195 }
196
197 if (found)
198 break;
199 }
200
201 if (!found) {
202 ERROR("failed to determine fs type for '%s'", rootfs);
203 goto out;
204 }
205
206 out:
207 rmdir(cbarg.testdir);
208 return found - 1;
209 }
210
211 static int configure_rootfs_dir_cb(const char *rootfs, const char *absrootfs,
212 FILE *f)
213 {
214 return fprintf(f, "%s %s none rbind 0 0\n", absrootfs, rootfs);
215 }
216
217 static int configure_rootfs_blk_cb(const char *rootfs, const char *absrootfs,
218 FILE *f)
219 {
220 char fstype[MAXPATHLEN];
221
222 if (configure_find_fstype(absrootfs, fstype, 0)) {
223 ERROR("failed to configure mount for block device '%s'",
224 absrootfs);
225 return -1;
226 }
227
228 return fprintf(f, "%s %s %s defaults 0 0\n", absrootfs, rootfs, fstype);
229 }
230
231 static int configure_rootfs(const char *name, const char *rootfs)
232 {
233 char path[MAXPATHLEN];
234 char absrootfs[MAXPATHLEN];
235 char fstab[MAXPATHLEN];
236 struct stat s;
237 FILE *f;
238 int i, ret;
239
240 typedef int (*rootfs_cb)(const char *, const char *, FILE *);
241
242 struct rootfs_type {
243 int type;
244 rootfs_cb cb;
245 } rtfs_type[] = {
246 { __S_IFDIR, configure_rootfs_dir_cb },
247 { __S_IFBLK, configure_rootfs_blk_cb },
248 };
249
250 if (!realpath(rootfs, absrootfs)) {
251 SYSERROR("failed to get real path for '%s'", rootfs);
252 return -1;
253 }
254
255 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
256
257 if (mkdir(path, 0755)) {
258 SYSERROR("failed to create the '%s' directory", path);
259 return -1;
260 }
261
262 if (access(absrootfs, F_OK)) {
263 SYSERROR("'%s' is not accessible", absrootfs);
264 return -1;
265 }
266
267 if (stat(absrootfs, &s)) {
268 SYSERROR("failed to stat '%s'", absrootfs);
269 return -1;
270 }
271
272 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
273
274 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
275 continue;
276
277 snprintf(fstab, MAXPATHLEN, LXCPATH "/%s/fstab", name);
278
279 f = fopen(fstab, "a+");
280 if (!f) {
281 SYSERROR("failed to open fstab file");
282 return -1;
283 }
284
285 ret = rtfs_type[i].cb(path, absrootfs, f);
286
287 fclose(f);
288
289 if (ret < 0) {
290 ERROR("failed to add rootfs mount in fstab");
291 return -1;
292 }
293
294 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs/rootfs", name);
295
296 return symlink(absrootfs, path);
297 }
298
299 ERROR("unsupported rootfs type for '%s'", absrootfs);
300 return -1;
301 }
302
303 static int unconfigure_ip_addresses(const char *directory)
304 {
305 char path[MAXPATHLEN];
306
307 snprintf(path, MAXPATHLEN, "%s/ipv4", directory);
308 delete_info(path, "addresses");
309 rmdir(path);
310
311 snprintf(path, MAXPATHLEN, "%s/ipv6", directory);
312 delete_info(path, "addresses");
313 rmdir(path);
314
315 return 0;
316 }
317
318 static int unconfigure_network_cb(const char *name, const char *directory,
319 const char *file, void *data)
320 {
321 char path[MAXPATHLEN];
322
323 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
324 delete_info(path, "ifindex");
325 delete_info(path, "name");
326 delete_info(path, "addr");
327 delete_info(path, "link");
328 delete_info(path, "hwaddr");
329 delete_info(path, "mtu");
330 delete_info(path, "up");
331 unconfigure_ip_addresses(path);
332 rmdir(path);
333
334 return 0;
335 }
336
337 static int unconfigure_network(const char *name)
338 {
339 char directory[MAXPATHLEN];
340
341 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
342 lxc_dir_for_each(name, directory, unconfigure_network_cb, NULL);
343 rmdir(directory);
344
345 return 0;
346 }
347
348 static int unconfigure_cgroup_cb(const char *name, const char *directory,
349 const char *file, void *data)
350 {
351 return delete_info(directory, file);
352 }
353
354 static int unconfigure_cgroup(const char *name)
355 {
356 char filename[MAXPATHLEN];
357 struct stat s;
358
359 snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
360
361 if (stat(filename, &s)) {
362 SYSERROR("failed to stat '%s'", filename);
363 return -1;
364 }
365
366 if (S_ISDIR(s.st_mode)) {
367 /* old cgroup configuration */
368 lxc_dir_for_each(name, filename, unconfigure_cgroup_cb, NULL);
369 rmdir(filename);
370 } else {
371 unlink(filename);
372 }
373
374 return 0;
375 }
376
377 static int unconfigure_rootfs(const char *name)
378 {
379 char path[MAXPATHLEN];
380
381 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
382
383 #warning deprecated code to be removed in the next version
384
385 /* ugly but for backward compatibily, */
386 delete_info(path, "rootfs");
387 rmdir(path);
388 unlink(path);
389
390 return 0;
391 }
392
393 static int unconfigure_pts(const char *name)
394 {
395 char path[MAXPATHLEN];
396
397 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
398 delete_info(path, "pts");
399
400 return 0;
401 }
402
403 static int unconfigure_tty(const char *name)
404 {
405 char path[MAXPATHLEN];
406
407 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
408 delete_info(path, "tty");
409
410 return 0;
411 }
412
413 static int unconfigure_mount(const char *name)
414 {
415 char path[MAXPATHLEN];
416
417 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
418 delete_info(path, "fstab");
419
420 return 0;
421 }
422
423 static int unconfigure_utsname(const char *name)
424 {
425 char path[MAXPATHLEN];
426
427 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
428 delete_info(path, "utsname");
429
430 return 0;
431 }
432
433 static int setup_utsname(struct utsname *utsname)
434 {
435 if (!utsname)
436 return 0;
437
438 if (sethostname(utsname->nodename, strlen(utsname->nodename))) {
439 SYSERROR("failed to set the hostname to '%s'", utsname->nodename);
440 return -1;
441 }
442
443 INFO("'%s' hostname has been setup", utsname->nodename);
444
445 return 0;
446 }
447
448 static int setup_tty(const char *rootfs, const struct lxc_tty_info *tty_info)
449 {
450 char path[MAXPATHLEN];
451 int i;
452
453 for (i = 0; i < tty_info->nbtty; i++) {
454
455 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
456
457 snprintf(path, sizeof(path), "%s/dev/tty%d",
458 rootfs ? rootfs : "", i + 1);
459
460 /* At this point I can not use the "access" function
461 * to check the file is present or not because it fails
462 * with EACCES errno and I don't know why :( */
463
464 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
465 WARN("failed to mount '%s'->'%s'",
466 pty_info->name, path);
467 continue;
468 }
469 }
470
471 INFO("%d tty(s) has been setup", tty_info->nbtty);
472
473 return 0;
474 }
475
476 static int setup_rootfs(const char *rootfs)
477 {
478 char *tmpname;
479 int ret = -1;
480
481 if (!rootfs)
482 return 0;
483
484 tmpname = tempnam("/tmp", "lxc-rootfs");
485 if (!tmpname) {
486 SYSERROR("failed to generate temporary name");
487 return -1;
488 }
489
490 if (mkdir(tmpname, 0700)) {
491 SYSERROR("failed to create temporary directory '%s'", tmpname);
492 return -1;
493 }
494
495 if (mount(rootfs, tmpname, "none", MS_BIND|MS_REC, NULL)) {
496 SYSERROR("failed to mount '%s'->'%s'", rootfs, tmpname);
497 goto out;
498 }
499
500 if (chroot(tmpname)) {
501 SYSERROR("failed to set chroot %s", tmpname);
502 goto out;
503 }
504
505 if (chdir(getenv("HOME")) && chdir("/")) {
506 SYSERROR("failed to change to home directory");
507 goto out;
508 }
509
510 INFO("chrooted to '%s'", rootfs);
511
512 ret = 0;
513 out:
514 rmdir(tmpname);
515 return ret;
516 }
517
518 static int setup_pts(int pts)
519 {
520 if (!pts)
521 return 0;
522
523 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
524 SYSERROR("failed to umount 'dev/pts'");
525 return -1;
526 }
527
528 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance")) {
529 SYSERROR("failed to mount a new instance of '/dev/pts'");
530 return -1;
531 }
532
533 if (chmod("/dev/pts/ptmx", 0666)) {
534 SYSERROR("failed to set permission for '/dev/pts/ptmx'");
535 return -1;
536 }
537
538 if (access("/dev/ptmx", F_OK)) {
539 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
540 goto out;
541 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
542 return -1;
543 }
544
545 /* fallback here, /dev/pts/ptmx exists just mount bind */
546 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
547 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
548 return -1;
549 }
550
551 INFO("created new pts instance");
552
553 out:
554 return 0;
555 }
556
557 static int setup_console(const char *rootfs, const char *tty)
558 {
559 char console[MAXPATHLEN];
560
561 snprintf(console, sizeof(console), "%s/dev/console",
562 rootfs ? rootfs : "");
563
564 /* we have the rootfs with /dev/console but no tty
565 * to be used as console, let's remap /dev/console
566 * to /dev/null to avoid to log to the system console
567 */
568 if (rootfs && !tty[0]) {
569
570 if (!access(console, F_OK)) {
571
572 if (mount("/dev/null", console, "none", MS_BIND, 0)) {
573 SYSERROR("failed to mount '/dev/null'->'%s'",
574 console);
575 return -1;
576 }
577 }
578 }
579
580 if (!tty[0])
581 return 0;
582
583 if (access(console, R_OK|W_OK))
584 return 0;
585
586 if (mount(tty, console, "none", MS_BIND, 0)) {
587 ERROR("failed to mount the console");
588 return -1;
589 }
590
591 INFO("console '%s' mounted to '%s'", tty, console);
592
593 return 0;
594 }
595
596 static int setup_cgroup(const char *name, struct lxc_list *cgroups)
597 {
598 struct lxc_list *iterator;
599 struct lxc_cgroup *cg;
600
601 if (lxc_list_empty(cgroups))
602 return 0;
603
604 lxc_list_for_each(iterator, cgroups) {
605
606 cg = iterator->elem;
607
608 if (lxc_cgroup_set(name, cg->subsystem, cg->value))
609 break;
610
611 DEBUG("cgroup '%s' set to '%s'", cg->subsystem, cg->value);
612 }
613
614 INFO("cgroup has been setup");
615
616 return 0;
617 }
618
619 static void parse_mntopt(char *opt, unsigned long *flags, char **data)
620 {
621 struct mount_opt *mo;
622
623 /* If opt is found in mount_opt, set or clear flags.
624 * Otherwise append it to data. */
625
626 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
627 if (!strncmp(opt, mo->name, strlen(mo->name))) {
628 if (mo->clear)
629 *flags &= ~mo->flag;
630 else
631 *flags |= mo->flag;
632 return;
633 }
634 }
635
636 if (strlen(*data))
637 strcat(*data, ",");
638 strcat(*data, opt);
639 }
640
641 static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
642 char **mntdata)
643 {
644 char *s, *data;
645 char *p, *saveptr = NULL;
646
647 if (!mntent->mnt_opts)
648 return 0;
649
650 s = strdup(mntent->mnt_opts);
651 if (!s) {
652 SYSERROR("failed to allocate memory");
653 return -1;
654 }
655
656 data = malloc(strlen(s) + 1);
657 if (!data) {
658 SYSERROR("failed to allocate memory");
659 free(s);
660 return -1;
661 }
662 *data = 0;
663
664 for (p = strtok_r(s, ",", &saveptr); p != NULL;
665 p = strtok_r(NULL, ",", &saveptr))
666 parse_mntopt(p, mntflags, &data);
667
668 if (*data)
669 *mntdata = data;
670 else
671 free(data);
672 free(s);
673
674 return 0;
675 }
676
677 static int setup_mount(const char *fstab)
678 {
679 struct mntent *mntent;
680 FILE *file;
681 int ret = -1;
682 unsigned long mntflags;
683 char *mntdata;
684
685 if (!fstab)
686 return 0;
687
688 file = setmntent(fstab, "r");
689 if (!file) {
690 SYSERROR("failed to use '%s'", fstab);
691 return -1;
692 }
693
694 while ((mntent = getmntent(file))) {
695
696 mntflags = 0;
697 mntdata = NULL;
698 if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
699 ERROR("failed to parse mount option '%s'",
700 mntent->mnt_opts);
701 goto out;
702 }
703
704 if (mount(mntent->mnt_fsname, mntent->mnt_dir,
705 mntent->mnt_type, mntflags, mntdata)) {
706 SYSERROR("failed to mount '%s' on '%s'",
707 mntent->mnt_fsname, mntent->mnt_dir);
708 goto out;
709 }
710
711 DEBUG("mounted %s on %s, type %s", mntent->mnt_fsname,
712 mntent->mnt_dir, mntent->mnt_type);
713
714 free(mntdata);
715 }
716
717 ret = 0;
718
719 INFO("mount points have been setup");
720 out:
721 endmntent(file);
722 return ret;
723 }
724
725 static int setup_hw_addr(char *hwaddr, const char *ifname)
726 {
727 struct sockaddr sockaddr;
728 struct ifreq ifr;
729 int ret, fd;
730
731 if (lxc_convert_mac(hwaddr, &sockaddr)) {
732 ERROR("conversion has failed");
733 return -1;
734 }
735
736 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
737 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
738
739 fd = socket(AF_INET, SOCK_DGRAM, 0);
740 if (fd < 0) {
741 ERROR("socket failure : %s", strerror(errno));
742 return -1;
743 }
744
745 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
746 close(fd);
747 if (ret)
748 ERROR("ioctl failure : %s", strerror(errno));
749
750 DEBUG("mac address '%s' on '%s' has been setup", hwaddr, ifname);
751
752 return ret;
753 }
754
755 static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
756 {
757 struct lxc_list *iterator;
758 struct lxc_inetdev *inetdev;
759
760 lxc_list_for_each(iterator, ip) {
761
762 inetdev = iterator->elem;
763
764 if (lxc_ip_addr_add(AF_INET, ifindex,
765 &inetdev->addr, inetdev->prefix)) {
766 return -1;
767 }
768 }
769
770 return 0;
771 }
772
773 static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
774 {
775 struct lxc_list *iterator;
776 struct lxc_inetdev *inet6dev;
777
778 lxc_list_for_each(iterator, ip) {
779
780 inet6dev = iterator->elem;
781
782 if (lxc_ip_addr_add(AF_INET6, ifindex,
783 & inet6dev->addr, inet6dev->prefix))
784 return -1;
785 }
786
787 return 0;
788 }
789
790 static int setup_netdev(struct lxc_netdev *netdev)
791 {
792 char ifname[IFNAMSIZ];
793 char *current_ifname = ifname;
794
795 /* empty network namespace */
796 if (!netdev->ifindex) {
797 if (netdev->flags | IFF_UP) {
798 if (lxc_device_up("lo")) {
799 ERROR("failed to set the loopback up");
800 return -1;
801 }
802 return 0;
803 }
804 }
805
806 /* retrieve the name of the interface */
807 if (!if_indextoname(netdev->ifindex, current_ifname)) {
808 ERROR("no interface corresponding to index '%d'",
809 netdev->ifindex);
810 return -1;
811 }
812
813 /* default: let the system to choose one interface name */
814 if (!netdev->newname)
815 netdev->newname = "eth%d";
816
817 /* rename the interface name */
818 if (lxc_device_rename(ifname, netdev->newname)) {
819 ERROR("failed to rename %s->%s", ifname, current_ifname);
820 return -1;
821 }
822
823 /* Re-read the name of the interface because its name has changed
824 * and would be automatically allocated by the system
825 */
826 if (!if_indextoname(netdev->ifindex, current_ifname)) {
827 ERROR("no interface corresponding to index '%d'",
828 netdev->ifindex);
829 return -1;
830 }
831
832 /* set a mac address */
833 if (netdev->hwaddr) {
834 if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
835 ERROR("failed to setup hw address for '%s'",
836 current_ifname);
837 return -1;
838 }
839 }
840
841 /* setup ipv4 addresses on the interface */
842 if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
843 ERROR("failed to setup ip addresses for '%s'",
844 ifname);
845 return -1;
846 }
847
848 /* setup ipv6 addresses on the interface */
849 if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
850 ERROR("failed to setup ipv6 addresses for '%s'",
851 ifname);
852 return -1;
853 }
854
855 /* set the network device up */
856 if (netdev->flags | IFF_UP) {
857 if (lxc_device_up(current_ifname)) {
858 ERROR("failed to set '%s' up", current_ifname);
859 return -1;
860 }
861
862 /* the network is up, make the loopback up too */
863 if (lxc_device_up("lo")) {
864 ERROR("failed to set the loopback up");
865 return -1;
866 }
867 }
868
869 DEBUG("'%s' has been setup", current_ifname);
870
871 return 0;
872 }
873
874 static int setup_network(struct lxc_list *network)
875 {
876 struct lxc_list *iterator;
877 struct lxc_netdev *netdev;
878
879 lxc_list_for_each(iterator, network) {
880
881 netdev = iterator->elem;
882
883 if (setup_netdev(netdev)) {
884 ERROR("failed to setup netdev");
885 return -1;
886 }
887 }
888
889 if (!lxc_list_empty(network))
890 INFO("network has been setup");
891
892 return 0;
893 }
894
895 int conf_has(const char *name, const char *info)
896 {
897 int ret = 0;
898 char path[MAXPATHLEN];
899 struct stat st;
900
901 snprintf(path, MAXPATHLEN, LXCPATH "/%s/%s", name, info);
902
903 if (!stat(path, &st) || !lstat(path, &st)) {
904 ret = 1;
905 goto out;
906 }
907
908 if (errno == ENOENT) {
909 ret = 0;
910 goto out;
911 }
912
913 SYSERROR("failed to stat %s info", info);
914 out:
915 return ret;
916 }
917
918 int lxc_conf_init(struct lxc_conf *conf)
919 {
920 conf->rootfs = NULL;
921 conf->fstab = NULL;
922 conf->utsname = NULL;
923 conf->tty = 0;
924 conf->pts = 0;
925 conf->console[0] = '\0';
926 lxc_list_init(&conf->cgroup);
927 lxc_list_init(&conf->network);
928 return 0;
929 }
930
931 int lxc_unconfigure(const char *name)
932 {
933 if (conf_has_utsname(name) && unconfigure_utsname(name))
934 ERROR("failed to cleanup utsname");
935
936 if (conf_has_network(name) && unconfigure_network(name))
937 ERROR("failed to cleanup the network");
938
939 if (conf_has_cgroup(name) && unconfigure_cgroup(name))
940 ERROR("failed to cleanup cgroup");
941
942 if (conf_has_tty(name) && unconfigure_tty(name))
943 ERROR("failed to cleanup tty");
944
945 if (conf_has_rootfs(name) && unconfigure_rootfs(name))
946 ERROR("failed to cleanup rootfs");
947
948 if (conf_has_fstab(name) && unconfigure_mount(name))
949 ERROR("failed to cleanup mount");
950
951 if (conf_has_pts(name) && unconfigure_pts(name))
952 ERROR("failed to cleanup pts");
953
954 return 0;
955 }
956
957 static int instanciate_veth(struct lxc_netdev *netdev)
958 {
959 char veth1[IFNAMSIZ];
960 char veth2[IFNAMSIZ];
961 int ret = -1;
962
963 snprintf(veth1, sizeof(veth1), "vethXXXXXX");
964 snprintf(veth2, sizeof(veth2), "vethXXXXXX");
965
966 mktemp(veth1);
967 mktemp(veth2);
968
969 if (!strlen(veth1) || !strlen(veth2)) {
970 ERROR("failed to allocate a temporary name");
971 return -1;
972 }
973
974 if (lxc_veth_create(veth1, veth2)) {
975 ERROR("failed to create %s-%s/%s",
976 veth1, veth2, netdev->ifname);
977 goto out;
978 }
979
980 if (netdev->mtu) {
981 if (lxc_device_set_mtu(veth1, atoi(netdev->mtu))) {
982 ERROR("failed to set mtu '%s' for '%s'",
983 netdev->mtu, veth1);
984 goto out_delete;
985 }
986
987 if (lxc_device_set_mtu(veth2, atoi(netdev->mtu))) {
988 ERROR("failed to set mtu '%s' for '%s'",
989 netdev->mtu, veth2);
990 goto out_delete;
991 }
992 }
993
994 if (lxc_bridge_attach(netdev->ifname, veth1)) {
995 ERROR("failed to attach '%s' to the bridge '%s'",
996 veth1, netdev->ifname);
997 goto out_delete;
998 }
999
1000 netdev->ifindex = if_nametoindex(veth2);
1001 if (!netdev->ifindex) {
1002 ERROR("failed to retrieve the index for %s", veth2);
1003 goto out_delete;
1004 }
1005
1006 if (netdev->flags & IFF_UP) {
1007 if (lxc_device_up(veth1)) {
1008 ERROR("failed to set %s up", veth1);
1009 goto out_delete;
1010 }
1011 }
1012
1013 DEBUG("instanciated veth '%s/%s', index is '%d'",
1014 veth1, veth2, netdev->ifindex);
1015
1016 ret = 0;
1017 out:
1018 return ret;
1019
1020 out_delete:
1021 lxc_device_delete(veth1);
1022 goto out;
1023 }
1024 static int instanciate_macvlan(struct lxc_netdev *netdev)
1025 {
1026 char peer[IFNAMSIZ];
1027 int ret = -1;
1028
1029 snprintf(peer, sizeof(peer), "mcXXXXXX");
1030
1031 mktemp(peer);
1032
1033 if (!strlen(peer)) {
1034 ERROR("failed to make a temporary name");
1035 return -1;
1036 }
1037
1038 if (lxc_macvlan_create(netdev->ifname, peer)) {
1039 ERROR("failed to create macvlan interface '%s' on '%s'",
1040 peer, netdev->ifname);
1041 goto out;
1042 }
1043
1044 netdev->ifindex = if_nametoindex(peer);
1045 if (!netdev->ifindex) {
1046 ERROR("failed to retrieve the index for %s", peer);
1047 goto out_delete;
1048 }
1049
1050 DEBUG("instanciated macvlan '%s', index is '%d'", peer, netdev->ifindex);
1051
1052 ret = 0;
1053 out:
1054 return ret;
1055
1056 out_delete:
1057 lxc_device_delete(peer);
1058 goto out;
1059 }
1060
1061 static int instanciate_phys(struct lxc_netdev *netdev)
1062 {
1063 netdev->ifindex = if_nametoindex(netdev->ifname);
1064 if (!netdev->ifindex) {
1065 ERROR("failed to retrieve the index for %s", netdev->ifname);
1066 return -1;
1067 }
1068
1069 return 0;
1070 }
1071
1072 static int instanciate_empty(struct lxc_netdev *netdev)
1073 {
1074 netdev->ifindex = 0;
1075 return 0;
1076 }
1077
1078 int lxc_create_network(struct lxc_list *network)
1079 {
1080 struct lxc_list *iterator;
1081 struct lxc_netdev *netdev;
1082
1083 lxc_list_for_each(iterator, network) {
1084
1085 netdev = iterator->elem;
1086
1087 if (netdev->type < 0 || netdev->type > MAXCONFTYPE) {
1088 ERROR("invalid network configuration type '%d'",
1089 netdev->type);
1090 return -1;
1091 }
1092
1093 if (netdev_conf[netdev->type](netdev)) {
1094 ERROR("failed to create netdev");
1095 return -1;
1096 }
1097 }
1098
1099 return 0;
1100 }
1101
1102 int lxc_assign_network(struct lxc_list *network, pid_t pid)
1103 {
1104 struct lxc_list *iterator;
1105 struct lxc_netdev *netdev;
1106
1107 lxc_list_for_each(iterator, network) {
1108
1109 netdev = iterator->elem;
1110
1111 if (lxc_device_move(netdev->ifindex, pid)) {
1112 ERROR("failed to move '%s' to the container",
1113 netdev->ifname);
1114 return -1;
1115 }
1116
1117 DEBUG("move '%s' to '%d'", netdev->ifname, pid);
1118 }
1119
1120 return 0;
1121 }
1122
1123 int lxc_create_tty(const char *name, struct lxc_conf *conf)
1124 {
1125 struct lxc_tty_info *tty_info = &conf->tty_info;
1126 int i, ret = -1;
1127
1128 /* no tty in the configuration */
1129 if (!conf->tty)
1130 return 0;
1131
1132 tty_info->nbtty = conf->tty;
1133 tty_info->pty_info =
1134 malloc(sizeof(*tty_info->pty_info)*tty_info->nbtty);
1135
1136 if (!tty_info->pty_info) {
1137 SYSERROR("failed to allocate pty_info");
1138 goto out;
1139 }
1140
1141 for (i = 0; i < tty_info->nbtty; i++) {
1142
1143 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1144
1145 if (openpty(&pty_info->master, &pty_info->slave,
1146 pty_info->name, NULL, NULL)) {
1147 SYSERROR("failed to create pty #%d", i);
1148 goto out_free;
1149 }
1150
1151 /* Prevent leaking the file descriptors to the container */
1152 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
1153 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
1154
1155 pty_info->busy = 0;
1156 }
1157
1158 ret = 0;
1159
1160 INFO("tty's configured");
1161
1162 out:
1163 return ret;
1164
1165 out_free:
1166 free(tty_info->pty_info);
1167 goto out;
1168 }
1169
1170 void lxc_delete_tty(struct lxc_tty_info *tty_info)
1171 {
1172 int i;
1173
1174 for (i = 0; i < tty_info->nbtty; i++) {
1175 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1176
1177 close(pty_info->master);
1178 close(pty_info->slave);
1179 }
1180
1181 free(tty_info->pty_info);
1182 tty_info->nbtty = 0;
1183 }
1184
1185 int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
1186 {
1187 if (setup_utsname(lxc_conf->utsname)) {
1188 ERROR("failed to setup the utsname for '%s'", name);
1189 return -1;
1190 }
1191
1192 if (setup_network(&lxc_conf->network)) {
1193 ERROR("failed to setup the network for '%s'", name);
1194 return -1;
1195 }
1196
1197 if (setup_cgroup(name, &lxc_conf->cgroup)) {
1198 ERROR("failed to setup the cgroups for '%s'", name);
1199 return -1;
1200 }
1201
1202 if (setup_mount(lxc_conf->fstab)) {
1203 ERROR("failed to setup the mounts for '%s'", name);
1204 return -1;
1205 }
1206
1207 if (setup_console(lxc_conf->rootfs, lxc_conf->console)) {
1208 ERROR("failed to setup the console for '%s'", name);
1209 return -1;
1210 }
1211
1212 if (setup_tty(lxc_conf->rootfs, &lxc_conf->tty_info)) {
1213 ERROR("failed to setup the ttys for '%s'", name);
1214 return -1;
1215 }
1216
1217 if (setup_rootfs(lxc_conf->rootfs)) {
1218 ERROR("failed to set rootfs for '%s'", name);
1219 return -1;
1220 }
1221
1222 if (setup_pts(lxc_conf->pts)) {
1223 ERROR("failed to setup the new pts instance");
1224 return -1;
1225 }
1226
1227 NOTICE("'%s' is setup.", name);
1228
1229 return 0;
1230 }