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