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