]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/lxc_conf.c
Joined liblxc and lxc directory
[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>
32
33#include <sys/types.h>
34#include <sys/utsname.h>
35#include <sys/param.h>
36#include <sys/stat.h>
37#include <sys/socket.h>
38#include <sys/mount.h>
39#include <sys/mman.h>
40
41#include <arpa/inet.h>
42#include <fcntl.h>
43#include <netinet/in.h>
44#include <net/if.h>
45
46#include <lxc.h>
47#include <network.h>
48
49#define MAXHWLEN 18
50#define MAXINDEXLEN 20
51#define MAXLINELEN 128
52
53typedef int (*instanciate_cb)(const char *dirname,
54 const char *file, pid_t pid);
55
56typedef int (*dir_cb)(const char *name, const char *dirname,
57 const char *file, void *data);
58
59typedef int (*file_cb)(void* buffer, void *data);
60
61struct netdev_conf {
62 const char *type;
63 instanciate_cb cb;
64 int count;
65};
66
67static int instanciate_veth(const char *, const char *, pid_t);
68static int instanciate_macvlan(const char *, const char *, pid_t);
69static int instanciate_phys(const char *, const char *, pid_t);
70static int instanciate_empty(const char *, const char *, pid_t);
71
72static struct netdev_conf netdev_conf[MAXCONFTYPE + 1] = {
73 [VETH] = { "veth", instanciate_veth, 0 },
74 [MACVLAN] = { "macvlan", instanciate_macvlan, 0, },
75 [PHYS] = { "phys", instanciate_phys, 0, },
76 [EMPTY] = { "empty", instanciate_empty, 0, },
77};
78
79static int dir_filter(const struct dirent *dirent)
80{
81 if (!strcmp(dirent->d_name, ".") ||
82 !strcmp(dirent->d_name, ".."))
83 return 0;
84 return 1;
85}
86
87static int dir_for_each(const char *name, const char *dirname,
88 dir_cb callback, void *data)
89{
90 struct dirent **namelist;
91 int n;
92
93 n = scandir(dirname, &namelist, dir_filter, alphasort);
94 if (n < 0) {
95 lxc_log_syserror("failed to scan %s directory", dirname);
96 return -1;
97 }
98
99 while (n--) {
100 if (callback(name, dirname, namelist[n]->d_name, data)) {
101 lxc_log_error("callback failed");
102 free(namelist[n]);
103 return -1;
104 }
105 free(namelist[n]);
106 }
107
108 return 0;
109}
110
111static int file_for_each_line(const char *file, file_cb callback,
112 void *buffer, size_t len, void* data)
113{
114 FILE *f;
115 int err = -1;
116
117 f = fopen(file, "r");
118 if (!f) {
119 lxc_log_syserror("failed to open %s", file);
120 return -1;
121 }
122
123 while (fgets(buffer, len, f))
124 if (callback(buffer, data))
125 goto out;
126 err = 0;
127out:
128 fclose(f);
129 return err;
130}
131
132static int write_info(const char *path, const char *file, const char *info)
133{
134 int fd, err = -1;
135 char *f;
136
137 asprintf(&f, "%s/%s", path, file);
138 fd = creat(f, 0755);
139 if (fd < 0)
140 goto out;
141
142 if (write(fd, info, strlen(info)) < 0 ||
143 write(fd, "\n", strlen("\n") + 1) < 0)
144 goto out_write;
145 err = 0;
146out:
147 close(fd);
148 free(f);
149 return err;
150
151out_write:
152 unlink(f);
153 goto out;
154}
155
156static int read_info(const char *path, const char *file, char *info, size_t len)
157{
158 int fd, ret = -1;
159 char *f, *token;
160
161 asprintf(&f, "%s/%s", path, file);
162 fd = open(f, O_RDONLY);
163 if (fd < 0) {
164 if (errno == ENOENT)
165 ret = 1;
166 goto out;
167 }
168
169 ret = read(fd, info, len);
170 if (ret < 0)
171 goto out;
172
173 token = strstr(info, "\n");
174 if (token)
175 *token = '\0';
176 ret = 0;
177out:
178 close(fd);
179 free(f);
180 return ret;
181}
182
183static int delete_info(const char *path, const char *file)
184{
185 char *info;
186 int ret;
187
188 asprintf(&info, "%s/%s", path, file);
189 ret = unlink(info);
190 free(info);
191
192 return ret;
193}
194
195static int configure_ip4addr(int fd, struct lxc_inetdev *in)
196{
197 char addr[INET6_ADDRSTRLEN];
198 char bcast[INET_ADDRSTRLEN];
199 char *line = NULL;
200 int err = -1;
201
202 if (!inet_ntop(AF_INET, &in->addr, addr, sizeof(addr))) {
203 lxc_log_syserror("failed to convert ipv4 address");
204 goto err;
205 }
206
207 if (!inet_ntop(AF_INET, &in->bcast, bcast, sizeof(bcast))) {
208 lxc_log_syserror("failed to convert ipv4 broadcast");
209 goto err;
210 }
211
212 if (in->prefix)
213 asprintf(&line, "%s/%d %s\n", addr, in->prefix, bcast);
214 else
215 asprintf(&line, "%s %s\n", addr, bcast);
216
217 if (write(fd, line, strlen(line)) < 0) {
218 lxc_log_syserror("failed to write address info");
219 goto err;
220 }
221
222 err = 0;
223err:
224 free(line);
225 return err;
226}
227
228static int configure_ip6addr(int fd, struct lxc_inet6dev *in6)
229{
230 char addr[INET6_ADDRSTRLEN];
231 char *line = NULL;
232 int err = -1;
233
234 if (!inet_ntop(AF_INET6, &in6->addr, addr, sizeof(addr))) {
235 lxc_log_syserror("failed to convert ipv4 address");
236 goto err;
237 }
238
239 asprintf(&line, "%s/%d\n", addr, in6->prefix?in6->prefix:64);
240
241 if (write(fd, line, strlen(line)) < 0) {
242 lxc_log_syserror("failed to write address info");
243 goto err;
244 }
245
246 err = 0;
247err:
248 free(line);
249 return err;
250}
251
252static int configure_ip_address(const char *path, struct lxc_list *ip, int family)
253{
254 char file[MAXPATHLEN];
255 struct lxc_list *iterator;
256 int fd, err = -1;
257
258 if (mkdir(path, 0755)) {
259 lxc_log_syserror("failed to create directory %s", path);
260 return -1;
261 }
262
263 snprintf(file, MAXPATHLEN, "%s/addresses", path);
264 fd = creat(file, 0755);
265 if (fd < 0) {
266 lxc_log_syserror("failed to create %s file", file);
267 goto err;
268 }
269
270 lxc_list_for_each(iterator, ip) {
271 err = family == AF_INET?
272 configure_ip4addr(fd, iterator->elem):
273 configure_ip6addr(fd, iterator->elem);
274 if (err)
275 goto err;
276 }
277out:
278 close(fd);
279 return err;
280err:
281 unlink(file);
282 rmdir(path);
283 goto out;
284}
285
286static int configure_netdev(const char *path, struct lxc_netdev *netdev)
287{
288 int err = -1;
289 char dir[MAXPATHLEN];
290
291 if (mkdir(path, 0755)) {
292 lxc_log_syserror("failed to create %s directory", path);
293 return -1;
294 }
295
296 if (netdev->ifname) {
297 if (write_info(path, "link", netdev->ifname))
298 goto out_link;
299 }
300
301 if (netdev->newname) {
302 if (write_info(path, "name", netdev->newname))
303 goto out_newname;
304 }
305
306 if (netdev->hwaddr) {
307 if (write_info(path, "hwaddr", netdev->hwaddr))
308 goto out_up;
309 }
310
311 if (netdev->flags & IFF_UP) {
312 if (write_info(path, "up", ""))
313 goto out_hwaddr;
314 }
315
316 if (!lxc_list_empty(&netdev->ipv4)) {
317 snprintf(dir, MAXPATHLEN, "%s/ipv4", path);
318 if (configure_ip_address(dir, &netdev->ipv4, AF_INET))
319 goto out_ipv4;
320 }
321
322 if (!lxc_list_empty(&netdev->ipv6)) {
323 snprintf(dir, MAXPATHLEN, "%s/ipv6", path);
324 if (configure_ip_address(dir, &netdev->ipv6, AF_INET6))
325 goto out_ipv6;
326 }
327 err = 0;
328out:
329 return err;
330out_ipv6:
331 delete_info(path, "ipv4");
332out_ipv4:
333 delete_info(path, "up");
334out_hwaddr:
335 delete_info(path, "hwaddr");
336out_up:
337 delete_info(path, "name");
338out_newname:
339 delete_info(path, "link");
340out_link:
341 rmdir(path);
342 goto out;
343}
344
345static int configure_utsname(const char *name, struct utsname *utsname)
346{
347 char path[MAXPATHLEN];
348
349 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
350
351 if (write_info(path, "utsname", utsname->nodename)) {
352 lxc_log_error("failed to write the utsname info");
353 return -1;
354 }
355
356 return 0;
357}
358
359static int configure_network(const char *name, struct lxc_list *network)
360{
361 struct lxc_list *iterator;
362 struct lxc_network *n;
363 char networkpath[MAXPATHLEN];
364 char path[MAXPATHLEN];
365 int err = -1;
366
367 if (lxc_list_empty(network))
368 return 0;
369
370 snprintf(networkpath, MAXPATHLEN, LXCPATH "/%s/network", name);
371 if (mkdir(networkpath, 0755)) {
372 lxc_log_syserror("failed to create %s directory", networkpath);
373 goto out;
374 }
375
376 lxc_list_for_each(iterator, network) {
377
378 n = iterator->elem;
379
380 if (n->type < 0 || n->type > MAXCONFTYPE) {
381 lxc_log_error("invalid network configuration type '%d'",
382 n->type);
383 goto out;
384 }
385
386 snprintf(path, MAXPATHLEN, "%s/%s%d", networkpath,
387 netdev_conf[n->type].type,
388 netdev_conf[n->type].count++);
389
390 if (configure_netdev(path, lxc_list_first_elem(&n->netdev))) {
391 lxc_log_error("failed to configure network type %s",
392 netdev_conf[n->type].type);
393 goto out;
394 }
395 }
396
397 err = 0;
398out:
399 return err;
400}
401
402static int configure_cgroup(const char *name, struct lxc_cgroup *cgroup)
403{
404 return 0;
405}
406
407static int configure_chroot(const char *name, const char *chroot)
408{
409 char path[MAXPATHLEN];
410
411 snprintf(path, MAXPATHLEN, LXCPATH "/%s/chroot", name);
412
413 return symlink(chroot, path);
414
415}
416
417static int configure_mount(const char *name, const char *fstab)
418{
419 char *path;
420 struct stat stat;
421 int infd, outfd;
422 void *src, *dst;
423 char c = '\0';
424 int ret = -1;
425
426 asprintf(&path, LXCPATH "/%s/fstab", name);
427
428 outfd = open(path, O_RDWR|O_CREAT|O_EXCL, 0640);
429 if (outfd < 0) {
430 lxc_log_syserror("failed to creat '%s'", path);
431 goto out;
432 }
433
434 infd = open(fstab, O_RDONLY);
435 if (infd < 0) {
436 lxc_log_syserror("failed to open '%s'", fstab);
437 goto out;
438 }
439
440 if (fstat(infd, &stat)) {
441 lxc_log_syserror("failed to stat '%s'", fstab);
442 goto out;
443 }
444
445 if (lseek(outfd, stat.st_size - 1, SEEK_SET) < 0) {
446 lxc_log_syserror("failed to seek dest file '%s'", path);
447 goto out;
448 }
449
450 /* fixup length */
451 if (write(outfd, &c, 1) < 0) {
452 lxc_log_syserror("failed to write to '%s'", path);
453 goto out;
454 }
455
456 src = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, infd, 0L);
457 if (src == MAP_FAILED) {
458 lxc_log_syserror("failed to mmap '%s'", fstab);
459 goto out;
460 }
461
462 dst = mmap(NULL, stat.st_size, PROT_WRITE, MAP_SHARED, outfd, 0L);
463 if (dst == MAP_FAILED) {
464 lxc_log_syserror("failed to mmap '%s'", path);
465 goto out;
466 }
467
468 memcpy(dst, src, stat.st_size);
469
470 munmap(src, stat.st_size);
471 munmap(dst, stat.st_size);
472
473 ret = 0;
474out:
475 free(path);
476 return ret;
477}
478
479static int unconfigure_ip_addresses(const char *dirname)
480{
481 char path[MAXPATHLEN];
482
483 snprintf(path, MAXPATHLEN, "%s/ipv4", dirname);
484 delete_info(path, "addresses");
485 rmdir(path);
486
487 snprintf(path, MAXPATHLEN, "%s/ipv6", dirname);
488 delete_info(path, "addresses");
489 rmdir(path);
490
491 return 0;
492}
493
494static int unconfigure_network_cb(const char *name, const char *dirname,
495 const char *file, void *data)
496{
497 char path[MAXPATHLEN];
498
499 snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
500 delete_info(path, "name");
501 delete_info(path, "addr");
502 delete_info(path, "link");
503 delete_info(path, "hwaddr");
504 delete_info(path, "up");
505 unconfigure_ip_addresses(path);
506 rmdir(path);
507
508 return 0;
509}
510
511static int unconfigure_network(const char *name)
512{
513 char dirname[MAXPATHLEN];
514
515 snprintf(dirname, MAXPATHLEN, LXCPATH "/%s/network", name);
516 dir_for_each(name, dirname, unconfigure_network_cb, NULL);
517 rmdir(dirname);
518
519 return 0;
520}
521
522static int unconfigure_cgroup(const char *name)
523{
524 return 0;
525}
526
527static int unconfigure_chroot(const char *name)
528{
529 char path[MAXPATHLEN];
530
531 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
532 delete_info(path, "chroot");
533
534 return 0;
535}
536
537static int unconfigure_mount(const char *name)
538{
539 char path[MAXPATHLEN];
540
541 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
542 delete_info(path, "fstab");
543
544 return 0;
545}
546
547static int unconfigure_utsname(const char *name)
548{
549 char path[MAXPATHLEN];
550
551 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
552 delete_info(path, "utsname");
553
554 return 0;
555}
556
557static int setup_utsname(const char *name)
558{
559 int ret;
560 char path[MAXPATHLEN];
561 struct utsname utsname;
562
563 snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
564
565 ret = read_info(path, "utsname", utsname.nodename,
566 sizeof(utsname.nodename));
567 if (ret < 0) {
568 lxc_log_syserror("failed to read utsname info");
569 return -1;
570 }
571
572 if (!ret && sethostname(utsname.nodename, strlen(utsname.nodename))) {
573 lxc_log_syserror("failed to set the hostname to '%s'",
574 utsname.nodename);
575 return -1;
576 }
577
578 return 0;
579}
580
581static int setup_chroot(const char *name)
582{
583 char path[MAXPATHLEN], chrt[MAXPATHLEN];
584
585 snprintf(path, MAXPATHLEN, LXCPATH "/%s/chroot", name);
586
587 if (readlink(path, chrt, MAXPATHLEN) > 0) {
588
589 if (chroot(chrt)) {
590 lxc_log_syserror("failed to set chroot %s", path);
591 return -1;
592 }
593
594 if (chdir(getenv("HOME")) && chdir("/")) {
595 lxc_log_syserror("failed to change to home directory");
596 return -1;
597 }
598 }
599
600 return 0;
601}
602
603static int setup_mount(const char *name)
604{
605 char path[MAXPATHLEN];
606 struct mntent *mntent;
607 FILE *file;
608 int ret = -1;
609 unsigned long mntflags = 0;
610
611 snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
612
613 file = setmntent(path, "r");
614 if (!file) {
615 if (errno == ENOENT)
616 return 0;
617 lxc_log_syserror("failed to open '%s'", path);
618 goto out;
619 }
620
621 while((mntent = getmntent(file))) {
622
623 if (hasmntopt(mntent, "bind"))
624 mntflags |= MS_BIND;
625
626 if (mount(mntent->mnt_fsname, mntent->mnt_dir,
627 mntent->mnt_type, mntflags, NULL)) {
628 lxc_log_syserror("failed to mount '%s' on '%s'",
629 mntent->mnt_fsname, mntent->mnt_dir);
630 goto out;
631 }
632 }
633 ret = 0;
634out:
635 endmntent(file);
636 return ret;
637}
638
639static int setup_ipv4_addr_cb(void *buffer, void *data)
640{
641 char *ifname = data;
642 char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
643 int p = 24;
644
645 addr = buffer;
646 cursor = strstr(addr, " ");
647 if (cursor) {
648 *cursor = '\0';
649 bcast = cursor + 1;
650 cursor = strstr(bcast, "\n");
651 if (cursor)
652 *cursor = '\0';
653 }
654
655 slash = strstr(addr, "/");
656 if (slash) {
657 *slash = '\0';
658 prefix = slash + 1;
659 }
660
661 if (prefix)
662 p = atoi(prefix);
663
664 if (ip_addr_add(ifname, addr, p, bcast)) {
665 lxc_log_error("failed to set %s to addr %s/%d %s", ifname,
666 addr, p, bcast?bcast:"");
667 return -1;
668 }
669
670 return 0;
671}
672
673static int setup_ipv6_addr_cb(void *buffer, void *data)
674{
675 char *ifname = data;
676 char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
677 int p = 24;
678
679 addr = buffer;
680 cursor = strstr(addr, " ");
681 if (cursor) {
682 *cursor = '\0';
683 bcast = cursor + 1;
684 cursor = strstr(bcast, "\n");
685 if (cursor)
686 *cursor = '\0';
687 }
688
689 slash = strstr(addr, "/");
690 if (slash) {
691 *slash = '\0';
692 prefix = slash + 1;
693 }
694
695 if (prefix)
696 p = atoi(prefix);
697
698 if (ip6_addr_add(ifname, addr, p, bcast)) {
699 lxc_log_error("failed to set %s to addr %s/%d %s", ifname,
700 addr, p, bcast?bcast:"");
701 return -1;
702 }
703
704 return 0;
705}
706
707static int setup_hw_addr(char *hwaddr, const char *ifname)
708{
709 struct sockaddr sockaddr;
710 struct ifreq ifr;
711 int ret, fd;
712
713 if (lxc_convert_mac(hwaddr, &sockaddr)) {
714 fprintf(stderr, "conversion has failed\n");
715 return -1;
716 }
717
718 memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
719 memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
720
721 fd = socket(AF_INET, SOCK_DGRAM, 0);
722 if (fd < 0) {
723 perror("socket");
724 return -1;
725 }
726
727 ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
728 close(fd);
729 if (ret)
730 perror("ioctl");
731
732 return ret;
733}
734
735static int setup_ip_addr(const char *dirname, const char *ifname)
736{
737 char path[MAXPATHLEN], line[MAXLINELEN];
738 struct stat s;
739 int ret = 0;
740
741 snprintf(path, MAXPATHLEN, "%s/ipv4/addresses", dirname);
742 if (!stat(path, &s))
743 ret = file_for_each_line(path, setup_ipv4_addr_cb,
744 line, MAXPATHLEN, (void*)ifname);
745 return ret;
746}
747
748static int setup_ip6_addr(const char *dirname, const char *ifname)
749{
750 char path[MAXPATHLEN], line[MAXLINELEN];
751 struct stat s;
752 int ret = 0;
753
754 snprintf(path, MAXLINELEN, "%s/ipv6/addresses", dirname);
755 if (!stat(path, &s))
756 ret = file_for_each_line(path, setup_ipv6_addr_cb,
757 line, MAXPATHLEN, (void*)ifname);
758 return ret;
759}
760
761static int setup_network_cb(const char *name, const char *dirname,
762 const char *file, void *data)
763{
764 char path[MAXPATHLEN];
765 char strindex[MAXINDEXLEN];
766 char ifname[IFNAMSIZ];
767 char newname[IFNAMSIZ];
768 char hwaddr[MAXHWLEN];
769 char *current_ifname = ifname;
770 int ifindex;
771
772 snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
773
774 if (read_info(path, "ifindex", strindex, sizeof(strindex))) {
775 lxc_log_error("failed to read ifindex info");
776 return -1;
777 }
778
779 ifindex = atoi(strindex);
780 if (!ifindex) {
781 if (!read_info(path, "up", strindex, sizeof(strindex)))
782 if (device_up("lo")) {
783 lxc_log_error("failed to set the loopback up");
784 return -1;
785 }
786 return 0;
787 }
788
789 if (!if_indextoname(ifindex, current_ifname)) {
790 lxc_log_error("no interface corresponding to index '%d'",
791 ifindex);
792 return -1;
793 }
794
795 if (!read_info(path, "name", newname, sizeof(newname))) {
796 if (device_rename(ifname, newname)) {
797 lxc_log_error("failed to rename %s->%s",
798 ifname, newname);
799 return -1;
800 }
801 current_ifname = newname;
802 }
803
804 if (!read_info(path, "hwaddr", hwaddr, sizeof(hwaddr))) {
805 if (setup_hw_addr(hwaddr, current_ifname)) {
806 lxc_log_error("failed to setup hw address for '%s'",
807 current_ifname);
808 return -1;
809 }
810 }
811
812 if (setup_ip_addr(path, current_ifname)) {
813 lxc_log_error("failed to setup ip addresses for '%s'",
814 ifname);
815 return -1;
816 }
817
818 if (setup_ip6_addr(path, current_ifname)) {
819 lxc_log_error("failed to setup ipv6 addresses for '%s'",
820 ifname);
821 return -1;
822 }
823
824 if (!read_info(path, "up", strindex, sizeof(strindex))) {
825 if (device_up(current_ifname)) {
826 lxc_log_error("failed to set '%s' up", current_ifname);
827 return -1;
828 }
829
830 /* the network is up, make the loopback up too */
831 if (device_up("lo")) {
832 lxc_log_error("failed to set the loopback up");
833 return -1;
834 }
835 }
836
837 return 0;
838}
839
840static int setup_network(const char *name)
841{
842 char dirname[MAXPATHLEN];
843
844 snprintf(dirname, MAXPATHLEN, LXCPATH "/%s/network", name);
845 return dir_for_each(name, dirname, setup_network_cb, NULL);
846}
847
848int conf_has(const char *name, const char *info)
849{
850 int ret;
851 char path[MAXPATHLEN];
852 struct stat st;
853
854 snprintf(path, MAXPATHLEN, LXCPATH "/%s/%s", name, info);
855
856 ret = stat(path, &st);
857 if (!ret) {
858 ret = 1;
859 goto out;
860 }
861
862 if (errno == ENOENT) {
863 ret = 0;
864 goto out;
865 }
866
867 lxc_log_syserror("failed to stat %s info", info);
868out:
869 return ret;
870}
871
872int lxc_configure(const char *name, struct lxc_conf *conf)
873{
874 if (!conf)
875 return 0;
876
877 if (conf->utsname && configure_utsname(name, conf->utsname)) {
878 lxc_log_error("failed to configure the utsname");
879 return -1;
880 }
881
882 if (configure_network(name, &conf->networks)) {
883 lxc_log_error("failed to configure the network");
884 return -1;
885 }
886
887 if (conf->cgroup && configure_cgroup(name, conf->cgroup)) {
888 lxc_log_error("failed to configure the control group");
889 return -1;
890 }
891
892 if (conf->chroot && configure_chroot(name, conf->chroot)) {
893 lxc_log_error("failed to configure the chroot");
894 return -1;
895 }
896
897 if (conf->fstab && configure_mount(name, conf->fstab)) {
898 lxc_log_error("failed to configure the mount points");
899 return -1;
900 }
901
902 return 0;
903}
904
905int lxc_unconfigure(const char *name)
906{
907 if (conf_has_utsname(name) && unconfigure_utsname(name))
908 lxc_log_error("failed to cleanup utsname");
909
910 if (conf_has_network(name) && unconfigure_network(name))
911 lxc_log_error("failed to cleanup the network");
912
913 if (unconfigure_cgroup(name))
914 lxc_log_error("failed to cleanup cgroup");
915
916 if (conf_has_chroot(name) && unconfigure_chroot(name))
917 lxc_log_error("failed to cleanup chroot");
918
919 if (conf_has_fstab(name) && unconfigure_mount(name))
920 lxc_log_error("failed to cleanup mount");
921
922 return 0;
923}
924
925static int instanciate_veth(const char *dirname, const char *file, pid_t pid)
926{
927 char *path = NULL, *strindex = NULL, *veth1 = NULL, *veth2 = NULL;
928 char bridge[IFNAMSIZ];
929 int ifindex, ret = -1;
930
931 asprintf(&veth1, "%s_%d", file, pid);
932 asprintf(&veth2, "%s~%d", file, pid);
933 asprintf(&path, "%s/%s", dirname, file);
934
935 if (read_info(path, "link", bridge, IFNAMSIZ)) {
936 lxc_log_error("failed to read bridge info");
937 goto out;
938 }
939
940 if (lxc_configure_veth(veth1, veth2, bridge)) {
941 lxc_log_error("failed to create %s-%s/%s", veth1, veth2, bridge);
942 goto out;
943 }
944
945 ifindex = if_nametoindex(veth2);
946 if (!ifindex) {
947 lxc_log_error("failed to retrieve the index for %s", veth2);
948 goto out;
949 }
950
951 asprintf(&strindex, "%d", ifindex);
952 if (write_info(path, "ifindex", strindex)) {
953 lxc_log_error("failed to write interface index to %s", path);
954 goto out;
955 }
956
957 if (!read_info(path, "up", strindex, sizeof(strindex))) {
958 if (device_up(veth1)) {
959 lxc_log_error("failed to set %s up", veth1);
960 goto out;
961 }
962 }
963
964 ret = 0;
965out:
966 free(path);
967 free(strindex);
968 free(veth1);
969 free(veth2);
970 return ret;
971}
972static int instanciate_macvlan(const char *dirname, const char *file, pid_t pid)
973{
974 char path[MAXPATHLEN], *strindex = NULL, *peer = NULL;
975 char link[IFNAMSIZ];
976 int ifindex, ret = -1;
977
978 asprintf(&peer, "%s~%d", file, pid);
979 snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
980 if (read_info(path, "link", link, IFNAMSIZ)) {
981 lxc_log_error("failed to read bridge info");
982 goto out;
983 }
984
985 if (lxc_configure_macvlan(link, peer)) {
986 lxc_log_error("failed to create macvlan interface %s", peer);
987 goto out;
988 }
989
990 ifindex = if_nametoindex(peer);
991 if (!ifindex) {
992 lxc_log_error("failed to retrieve the index for %s", peer);
993 goto out;
994 }
995
996 asprintf(&strindex, "%d", ifindex);
997 if (write_info(path, "ifindex", strindex)) {
998 lxc_log_error("failed to write interface index to %s", path);
999 goto out;
1000 }
1001
1002 ret = 0;
1003out:
1004 free(strindex);
1005 free(peer);
1006 return ret;
1007}
1008
1009static int instanciate_phys(const char *dirname, const char *file, pid_t pid)
1010{
1011 char path[MAXPATHLEN], *strindex = NULL;
1012 char link[IFNAMSIZ];
1013 int ifindex, ret = -1;
1014
1015 snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
1016 if (read_info(path, "link", link, IFNAMSIZ)) {
1017 lxc_log_error("failed to read link info");
1018 goto out;
1019 }
1020
1021 ifindex = if_nametoindex(link);
1022 if (!ifindex) {
1023 lxc_log_error("failed to retrieve the index for %s", link);
1024 goto out;
1025 }
1026
1027 asprintf(&strindex, "%d", ifindex);
1028 if (write_info(path, "ifindex", strindex)) {
1029 lxc_log_error("failed to write interface index to %s", path);
1030 goto out;
1031 }
1032
1033 ret = 0;
1034out:
1035 free(strindex);
1036 return ret;
1037}
1038
1039static int instanciate_empty(const char *dirname, const char *file, pid_t pid)
1040{
1041 char path[MAXPATHLEN], *strindex = NULL;
1042 int ret = -1;
1043
1044 snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
1045 if (!asprintf(&strindex, "%d", 0)) {
1046 lxc_log_error("not enough memory");
1047 return -1;
1048 }
1049
1050 if (write_info(path, "ifindex", strindex)) {
1051 lxc_log_error("failed to write interface index to %s", path);
1052 goto out;
1053 }
1054
1055 ret = 0;
1056out:
1057 free(strindex);
1058 return ret;
1059}
1060
1061static int instanciate_netdev_cb(const char *name, const char *dirname,
1062 const char *file, void *data)
1063{
1064 pid_t *pid = data;
1065
1066 if (!strncmp("veth", file, strlen("veth")))
1067 return instanciate_veth(dirname, file, *pid);
1068 else if (!strncmp("macvlan", file, strlen("macvlan")))
1069 return instanciate_macvlan(dirname, file, *pid);
1070 else if (!strncmp("phys", file, strlen("phys")))
1071 return instanciate_phys(dirname, file, *pid);
1072 else if (!strncmp("empty", file, strlen("empty")))
1073 return instanciate_empty(dirname, file, *pid);
1074
1075 return -1;
1076}
1077
1078static int instanciate_netdev(const char *name, pid_t pid)
1079{
1080 char *dirname;
1081 int ret;
1082
1083 asprintf(&dirname, LXCPATH "/%s/network", name);
1084 ret = dir_for_each(name, dirname, instanciate_netdev_cb, &pid);
1085 free(dirname);
1086
1087 return ret;
1088}
1089
1090static int move_netdev_cb(const char *name, const char *dirname,
1091 const char *file, void *data)
1092{
1093 char path[MAXPATHLEN], ifname[IFNAMSIZ], strindex[MAXINDEXLEN];
1094 pid_t *pid = data;
1095 int ifindex;
1096
1097 snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
1098 if (read_info(path, "ifindex", strindex, MAXINDEXLEN) < 0) {
1099 lxc_log_error("failed to read index to from %s", path);
1100 return -1;
1101 }
1102
1103 ifindex = atoi(strindex);
1104 if (!ifindex)
1105 return 0;
1106
1107 if (!if_indextoname(ifindex, ifname)) {
1108 lxc_log_error("interface with index %d does not exist",
1109 ifindex);
1110 return -1;
1111 }
1112
1113 if (device_move(ifname, *pid)) {
1114 lxc_log_error("failed to move %s to %d", ifname, *pid);
1115 return -1;
1116 }
1117
1118 return 0;
1119}
1120
1121static int move_netdev(const char *name, pid_t pid)
1122{
1123 char *dirname;
1124 int ret;
1125
1126 asprintf(&dirname, LXCPATH "/%s/network", name);
1127 ret = dir_for_each(name, dirname, move_netdev_cb, &pid);
1128 free(dirname);
1129
1130 return ret;
1131}
1132
1133int conf_create_network(const char *name, pid_t pid)
1134{
1135 if (instanciate_netdev(name, pid)) {
1136 lxc_log_error("failed to instantiate the network devices");
1137 return -1;
1138 }
1139
1140 if (move_netdev(name, pid)) {
1141 lxc_log_error("failed to move the netdev to the container");
1142 return -1;
1143 }
1144
1145 return 0;
1146}
1147
1148static int delete_netdev_cb(const char *name, const char *dirname,
1149 const char *file, void *data)
1150{
1151 char strindex[MAXINDEXLEN];
1152 char path[MAXPATHLEN];
1153 char ifname[IFNAMSIZ];
1154 int i, ifindex;
1155
1156 snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
1157
1158 if (read_info(path, "ifindex", strindex, MAXINDEXLEN)) {
1159 lxc_log_error("failed to read ifindex info");
1160 return -1;
1161 }
1162
1163 ifindex = atoi(strindex);
1164 if (!ifindex)
1165 return 0;
1166
1167 /* TODO : temporary code - needs wait on namespace */
1168 for (i = 0; i < 120; i++) {
1169 if (if_indextoname(ifindex, ifname))
1170 break;
1171 if (!i)
1172 printf("waiting for interface #%d to come back\n", ifindex);
1173 else
1174 printf("."); fflush(stdout);
1175 sleep(1);
1176 }
1177
1178 /* do not delete a physical network device */
1179 if (strncmp("phys", file, strlen("phys")))
1180 if (device_delete(ifname)) {
1181 lxc_log_error("failed to remove the netdev %s", ifname);
1182 }
1183
1184 delete_info(path, "ifindex");
1185
1186 return 0;
1187}
1188
1189static int delete_netdev(const char *name)
1190{
1191 char *dirname;
1192 int ret;
1193
1194 asprintf(&dirname, LXCPATH "/%s/network", name);
1195 ret = dir_for_each(name, dirname, delete_netdev_cb, NULL);
1196 free(dirname);
1197
1198 return ret;
1199}
1200
1201int conf_destroy_network(const char *name)
1202{
1203 if (delete_netdev(name)) {
1204 lxc_log_error("failed to remove the network devices");
1205 return -1;
1206 }
1207
1208 return 0;
1209}
1210
1211int lxc_setup(const char *name)
1212{
1213 if (conf_has_utsname(name) && setup_utsname(name)) {
1214 lxc_log_error("failed to setup the utsname for '%s'", name);
1215 return -1;
1216 }
1217
1218 if (conf_has_network(name) && setup_network(name)) {
1219 lxc_log_error("failed to setup the network for '%s'", name);
1220 return -1;
1221 }
1222
1223 if (conf_has_fstab(name) && setup_mount(name)) {
1224 lxc_log_error("failed to setup the mount points for '%s'", name);
1225 return -1;
1226 }
1227
1228 if (conf_has_chroot(name) && setup_chroot(name)) {
1229 lxc_log_error("failed to set chroot for '%s'", name);
1230 return -1;
1231 }
1232
1233 return 0;
1234}