]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/conf.c
lxc: use new logging system
[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_utsname(const char *name, struct utsname *utsname)
334 {
335 char path[MAXPATHLEN];
336
337 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
338
339 if (write_info(path, "utsname", utsname->nodename)) {
340 ERROR("failed to write the utsname info");
341 return -1;
342 }
343
344 return 0;
345 }
346
347 static int configure_network(const char *name, struct lxc_list *network)
348 {
349 struct lxc_list *iterator;
350 struct lxc_network *n;
351 char networkpath[MAXPATHLEN];
352 char path[MAXPATHLEN];
353 int err = -1;
354
355 if (lxc_list_empty(network))
356 return 0;
357
358 snprintf(networkpath, MAXPATHLEN, LXCPATH "/%s/network", name);
359 if (mkdir(networkpath, 0755)) {
360 SYSERROR("failed to create %s directory", networkpath);
361 goto out;
362 }
363
364 lxc_list_for_each(iterator, network) {
365
366 n = iterator->elem;
367
368 if (n->type < 0 || n->type > MAXCONFTYPE) {
369 ERROR("invalid network configuration type '%d'",
370 n->type);
371 goto out;
372 }
373
374 snprintf(path, MAXPATHLEN, "%s/%s%d", networkpath,
375 netdev_conf[n->type].type,
376 netdev_conf[n->type].count++);
377
378 if (configure_netdev(path, lxc_list_first_elem(&n->netdev))) {
379 ERROR("failed to configure network type %s",
380 netdev_conf[n->type].type);
381 goto out;
382 }
383 }
384
385 err = 0;
386 out:
387 return err;
388 }
389
390 static int configure_cgroup(const char *name, struct lxc_list *cgroup)
391 {
392 char path[MAXPATHLEN];
393 struct lxc_list *iterator;
394 struct lxc_cgroup *cg;
395 FILE *file;
396
397 if (lxc_list_empty(cgroup))
398 return 0;
399
400 snprintf(path, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
401
402 file = fopen(path, "w+");
403 if (!file) {
404 SYSERROR("failed to open '%s'", path);
405 return -1;
406 }
407
408 lxc_list_for_each(iterator, cgroup) {
409 cg = iterator->elem;
410 fprintf(file, "%s=%s\n", cg->subsystem, cg->value);
411 }
412
413 fclose(file);
414
415 return 0;
416 }
417
418 static int configure_tty(const char *name, int tty)
419 {
420 char path[MAXPATHLEN];
421 char *nbtty;
422 int ret;
423
424 if (asprintf(&nbtty, "%d", tty) < 0) {
425 ERROR("failed to convert tty number");
426 return -1;
427 }
428
429 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
430
431 ret = write_info(path, "tty", nbtty);
432 if (ret)
433 ERROR("failed to write the tty info");
434
435 free(nbtty);
436
437 return ret;
438 }
439
440 static int configure_find_fstype_cb(void* buffer, void *data)
441 {
442 struct cbarg {
443 const char *rootfs;
444 const char *testdir;
445 char *fstype;
446 int mntopt;
447 } *cbarg = data;
448
449 char *fstype;
450
451 /* we don't try 'nodev' entries */
452 if (strstr(buffer, "nodev"))
453 return 0;
454
455 fstype = buffer;
456 fstype += lxc_char_left_gc(fstype, strlen(fstype));
457 fstype[lxc_char_right_gc(fstype, strlen(fstype))] = '\0';
458
459 if (mount(cbarg->rootfs, cbarg->testdir, fstype, cbarg->mntopt, NULL))
460 return 0;
461
462 /* found ! */
463 umount(cbarg->testdir);
464 strcpy(cbarg->fstype, fstype);
465
466 return 1;
467 }
468
469 /* find the filesystem type with brute force */
470 static int configure_find_fstype(const char *rootfs, char *fstype, int mntopt)
471 {
472 int i, found;
473 char buffer[MAXPATHLEN];
474
475 struct cbarg {
476 const char *rootfs;
477 const char *testdir;
478 char *fstype;
479 int mntopt;
480 } cbarg = {
481 .rootfs = rootfs,
482 .fstype = fstype,
483 .mntopt = mntopt,
484 };
485
486 /* first we check with /etc/filesystems, in case the modules
487 * are auto-loaded and fall back to the supported kernel fs
488 */
489 char *fsfile[] = {
490 "/etc/filesystems",
491 "/proc/filesystems",
492 };
493
494 cbarg.testdir = tempnam("/tmp", "lxc-");
495 if (!cbarg.testdir) {
496 SYSERROR("failed to build a temp name");
497 return -1;
498 }
499
500 if (mkdir(cbarg.testdir, 0755)) {
501 SYSERROR("failed to create temporary directory");
502 return -1;
503 }
504
505 for (i = 0; i < sizeof(fsfile)/sizeof(fsfile[0]); i++) {
506
507 found = lxc_file_for_each_line(fsfile[i],
508 configure_find_fstype_cb,
509 buffer, sizeof(buffer), &cbarg);
510
511 if (found < 0) {
512 SYSERROR("failed to read '%s'", fsfile[i]);
513 goto out;
514 }
515
516 if (found)
517 break;
518 }
519
520 if (!found) {
521 ERROR("failed to determine fs type for '%s'", rootfs);
522 goto out;
523 }
524
525 out:
526 rmdir(cbarg.testdir);
527 return found - 1;
528 }
529
530 static int configure_rootfs_dir_cb(const char *rootfs, const char *absrootfs,
531 FILE *f)
532 {
533 return fprintf(f, "%s %s none rbind 0 0\n", absrootfs, rootfs);
534 }
535
536 static int configure_rootfs_blk_cb(const char *rootfs, const char *absrootfs,
537 FILE *f)
538 {
539 char fstype[MAXPATHLEN];
540
541 if (configure_find_fstype(absrootfs, fstype, 0)) {
542 ERROR("failed to configure mount for block device '%s'",
543 absrootfs);
544 return -1;
545 }
546
547 return fprintf(f, "%s %s %s defaults 0 0\n", absrootfs, rootfs, fstype);
548 }
549
550 static int configure_rootfs(const char *name, const char *rootfs)
551 {
552 char path[MAXPATHLEN];
553 char absrootfs[MAXPATHLEN];
554 char fstab[MAXPATHLEN];
555 struct stat s;
556 FILE *f;
557 int i, ret;
558
559 typedef int (*rootfs_cb)(const char *, const char *, FILE *);
560
561 struct rootfs_type {
562 int type;
563 rootfs_cb cb;
564 } rtfs_type[] = {
565 { __S_IFDIR, configure_rootfs_dir_cb },
566 { __S_IFBLK, configure_rootfs_blk_cb },
567 };
568
569 if (!realpath(rootfs, absrootfs)) {
570 SYSERROR("failed to get real path for '%s'", rootfs);
571 return -1;
572 }
573
574 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
575
576 if (mkdir(path, 0755)) {
577 SYSERROR("failed to create the '%s' directory", path);
578 return -1;
579 }
580
581 if (access(absrootfs, F_OK)) {
582 SYSERROR("'%s' is not accessible", absrootfs);
583 return -1;
584 }
585
586 if (stat(absrootfs, &s)) {
587 SYSERROR("failed to stat '%s'", absrootfs);
588 return -1;
589 }
590
591 for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
592
593 if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
594 continue;
595
596 snprintf(fstab, MAXPATHLEN, LXCPATH "/%s/fstab", name);
597
598 f = fopen(fstab, "a+");
599 if (!f) {
600 SYSERROR("failed to open fstab file");
601 return -1;
602 }
603
604 ret = rtfs_type[i].cb(path, absrootfs, f);
605
606 fclose(f);
607
608 if (ret < 0) {
609 ERROR("failed to add rootfs mount in fstab");
610 return -1;
611 }
612
613 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs/rootfs", name);
614
615 return symlink(absrootfs, path);
616 }
617
618 ERROR("unsupported rootfs type for '%s'", absrootfs);
619 return -1;
620 }
621
622 static int configure_pts(const char *name, int pts)
623 {
624 char path[MAXPATHLEN];
625 char *maxpts;
626 int ret;
627
628 if (asprintf(&maxpts, "%d", pts) < 0) {
629 ERROR("failed to convert max pts number");
630 return -1;
631 }
632
633 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
634
635 ret = write_info(path, "pts", maxpts);
636 if (ret)
637 ERROR("failed to write the pts info");
638
639 free(maxpts);
640
641 return ret;
642 }
643
644 static int configure_mount(const char *name, const char *fstab)
645 {
646 char path[MAXPATHLEN];
647 struct stat stat;
648 int infd, outfd;
649 void *src, *dst;
650 char c = '\0';
651 int ret = -1;
652
653 snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
654
655 outfd = open(path, O_RDWR|O_CREAT|O_EXCL, 0640);
656 if (outfd < 0) {
657 SYSERROR("failed to creat '%s'", path);
658 goto out;
659 }
660
661 infd = open(fstab, O_RDONLY);
662 if (infd < 0) {
663 SYSERROR("failed to open '%s'", fstab);
664 goto out_open;
665 }
666
667 if (fstat(infd, &stat)) {
668 SYSERROR("failed to stat '%s'", fstab);
669 goto out_open2;
670 }
671
672 if (lseek(outfd, stat.st_size - 1, SEEK_SET) < 0) {
673 SYSERROR("failed to seek dest file '%s'", path);
674 goto out_open2;
675 }
676
677 /* fixup length */
678 if (write(outfd, &c, 1) < 0) {
679 SYSERROR("failed to write to '%s'", path);
680 goto out_open2;
681 }
682
683 src = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, infd, 0L);
684 if (src == MAP_FAILED) {
685 SYSERROR("failed to mmap '%s'", fstab);
686 goto out_open2;
687 }
688
689 dst = mmap(NULL, stat.st_size, PROT_WRITE, MAP_SHARED, outfd, 0L);
690 if (dst == MAP_FAILED) {
691 SYSERROR("failed to mmap '%s'", path);
692 goto out_mmap;
693 }
694
695 memcpy(dst, src, stat.st_size);
696
697 munmap(src, stat.st_size);
698 munmap(dst, stat.st_size);
699
700 ret = 0;
701 out:
702 return ret;
703
704 out_mmap:
705 munmap(src, stat.st_size);
706 out_open2:
707 close(infd);
708 out_open:
709 unlink(path);
710 close(outfd);
711 goto out;
712 }
713
714 static int unconfigure_ip_addresses(const char *directory)
715 {
716 char path[MAXPATHLEN];
717
718 snprintf(path, MAXPATHLEN, "%s/ipv4", directory);
719 delete_info(path, "addresses");
720 rmdir(path);
721
722 snprintf(path, MAXPATHLEN, "%s/ipv6", directory);
723 delete_info(path, "addresses");
724 rmdir(path);
725
726 return 0;
727 }
728
729 static int unconfigure_network_cb(const char *name, const char *directory,
730 const char *file, void *data)
731 {
732 char path[MAXPATHLEN];
733
734 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
735 delete_info(path, "ifindex");
736 delete_info(path, "name");
737 delete_info(path, "addr");
738 delete_info(path, "link");
739 delete_info(path, "hwaddr");
740 delete_info(path, "mtu");
741 delete_info(path, "up");
742 unconfigure_ip_addresses(path);
743 rmdir(path);
744
745 return 0;
746 }
747
748 static int unconfigure_network(const char *name)
749 {
750 char directory[MAXPATHLEN];
751
752 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
753 lxc_dir_for_each(name, directory, unconfigure_network_cb, NULL);
754 rmdir(directory);
755
756 return 0;
757 }
758
759 static int unconfigure_cgroup_cb(const char *name, const char *directory,
760 const char *file, void *data)
761 {
762 return delete_info(directory, file);
763 }
764
765 static int unconfigure_cgroup(const char *name)
766 {
767 char filename[MAXPATHLEN];
768 struct stat s;
769
770 snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
771
772 if (stat(filename, &s)) {
773 SYSERROR("failed to stat '%s'", filename);
774 return -1;
775 }
776
777 if (S_ISDIR(s.st_mode)) {
778 /* old cgroup configuration */
779 lxc_dir_for_each(name, filename, unconfigure_cgroup_cb, NULL);
780 rmdir(filename);
781 } else {
782 unlink(filename);
783 }
784
785 return 0;
786 }
787
788 static int unconfigure_rootfs(const char *name)
789 {
790 char path[MAXPATHLEN];
791
792 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
793
794 #warning deprecated code to be removed in the next version
795
796 /* ugly but for backward compatibily, */
797 delete_info(path, "rootfs");
798 rmdir(path);
799 unlink(path);
800
801 return 0;
802 }
803
804 static int unconfigure_pts(const char *name)
805 {
806 char path[MAXPATHLEN];
807
808 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
809 delete_info(path, "pts");
810
811 return 0;
812 }
813
814 static int unconfigure_tty(const char *name)
815 {
816 char path[MAXPATHLEN];
817
818 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
819 delete_info(path, "tty");
820
821 return 0;
822 }
823
824 static int unconfigure_mount(const char *name)
825 {
826 char path[MAXPATHLEN];
827
828 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
829 delete_info(path, "fstab");
830
831 return 0;
832 }
833
834 static int unconfigure_utsname(const char *name)
835 {
836 char path[MAXPATHLEN];
837
838 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
839 delete_info(path, "utsname");
840
841 return 0;
842 }
843
844 static int setup_utsname(const char *name)
845 {
846 int ret;
847 char path[MAXPATHLEN];
848 struct utsname utsname;
849
850 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
851
852 ret = read_info(path, "utsname", utsname.nodename,
853 sizeof(utsname.nodename));
854 if (ret < 0) {
855 SYSERROR("failed to read utsname info");
856 return -1;
857 }
858
859 if (!ret && sethostname(utsname.nodename, strlen(utsname.nodename))) {
860 SYSERROR("failed to set the hostname to '%s'",
861 utsname.nodename);
862 return -1;
863 }
864
865 return 0;
866 }
867
868 static int setup_tty(const char *name, const struct lxc_tty_info *tty_info)
869 {
870 char path[MAXPATHLEN];
871 int i;
872
873 for (i = 0; i < tty_info->nbtty; i++) {
874
875 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
876
877 if (conf_has_rootfs(name))
878 snprintf(path, MAXPATHLEN,
879 LXCPATH "/%s/rootfs/dev/tty%d", name, i + 1);
880 else
881 snprintf(path, MAXPATHLEN, "/dev/tty%d", i + 1);
882
883 /* At this point I can not use the "access" function
884 * to check the file is present or not because it fails
885 * with EACCES errno and I don't know why :( */
886
887 if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
888 WARN("failed to mount '%s'->'%s'",
889 pty_info->name, path);
890 continue;
891 }
892 }
893
894 return 0;
895 }
896
897 static int setup_rootfs(const char *name)
898 {
899 char path[MAXPATHLEN];
900
901 snprintf(path, MAXPATHLEN, LXCPATH "/%s/rootfs", name);
902
903 if (chroot(path)) {
904 SYSERROR("failed to set chroot %s", path);
905 return -1;
906 }
907
908 if (chdir(getenv("HOME")) && chdir("/")) {
909 SYSERROR("failed to change to home directory");
910 return -1;
911 }
912
913 return 0;
914 }
915
916 static int setup_pts(const char *name)
917 {
918 char mountname[MAXPATHLEN];
919
920 if (!access("/dev/pts/ptmx", F_OK) && umount("/dev/pts")) {
921 SYSERROR("failed to umount 'dev/pts'");
922 return -1;
923 }
924
925 snprintf(mountname, MAXPATHLEN, "%spts", name);
926
927 if (mount(mountname, "/dev/pts", "devpts", MS_MGC_VAL, "newinstance")) {
928 SYSERROR("failed to mount a new instance of '/dev/pts'");
929 return -1;
930 }
931
932 if (chmod("/dev/pts/ptmx", 0666)) {
933 SYSERROR("failed to set permission for '/dev/pts/ptmx'");
934 return -1;
935 }
936
937 if (access("/dev/ptmx", F_OK)) {
938 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
939 goto out;
940 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
941 return -1;
942 }
943
944 /* fallback here, /dev/pts/ptmx exists just mount bind */
945 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0)) {
946 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
947 return -1;
948 }
949 out:
950 return 0;
951 }
952
953 static int setup_console(const char *name, const char *tty)
954 {
955 char console[MAXPATHLEN];
956
957 snprintf(console, MAXPATHLEN, LXCPATH "/%s/rootfs/dev/console", name);
958
959 if (access(console, R_OK|W_OK))
960 return 0;
961
962 if (mount(tty, console, "none", MS_BIND, 0)) {
963 ERROR("failed to mount the console");
964 return -1;
965 }
966
967 return 0;
968 }
969
970 static int setup_cgroup_cb(void* buffer, void *data)
971 {
972 char *key = buffer, *value;
973 char *name = data;
974 int ret;
975
976 value = strchr(key, '=');
977 if (!value)
978 return -1;
979
980 *value = '\0';
981 value += 1;
982
983 ret = lxc_cgroup_set(name, key, value);
984 if (ret)
985 SYSERROR("failed to set cgroup '%s' = '%s' for '%s'",
986 key, value, name);
987 return ret;
988 }
989
990 static int setup_convert_cgroup_cb(const char *name, const char *directory,
991 const char *file, void *data)
992 {
993 FILE *f = data;
994 char line[MAXPATHLEN];
995
996 if (read_info(directory, file, line, MAXPATHLEN)) {
997 ERROR("failed to read %s", file);
998 return -1;
999 }
1000
1001 fprintf(f, "%s=%s\n", file, line);
1002
1003 return 0;
1004 }
1005
1006 static int setup_convert_cgroup(const char *name, char *directory)
1007 {
1008 char filename[MAXPATHLEN];
1009 FILE *file;
1010 int ret;
1011
1012 snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup.new", name);
1013
1014 file = fopen(filename, "w+");
1015 if (!file)
1016 return -1;
1017
1018 ret = lxc_dir_for_each(name, directory, setup_convert_cgroup_cb, file);
1019 if (ret)
1020 goto out_error;
1021
1022 ret = unconfigure_cgroup(name);
1023 if (ret)
1024 goto out_error;
1025
1026 ret = rename(filename, directory);
1027 if (ret)
1028 goto out_error;
1029 out:
1030 fclose(file);
1031 return ret;
1032
1033 out_error:
1034 unlink(filename);
1035 goto out;
1036 }
1037
1038 static int setup_cgroup(const char *name)
1039 {
1040 char filename[MAXPATHLEN];
1041 char line[MAXPATHLEN];
1042 struct stat s;
1043
1044 snprintf(filename, MAXPATHLEN, LXCPATH "/%s/cgroup", name);
1045
1046 if (stat(filename, &s)) {
1047 SYSERROR("failed to stat '%s'", filename);
1048 return -1;
1049 }
1050
1051 if (S_ISDIR(s.st_mode)) {
1052 if (setup_convert_cgroup(name, filename)) {
1053 ERROR("failed to convert old cgroup configuration");
1054 return -1;
1055 }
1056 }
1057
1058 return lxc_file_for_each_line(filename, setup_cgroup_cb,
1059 line, MAXPATHLEN, (void *)name);
1060 }
1061
1062 static void parse_mntopt(char *opt, unsigned long *flags, char **data)
1063 {
1064 struct mount_opt *mo;
1065
1066 /* If opt is found in mount_opt, set or clear flags.
1067 * Otherwise append it to data. */
1068
1069 for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
1070 if (!strncmp(opt, mo->name, strlen(mo->name))) {
1071 if (mo->clear)
1072 *flags &= ~mo->flag;
1073 else
1074 *flags |= mo->flag;
1075 return;
1076 }
1077 }
1078
1079 if (strlen(*data))
1080 strcat(*data, ",");
1081 strcat(*data, opt);
1082 }
1083
1084 static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
1085 char **mntdata)
1086 {
1087 char *s, *data;
1088 char *p, *saveptr = NULL;
1089
1090 if (!mntent->mnt_opts)
1091 return 0;
1092
1093 s = strdup(mntent->mnt_opts);
1094 if (!s) {
1095 SYSERROR("failed to allocate memory");
1096 return -1;
1097 }
1098
1099 data = malloc(strlen(s) + 1);
1100 if (!data) {
1101 SYSERROR("failed to allocate memory");
1102 free(s);
1103 return -1;
1104 }
1105 *data = 0;
1106
1107 for (p = strtok_r(s, ",", &saveptr); p != NULL;
1108 p = strtok_r(NULL, ",", &saveptr))
1109 parse_mntopt(p, mntflags, &data);
1110
1111 if (*data)
1112 *mntdata = data;
1113 else
1114 free(data);
1115 free(s);
1116
1117 return 0;
1118 }
1119
1120 static int setup_mount(const char *name)
1121 {
1122 char path[MAXPATHLEN];
1123 struct mntent *mntent;
1124 FILE *file;
1125 int ret = -1;
1126 unsigned long mntflags;
1127 char *mntdata;
1128
1129 snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
1130
1131 file = setmntent(path, "r");
1132 if (!file) {
1133 if (errno == ENOENT)
1134 return 0;
1135 SYSERROR("failed to open '%s'", path);
1136 goto out;
1137 }
1138
1139 while ((mntent = getmntent(file))) {
1140 mntflags = 0;
1141 mntdata = NULL;
1142 if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
1143 ERROR("failed to parse mount option '%s'",
1144 mntent->mnt_opts);
1145 goto out;
1146 }
1147
1148 if (mount(mntent->mnt_fsname, mntent->mnt_dir,
1149 mntent->mnt_type, mntflags, mntdata)) {
1150 SYSERROR("failed to mount '%s' on '%s'",
1151 mntent->mnt_fsname, mntent->mnt_dir);
1152 goto out;
1153 }
1154
1155 free(mntdata);
1156 }
1157 ret = 0;
1158 out:
1159 endmntent(file);
1160 return ret;
1161 }
1162
1163 static int setup_ipv4_addr_cb(void *buffer, void *data)
1164 {
1165 char *ifname = data;
1166 char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
1167 int p = 24;
1168
1169 addr = buffer;
1170 cursor = strstr(addr, " ");
1171 if (cursor) {
1172 *cursor = '\0';
1173 bcast = cursor + 1;
1174 cursor = strstr(bcast, "\n");
1175 if (cursor)
1176 *cursor = '\0';
1177 }
1178
1179 slash = strstr(addr, "/");
1180 if (slash) {
1181 *slash = '\0';
1182 prefix = slash + 1;
1183 }
1184
1185 if (prefix)
1186 p = atoi(prefix);
1187
1188 if (lxc_ip_addr_add(ifname, addr, p, bcast)) {
1189 ERROR("failed to set %s to addr %s/%d %s", ifname,
1190 addr, p, bcast?bcast:"");
1191 return -1;
1192 }
1193
1194 return 0;
1195 }
1196
1197 static int setup_ipv6_addr_cb(void *buffer, void *data)
1198 {
1199 char *ifname = data;
1200 char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
1201 int p = 24;
1202
1203 addr = buffer;
1204 cursor = strstr(addr, " ");
1205 if (cursor) {
1206 *cursor = '\0';
1207 bcast = cursor + 1;
1208 cursor = strstr(bcast, "\n");
1209 if (cursor)
1210 *cursor = '\0';
1211 }
1212
1213 slash = strstr(addr, "/");
1214 if (slash) {
1215 *slash = '\0';
1216 prefix = slash + 1;
1217 }
1218
1219 if (prefix)
1220 p = atoi(prefix);
1221
1222 if (lxc_ip6_addr_add(ifname, addr, p, bcast)) {
1223 ERROR("failed to set %s to addr %s/%d %s", ifname,
1224 addr, p, bcast?bcast:"");
1225 return -1;
1226 }
1227
1228 return 0;
1229 }
1230
1231 static int setup_hw_addr(char *hwaddr, const char *ifname)
1232 {
1233 struct sockaddr sockaddr;
1234 struct ifreq ifr;
1235 int ret, fd;
1236
1237 if (lxc_convert_mac(hwaddr, &sockaddr)) {
1238 fprintf(stderr, "conversion has failed\n");
1239 return -1;
1240 }
1241
1242 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
1243 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
1244
1245 fd = socket(AF_INET, SOCK_DGRAM, 0);
1246 if (fd < 0) {
1247 perror("socket");
1248 return -1;
1249 }
1250
1251 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
1252 close(fd);
1253 if (ret)
1254 perror("ioctl");
1255
1256 return ret;
1257 }
1258
1259 static int setup_ip_addr(const char *directory, const char *ifname)
1260 {
1261 char path[MAXPATHLEN], line[MAXLINELEN];
1262 struct stat s;
1263 int ret = 0;
1264
1265 snprintf(path, MAXPATHLEN, "%s/ipv4/addresses", directory);
1266 if (!stat(path, &s))
1267 ret = lxc_file_for_each_line(path, setup_ipv4_addr_cb,
1268 line, MAXPATHLEN, (void*)ifname);
1269 return ret;
1270 }
1271
1272 static int setup_ip6_addr(const char *directory, const char *ifname)
1273 {
1274 char path[MAXPATHLEN], line[MAXLINELEN];
1275 struct stat s;
1276 int ret = 0;
1277
1278 snprintf(path, MAXLINELEN, "%s/ipv6/addresses", directory);
1279 if (!stat(path, &s))
1280 ret = lxc_file_for_each_line(path, setup_ipv6_addr_cb,
1281 line, MAXPATHLEN, (void*)ifname);
1282 return ret;
1283 }
1284
1285 static int setup_network_cb(const char *name, const char *directory,
1286 const char *file, void *data)
1287 {
1288 char path[MAXPATHLEN];
1289 char strindex[MAXINDEXLEN];
1290 char ifname[IFNAMSIZ];
1291 char newname[IFNAMSIZ];
1292 char hwaddr[MAXHWLEN];
1293 char *current_ifname = ifname;
1294 int ifindex;
1295
1296 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1297
1298 if (read_info(path, "ifindex", strindex, sizeof(strindex))) {
1299 ERROR("failed to read ifindex info");
1300 return -1;
1301 }
1302
1303 ifindex = atoi(strindex);
1304 if (!ifindex) {
1305 if (!read_info(path, "up", strindex, sizeof(strindex)))
1306 if (lxc_device_up("lo")) {
1307 ERROR("failed to set the loopback up");
1308 return -1;
1309 }
1310 return 0;
1311 }
1312
1313 if (!if_indextoname(ifindex, current_ifname)) {
1314 ERROR("no interface corresponding to index '%d'",
1315 ifindex);
1316 return -1;
1317 }
1318
1319 if (!read_info(path, "name", newname, sizeof(newname))) {
1320 if (lxc_device_rename(ifname, newname)) {
1321 ERROR("failed to rename %s->%s",
1322 ifname, newname);
1323 return -1;
1324 }
1325 current_ifname = newname;
1326 }
1327
1328 if (!read_info(path, "hwaddr", hwaddr, sizeof(hwaddr))) {
1329 if (setup_hw_addr(hwaddr, current_ifname)) {
1330 ERROR("failed to setup hw address for '%s'",
1331 current_ifname);
1332 return -1;
1333 }
1334 }
1335
1336 if (setup_ip_addr(path, current_ifname)) {
1337 ERROR("failed to setup ip addresses for '%s'",
1338 ifname);
1339 return -1;
1340 }
1341
1342 if (setup_ip6_addr(path, current_ifname)) {
1343 ERROR("failed to setup ipv6 addresses for '%s'",
1344 ifname);
1345 return -1;
1346 }
1347
1348 if (!read_info(path, "up", strindex, sizeof(strindex))) {
1349 if (lxc_device_up(current_ifname)) {
1350 ERROR("failed to set '%s' up", current_ifname);
1351 return -1;
1352 }
1353
1354 /* the network is up, make the loopback up too */
1355 if (lxc_device_up("lo")) {
1356 ERROR("failed to set the loopback up");
1357 return -1;
1358 }
1359 }
1360
1361 return 0;
1362 }
1363
1364 static int setup_network(const char *name)
1365 {
1366 char directory[MAXPATHLEN];
1367
1368 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
1369 return lxc_dir_for_each(name, directory, setup_network_cb, NULL);
1370 }
1371
1372 int conf_has(const char *name, const char *info)
1373 {
1374 int ret = 0;
1375 char path[MAXPATHLEN];
1376 struct stat st;
1377
1378 snprintf(path, MAXPATHLEN, LXCPATH "/%s/%s", name, info);
1379
1380 if (!stat(path, &st) || !lstat(path, &st)) {
1381 ret = 1;
1382 goto out;
1383 }
1384
1385 if (errno == ENOENT) {
1386 ret = 0;
1387 goto out;
1388 }
1389
1390 SYSERROR("failed to stat %s info", info);
1391 out:
1392 return ret;
1393 }
1394
1395 int lxc_conf_init(struct lxc_conf *conf)
1396 {
1397 conf->rootfs = NULL;
1398 conf->fstab = NULL;
1399 conf->utsname = NULL;
1400 conf->tty = 0;
1401 conf->pts = 0;
1402 lxc_list_init(&conf->cgroup);
1403 lxc_list_init(&conf->networks);
1404 return 0;
1405 }
1406
1407 int lxc_configure(const char *name, struct lxc_conf *conf)
1408 {
1409 if (!conf)
1410 return 0;
1411
1412 if (conf->utsname && configure_utsname(name, conf->utsname)) {
1413 ERROR("failed to configure the utsname");
1414 return -LXC_ERROR_CONF_UTSNAME;
1415 }
1416
1417 if (configure_cgroup(name, &conf->cgroup)) {
1418 ERROR("failed to configure the control group");
1419 return -LXC_ERROR_CONF_CGROUP;
1420 }
1421
1422 if (configure_network(name, &conf->networks)) {
1423 ERROR("failed to configure the network");
1424 return -LXC_ERROR_CONF_NETWORK;
1425 }
1426
1427 if (conf->tty && configure_tty(name, conf->tty)) {
1428 ERROR("failed to configure the tty");
1429 return -LXC_ERROR_CONF_TTY;
1430 }
1431
1432 if (conf->fstab && configure_mount(name, conf->fstab)) {
1433 ERROR("failed to configure the mount points");
1434 return -LXC_ERROR_CONF_MOUNT;
1435 }
1436
1437 if (conf->rootfs && configure_rootfs(name, conf->rootfs)) {
1438 ERROR("failed to configure the rootfs");
1439 return -LXC_ERROR_CONF_ROOTFS;
1440 }
1441
1442 if (conf->pts && configure_pts(name, conf->pts)) {
1443 ERROR("failed to configure a new pts instance");
1444 return -LXC_ERROR_CONF_PTS;
1445 }
1446
1447 return 0;
1448 }
1449
1450 int lxc_unconfigure(const char *name)
1451 {
1452 if (conf_has_utsname(name) && unconfigure_utsname(name))
1453 ERROR("failed to cleanup utsname");
1454
1455 if (conf_has_network(name) && unconfigure_network(name))
1456 ERROR("failed to cleanup the network");
1457
1458 if (conf_has_cgroup(name) && unconfigure_cgroup(name))
1459 ERROR("failed to cleanup cgroup");
1460
1461 if (conf_has_tty(name) && unconfigure_tty(name))
1462 ERROR("failed to cleanup tty");
1463
1464 if (conf_has_rootfs(name) && unconfigure_rootfs(name))
1465 ERROR("failed to cleanup rootfs");
1466
1467 if (conf_has_fstab(name) && unconfigure_mount(name))
1468 ERROR("failed to cleanup mount");
1469
1470 if (conf_has_pts(name) && unconfigure_pts(name))
1471 ERROR("failed to cleanup pts");
1472
1473 return 0;
1474 }
1475
1476 static int instanciate_veth(const char *directory, const char *file, pid_t pid)
1477 {
1478 char *path = NULL, *strindex = NULL, *veth1 = NULL, *veth2 = NULL;
1479 char bridge[IFNAMSIZ];
1480 char strmtu[MAXMTULEN];
1481 int ifindex, mtu = 0, ret = -1;
1482
1483 if (!asprintf(&veth1, "%s_%d", file, pid) ||
1484 !asprintf(&veth2, "%s~%d", file, pid) ||
1485 !asprintf(&path, "%s/%s", directory, file)) {
1486 SYSERROR("failed to allocate memory");
1487 goto out;
1488 }
1489
1490 if (read_info(path, "link", bridge, IFNAMSIZ)) {
1491 ERROR("failed to read bridge info");
1492 goto out;
1493 }
1494
1495 if (lxc_veth_create(veth1, veth2)) {
1496 ERROR("failed to create %s-%s/%s", veth1, veth2, bridge);
1497 goto out;
1498 }
1499
1500 if (!read_info(path, "mtu", strmtu, MAXMTULEN)) {
1501 if (sscanf(strmtu, "%u", &mtu) < 1) {
1502 ERROR("invalid mtu size '%d'", mtu);
1503 goto out_delete;
1504 }
1505
1506 if (lxc_device_set_mtu(veth1, mtu)) {
1507 ERROR("failed to set mtu for '%s'", veth1);
1508 goto out_delete;
1509 }
1510
1511 if (lxc_device_set_mtu(veth2, mtu)) {
1512 ERROR("failed to set mtu for '%s'", veth2);
1513 goto out_delete;
1514 }
1515 }
1516
1517 if (lxc_bridge_attach(bridge, veth1)) {
1518 ERROR("failed to attach '%s' to the bridge '%s'",
1519 veth1, bridge);
1520 goto out_delete;
1521 }
1522
1523 ifindex = if_nametoindex(veth2);
1524 if (!ifindex) {
1525 ERROR("failed to retrieve the index for %s", veth2);
1526 goto out_delete;
1527 }
1528
1529 if (!asprintf(&strindex, "%d", ifindex)) {
1530 SYSERROR("failed to allocate memory");
1531 goto out_delete;
1532 }
1533
1534 if (write_info(path, "ifindex", strindex)) {
1535 ERROR("failed to write interface index to %s", path);
1536 goto out_delete;
1537 }
1538
1539 if (!read_info(path, "up", strindex, sizeof(strindex))) {
1540 if (lxc_device_up(veth1)) {
1541 ERROR("failed to set %s up", veth1);
1542 goto out_delete;
1543 }
1544 }
1545
1546 ret = 0;
1547 out:
1548 free(path);
1549 free(strindex);
1550 free(veth1);
1551 free(veth2);
1552 return ret;
1553
1554 out_delete:
1555 lxc_device_delete(veth1);
1556 goto out;
1557 }
1558 static int instanciate_macvlan(const char *directory, const char *file, pid_t pid)
1559 {
1560 char path[MAXPATHLEN], *strindex = NULL, *peer = NULL;
1561 char link[IFNAMSIZ];
1562 int ifindex, ret = -1;
1563
1564 if (!asprintf(&peer, "%s~%d", file, pid)) {
1565 SYSERROR("failed to allocate memory");
1566 return -1;
1567 }
1568
1569 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1570 if (read_info(path, "link", link, IFNAMSIZ)) {
1571 ERROR("failed to read bridge info");
1572 goto out;
1573 }
1574
1575 if (lxc_macvlan_create(link, peer)) {
1576 ERROR("failed to create macvlan interface '%s' on '%s'",
1577 peer, link);
1578 goto out;
1579 }
1580
1581 ifindex = if_nametoindex(peer);
1582 if (!ifindex) {
1583 ERROR("failed to retrieve the index for %s", peer);
1584 goto out;
1585 }
1586
1587 if (!asprintf(&strindex, "%d", ifindex)) {
1588 SYSERROR("failed to allocate memory");
1589 return -1;
1590 }
1591
1592 if (write_info(path, "ifindex", strindex)) {
1593 ERROR("failed to write interface index to %s", path);
1594 goto out;
1595 }
1596
1597 ret = 0;
1598 out:
1599 free(strindex);
1600 free(peer);
1601 return ret;
1602 }
1603
1604 static int instanciate_phys(const char *directory, const char *file, pid_t pid)
1605 {
1606 char path[MAXPATHLEN], *strindex = NULL;
1607 char link[IFNAMSIZ];
1608 int ifindex, ret = -1;
1609
1610 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1611 if (read_info(path, "link", link, IFNAMSIZ)) {
1612 ERROR("failed to read link info");
1613 goto out;
1614 }
1615
1616 ifindex = if_nametoindex(link);
1617 if (!ifindex) {
1618 ERROR("failed to retrieve the index for %s", link);
1619 goto out;
1620 }
1621
1622 if (!asprintf(&strindex, "%d", ifindex)) {
1623 SYSERROR("failed to allocate memory");
1624 return -1;
1625 }
1626
1627 if (write_info(path, "ifindex", strindex)) {
1628 ERROR("failed to write interface index to %s", path);
1629 goto out;
1630 }
1631
1632 ret = 0;
1633 out:
1634 free(strindex);
1635 return ret;
1636 }
1637
1638 static int instanciate_empty(const char *directory, const char *file, pid_t pid)
1639 {
1640 char path[MAXPATHLEN], *strindex = NULL;
1641 int ret = -1;
1642
1643 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1644 if (!asprintf(&strindex, "%d", 0)) {
1645 ERROR("not enough memory");
1646 return -1;
1647 }
1648
1649 if (write_info(path, "ifindex", strindex)) {
1650 ERROR("failed to write interface index to %s", path);
1651 goto out;
1652 }
1653
1654 ret = 0;
1655 out:
1656 free(strindex);
1657 return ret;
1658 }
1659
1660 static int instanciate_netdev_cb(const char *name, const char *directory,
1661 const char *file, void *data)
1662 {
1663 pid_t *pid = data;
1664
1665 if (!strncmp("veth", file, strlen("veth")))
1666 return instanciate_veth(directory, file, *pid);
1667 else if (!strncmp("macvlan", file, strlen("macvlan")))
1668 return instanciate_macvlan(directory, file, *pid);
1669 else if (!strncmp("phys", file, strlen("phys")))
1670 return instanciate_phys(directory, file, *pid);
1671 else if (!strncmp("empty", file, strlen("empty")))
1672 return instanciate_empty(directory, file, *pid);
1673
1674 return -1;
1675 }
1676
1677 static int instanciate_netdev(const char *name, pid_t pid)
1678 {
1679 char directory[MAXPATHLEN];
1680
1681 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
1682 return lxc_dir_for_each(name, directory, instanciate_netdev_cb, &pid);
1683 }
1684
1685 static int move_netdev_cb(const char *name, const char *directory,
1686 const char *file, void *data)
1687 {
1688 char path[MAXPATHLEN], ifname[IFNAMSIZ], strindex[MAXINDEXLEN];
1689 pid_t *pid = data;
1690 int ifindex;
1691
1692 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1693 if (read_info(path, "ifindex", strindex, MAXINDEXLEN) < 0) {
1694 ERROR("failed to read index to from %s", path);
1695 return -1;
1696 }
1697
1698 ifindex = atoi(strindex);
1699 if (!ifindex)
1700 return 0;
1701
1702 if (!if_indextoname(ifindex, ifname)) {
1703 ERROR("interface with index %d does not exist",
1704 ifindex);
1705 return -1;
1706 }
1707
1708 if (lxc_device_move(ifname, *pid)) {
1709 ERROR("failed to move %s to %d", ifname, *pid);
1710 return -1;
1711 }
1712
1713 return 0;
1714 }
1715
1716 static int move_netdev(const char *name, pid_t pid)
1717 {
1718 char directory[MAXPATHLEN];
1719 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
1720 return lxc_dir_for_each(name, directory, move_netdev_cb, &pid);
1721 }
1722
1723 int conf_create_network(const char *name, pid_t pid)
1724 {
1725 if (instanciate_netdev(name, pid)) {
1726 ERROR("failed to instantiate the network devices");
1727 return -1;
1728 }
1729
1730 if (move_netdev(name, pid)) {
1731 ERROR("failed to move the netdev to the container");
1732 return -1;
1733 }
1734
1735 return 0;
1736 }
1737
1738 #ifdef NETWORK_DESTROY
1739 static int delete_netdev_cb(const char *name, const char *directory,
1740 const char *file, void *data)
1741 {
1742 char strindex[MAXINDEXLEN];
1743 char path[MAXPATHLEN];
1744 char ifname[IFNAMSIZ];
1745 int i, ifindex;
1746
1747 snprintf(path, MAXPATHLEN, "%s/%s", directory, file);
1748
1749 if (read_info(path, "ifindex", strindex, MAXINDEXLEN)) {
1750 ERROR("failed to read ifindex info");
1751 return -1;
1752 }
1753
1754 ifindex = atoi(strindex);
1755 if (!ifindex)
1756 return 0;
1757
1758 /* TODO : temporary code - needs wait on namespace */
1759 for (i = 0; i < 120; i++) {
1760 if (if_indextoname(ifindex, ifname))
1761 break;
1762 if (!i)
1763 printf("waiting for interface #%d to come back\n", ifindex);
1764 else
1765 printf("."); fflush(stdout);
1766 sleep(1);
1767 }
1768
1769 /* do not delete a physical network device */
1770 if (strncmp("phys", file, strlen("phys")))
1771 if (lxc_device_delete(ifname)) {
1772 ERROR("failed to remove the netdev %s", ifname);
1773 }
1774
1775 delete_info(path, "ifindex");
1776
1777 return 0;
1778 }
1779 #endif
1780
1781 int conf_destroy_network(const char *name)
1782 {
1783 #ifdef NETWORK_DESTROY
1784 char directory[MAXPATHLEN];
1785
1786 snprintf(directory, MAXPATHLEN, LXCPATH "/%s/network", name);
1787
1788 if (lxc_dir_for_each(name, directory, delete_netdev_cb, NULL)) {
1789 ERROR("failed to remove the network devices");
1790 return -1;
1791 }
1792 #endif
1793 return 0;
1794 }
1795
1796 int lxc_create_tty(const char *name, struct lxc_tty_info *tty_info)
1797 {
1798 char path[MAXPATHLEN];
1799 char tty[4];
1800 int i, ret = -1;
1801
1802 tty_info->nbtty = 0;
1803
1804 if (!conf_has_tty(name))
1805 return 0;
1806
1807 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
1808
1809 if (read_info(path, "tty", tty, sizeof(tty)) < 0) {
1810 SYSERROR("failed to read tty info");
1811 goto out;
1812 }
1813
1814 tty_info->nbtty = atoi(tty);
1815 tty_info->pty_info =
1816 malloc(sizeof(*tty_info->pty_info)*tty_info->nbtty);
1817
1818 if (!tty_info->pty_info) {
1819 SYSERROR("failed to allocate pty_info");
1820 goto out;
1821 }
1822
1823 for (i = 0; i < tty_info->nbtty; i++) {
1824
1825 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1826
1827 if (openpty(&pty_info->master, &pty_info->slave,
1828 pty_info->name, NULL, NULL)) {
1829 SYSERROR("failed to create pty #%d", i);
1830 goto out_free;
1831 }
1832
1833 /* Prevent leaking the file descriptors to the container */
1834 fcntl(pty_info->master, F_SETFD, FD_CLOEXEC);
1835 fcntl(pty_info->slave, F_SETFD, FD_CLOEXEC);
1836
1837 pty_info->busy = 0;
1838 }
1839
1840 ret = 0;
1841 out:
1842 return ret;
1843
1844 out_free:
1845 free(tty_info->pty_info);
1846 goto out;
1847 }
1848
1849 void lxc_delete_tty(struct lxc_tty_info *tty_info)
1850 {
1851 int i;
1852
1853 for (i = 0; i < tty_info->nbtty; i++) {
1854 struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
1855
1856 close(pty_info->master);
1857 close(pty_info->slave);
1858 }
1859
1860 free(tty_info->pty_info);
1861 tty_info->nbtty = 0;
1862 }
1863
1864 enum { utsname, network, cgroup, fstab, console, tty, rootfs, pts };
1865
1866 static int conf_is_set(long flags, int subsystem)
1867 {
1868 return flags & (1 << subsystem);
1869 }
1870
1871 static void conf_set_flag(long *flags, int subsystem)
1872 {
1873 *flags |= 1 << subsystem;
1874 }
1875
1876 static long make_conf_flagset(const char *name, const char *cons,
1877 const struct lxc_tty_info *tty_info)
1878 {
1879 long flags = 0;
1880
1881 if (conf_has_utsname(name))
1882 conf_set_flag(&flags, utsname);
1883
1884 if (conf_has_network(name))
1885 conf_set_flag(&flags, network);
1886
1887 if (conf_has_cgroup(name))
1888 conf_set_flag(&flags, cgroup);
1889
1890 if (conf_has_fstab(name))
1891 conf_set_flag(&flags, fstab);
1892
1893 if (conf_has_rootfs(name))
1894 conf_set_flag(&flags, rootfs);
1895
1896 if (conf_has_pts(name))
1897 conf_set_flag(&flags, pts);
1898
1899 if (tty_info->nbtty)
1900 conf_set_flag(&flags, tty);
1901
1902 if (cons[0])
1903 conf_set_flag(&flags, console);
1904
1905 return flags;
1906 }
1907
1908 int lxc_setup(const char *name, const char *cons,
1909 const struct lxc_tty_info *tty_info)
1910
1911 {
1912 /* store the conf flags set otherwise conf_has will not
1913 * work after chrooting */
1914 long flags = make_conf_flagset(name, cons, tty_info);
1915
1916 if (conf_is_set(flags, utsname) && setup_utsname(name)) {
1917 ERROR("failed to setup the utsname for '%s'", name);
1918 return -LXC_ERROR_SETUP_UTSNAME;
1919 }
1920
1921 if (conf_is_set(flags, network) && setup_network(name)) {
1922 ERROR("failed to setup the network for '%s'", name);
1923 return -LXC_ERROR_SETUP_NETWORK;
1924 }
1925
1926 if (conf_is_set(flags, cgroup) && setup_cgroup(name)) {
1927 ERROR("failed to setup the cgroups for '%s'", name);
1928 return -LXC_ERROR_SETUP_CGROUP;
1929 }
1930
1931 if (conf_is_set(flags, fstab) && setup_mount(name)) {
1932 ERROR("failed to setup the mounts for '%s'", name);
1933 return -LXC_ERROR_SETUP_MOUNT;
1934 }
1935
1936 if (conf_is_set(flags, console) && setup_console(name, cons)) {
1937 ERROR("failed to setup the console for '%s'", name);
1938 return -LXC_ERROR_SETUP_CONSOLE;
1939 }
1940
1941 if (conf_is_set(flags, tty) && setup_tty(name, tty_info)) {
1942 ERROR("failed to setup the ttys for '%s'", name);
1943 return -LXC_ERROR_SETUP_TTY;
1944 }
1945
1946 if (conf_is_set(flags, rootfs) && setup_rootfs(name)) {
1947 ERROR("failed to set rootfs for '%s'", name);
1948 return -LXC_ERROR_SETUP_ROOTFS;
1949 }
1950
1951 if (conf_is_set(flags, pts) && setup_pts(name)) {
1952 ERROR("failed to setup the new pts instance");
1953 return -LXC_ERROR_SETUP_PTS;
1954 }
1955
1956 return 0;
1957 }