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