]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/conf.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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.
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.
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
34 #include <sys/types.h>
35 #include <sys/utsname.h>
36 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/mount.h>
42 #include <arpa/inet.h>
44 #include <netinet/in.h>
55 #define MAXINDEXLEN 20
57 #define MAXLINELEN 128
63 typedef int (*instanciate_cb
)(const char *directory
,
64 const char *file
, pid_t pid
);
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
);
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, },
85 static int write_info(const char *path
, const char *file
, const char *info
)
90 snprintf(f
, MAXPATHLEN
, "%s/%s", path
, file
);
95 if (write(fd
, info
, strlen(info
)) < 0 ||
96 write(fd
, "\n", strlen("\n") + 1) < 0)
108 static int read_info(const char *path
, const char *file
, char *info
, size_t len
)
111 char f
[MAXPATHLEN
], *token
;
113 snprintf(f
, MAXPATHLEN
, "%s/%s", path
, file
);
114 fd
= open(f
, O_RDONLY
);
121 ret
= read(fd
, info
, len
);
125 token
= strstr(info
, "\n");
134 static int delete_info(const char *path
, const char *file
)
136 char info
[MAXPATHLEN
];
139 snprintf(info
, MAXPATHLEN
, "%s/%s", path
, file
);
145 static int configure_ip4addr(int fd
, struct lxc_inetdev
*in
)
147 char addr
[INET6_ADDRSTRLEN
];
148 char bcast
[INET_ADDRSTRLEN
];
149 char line
[MAXLINELEN
];
152 if (!inet_ntop(AF_INET
, &in
->addr
, addr
, sizeof(addr
))) {
153 lxc_log_syserror("failed to convert ipv4 address");
157 if (!inet_ntop(AF_INET
, &in
->bcast
, bcast
, sizeof(bcast
))) {
158 lxc_log_syserror("failed to convert ipv4 broadcast");
163 snprintf(line
, MAXLINELEN
, "%s/%d %s\n", addr
, in
->prefix
, bcast
);
165 snprintf(line
, MAXLINELEN
, "%s %s\n", addr
, bcast
);
167 if (write(fd
, line
, strlen(line
)) < 0) {
168 lxc_log_syserror("failed to write address info");
177 static int configure_ip6addr(int fd
, struct lxc_inet6dev
*in6
)
179 char addr
[INET6_ADDRSTRLEN
];
180 char line
[MAXLINELEN
];
183 if (!inet_ntop(AF_INET6
, &in6
->addr
, addr
, sizeof(addr
))) {
184 lxc_log_syserror("failed to convert ipv4 address");
188 snprintf(line
, MAXLINELEN
, "%s/%d\n", addr
, in6
->prefix
?in6
->prefix
:64);
190 if (write(fd
, line
, strlen(line
)) < 0) {
191 lxc_log_syserror("failed to write address info");
200 static int configure_ip_address(const char *path
, struct lxc_list
*ip
, int family
)
202 char file
[MAXPATHLEN
];
203 struct lxc_list
*iterator
;
206 if (mkdir(path
, 0755)) {
207 lxc_log_syserror("failed to create directory %s", path
);
211 snprintf(file
, MAXPATHLEN
, "%s/addresses", path
);
212 fd
= creat(file
, 0755);
214 lxc_log_syserror("failed to create %s file", file
);
218 lxc_list_for_each(iterator
, ip
) {
219 err
= family
== AF_INET
?
220 configure_ip4addr(fd
, iterator
->elem
):
221 configure_ip6addr(fd
, iterator
->elem
);
234 static int configure_netdev(const char *path
, struct lxc_netdev
*netdev
)
237 char dir
[MAXPATHLEN
];
239 if (mkdir(path
, 0755)) {
240 lxc_log_syserror("failed to create %s directory", path
);
244 if (netdev
->ifname
) {
245 if (write_info(path
, "link", netdev
->ifname
))
249 if (netdev
->newname
) {
250 if (write_info(path
, "name", netdev
->newname
))
254 if (netdev
->hwaddr
) {
255 if (write_info(path
, "hwaddr", netdev
->hwaddr
))
260 if (write_info(path
, "mtu", netdev
->mtu
))
264 if (netdev
->flags
& IFF_UP
) {
265 if (write_info(path
, "up", ""))
269 if (!lxc_list_empty(&netdev
->ipv4
)) {
270 snprintf(dir
, MAXPATHLEN
, "%s/ipv4", path
);
271 if (configure_ip_address(dir
, &netdev
->ipv4
, AF_INET
))
275 if (!lxc_list_empty(&netdev
->ipv6
)) {
276 snprintf(dir
, MAXPATHLEN
, "%s/ipv6", path
);
277 if (configure_ip_address(dir
, &netdev
->ipv6
, AF_INET6
))
284 delete_info(path
, "ipv4");
286 delete_info(path
, "up");
288 delete_info(path
, "mtu");
290 delete_info(path
, "hwaddr");
292 delete_info(path
, "name");
294 delete_info(path
, "link");
300 static int configure_utsname(const char *name
, struct utsname
*utsname
)
302 char path
[MAXPATHLEN
];
304 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
306 if (write_info(path
, "utsname", utsname
->nodename
)) {
307 lxc_log_error("failed to write the utsname info");
314 static int configure_network(const char *name
, struct lxc_list
*network
)
316 struct lxc_list
*iterator
;
317 struct lxc_network
*n
;
318 char networkpath
[MAXPATHLEN
];
319 char path
[MAXPATHLEN
];
322 if (lxc_list_empty(network
))
325 snprintf(networkpath
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
326 if (mkdir(networkpath
, 0755)) {
327 lxc_log_syserror("failed to create %s directory", networkpath
);
331 lxc_list_for_each(iterator
, network
) {
335 if (n
->type
< 0 || n
->type
> MAXCONFTYPE
) {
336 lxc_log_error("invalid network configuration type '%d'",
341 snprintf(path
, MAXPATHLEN
, "%s/%s%d", networkpath
,
342 netdev_conf
[n
->type
].type
,
343 netdev_conf
[n
->type
].count
++);
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
);
357 static int configure_cgroup(const char *name
, struct lxc_list
*cgroup
)
359 char path
[MAXPATHLEN
];
360 struct lxc_list
*iterator
;
361 struct lxc_cgroup
*cg
;
364 if (lxc_list_empty(cgroup
))
367 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/cgroup", name
);
369 file
= fopen(path
, "w+");
371 lxc_log_syserror("failed to open '%s'", path
);
375 lxc_list_for_each(iterator
, cgroup
) {
377 fprintf(file
, "%s=%s\n", cg
->subsystem
, cg
->value
);
385 static int configure_tty(const char *name
, int tty
)
387 char path
[MAXPATHLEN
];
391 if (asprintf(&nbtty
, "%d", tty
) < 0) {
392 lxc_log_error("failed to convert tty number");
396 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
398 ret
= write_info(path
, "tty", nbtty
);
400 lxc_log_error("failed to write the tty info");
407 static int configure_find_fstype_cb(void* buffer
, void *data
)
418 /* we don't try 'nodev' entries */
419 if (strstr(buffer
, "nodev"))
423 fstype
+= lxc_char_left_gc(fstype
, strlen(fstype
));
424 fstype
[lxc_char_right_gc(fstype
, strlen(fstype
))] = '\0';
426 if (mount(cbarg
->rootfs
, cbarg
->testdir
, fstype
, cbarg
->mntopt
, NULL
))
430 umount(cbarg
->testdir
);
431 strcpy(cbarg
->fstype
, fstype
);
436 /* find the filesystem type with brute force */
437 static int configure_find_fstype(const char *rootfs
, char *fstype
, int mntopt
)
440 char buffer
[MAXPATHLEN
];
453 /* first we check with /etc/filesystems, in case the modules
454 * are auto-loaded and fall back to the supported kernel fs
461 cbarg
.testdir
= tempnam("/tmp", "lxc-");
462 if (!cbarg
.testdir
) {
463 lxc_log_syserror("failed to build a temp name");
467 if (mkdir(cbarg
.testdir
, 0755)) {
468 lxc_log_syserror("failed to create temporary directory");
472 for (i
= 0; i
< sizeof(fsfile
)/sizeof(fsfile
[0]); i
++) {
474 found
= lxc_file_for_each_line(fsfile
[i
],
475 configure_find_fstype_cb
,
476 buffer
, sizeof(buffer
), &cbarg
);
479 lxc_log_syserror("failed to read '%s'", fsfile
[i
]);
488 lxc_log_error("failed to determine fs type for '%s'", rootfs
);
493 rmdir(cbarg
.testdir
);
497 static int configure_rootfs_dir_cb(const char *rootfs
, const char *absrootfs
,
500 return fprintf(f
, "%s %s none rbind 0 0\n", absrootfs
, rootfs
);
503 static int configure_rootfs_blk_cb(const char *rootfs
, const char *absrootfs
,
506 char fstype
[MAXPATHLEN
];
508 if (configure_find_fstype(absrootfs
, fstype
, 0)) {
509 lxc_log_error("failed to configure mount for block device '%s'",
514 return fprintf(f
, "%s %s %s defaults 0 0\n", absrootfs
, rootfs
, fstype
);
517 static int configure_rootfs(const char *name
, const char *rootfs
)
519 char path
[MAXPATHLEN
];
520 char absrootfs
[MAXPATHLEN
];
521 char fstab
[MAXPATHLEN
];
526 typedef int (*rootfs_cb
)(const char *, const char *, FILE *);
532 { __S_IFDIR
, configure_rootfs_dir_cb
},
533 { __S_IFBLK
, configure_rootfs_blk_cb
},
536 if (!realpath(rootfs
, absrootfs
)) {
537 lxc_log_syserror("failed to get real path for '%s'", rootfs
);
541 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
543 if (mkdir(path
, 0755)) {
544 lxc_log_syserror("failed to create the '%s' directory", path
);
548 if (access(absrootfs
, F_OK
)) {
549 lxc_log_syserror("'%s' is not accessible", absrootfs
);
553 if (stat(absrootfs
, &s
)) {
554 lxc_log_syserror("failed to stat '%s'", absrootfs
);
558 for (i
= 0; i
< sizeof(rtfs_type
)/sizeof(rtfs_type
[0]); i
++) {
560 if (!__S_ISTYPE(s
.st_mode
, rtfs_type
[i
].type
))
563 snprintf(fstab
, MAXPATHLEN
, LXCPATH
"/%s/fstab", name
);
565 f
= fopen(fstab
, "a+");
567 lxc_log_syserror("failed to open fstab file");
571 ret
= rtfs_type
[i
].cb(path
, absrootfs
, f
);
576 lxc_log_error("failed to add rootfs mount in fstab");
580 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs/rootfs", name
);
582 return symlink(absrootfs
, path
);
585 lxc_log_error("unsupported rootfs type for '%s'", absrootfs
);
589 static int configure_pts(const char *name
, int pts
)
591 char path
[MAXPATHLEN
];
595 if (asprintf(&maxpts
, "%d", pts
) < 0) {
596 lxc_log_error("failed to convert max pts number");
600 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
602 ret
= write_info(path
, "pts", maxpts
);
604 lxc_log_error("failed to write the pts info");
611 static int configure_mount(const char *name
, const char *fstab
)
613 char path
[MAXPATHLEN
];
620 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/fstab", name
);
622 outfd
= open(path
, O_RDWR
|O_CREAT
|O_EXCL
, 0640);
624 lxc_log_syserror("failed to creat '%s'", path
);
628 infd
= open(fstab
, O_RDONLY
);
630 lxc_log_syserror("failed to open '%s'", fstab
);
634 if (fstat(infd
, &stat
)) {
635 lxc_log_syserror("failed to stat '%s'", fstab
);
639 if (lseek(outfd
, stat
.st_size
- 1, SEEK_SET
) < 0) {
640 lxc_log_syserror("failed to seek dest file '%s'", path
);
645 if (write(outfd
, &c
, 1) < 0) {
646 lxc_log_syserror("failed to write to '%s'", path
);
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
);
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
);
662 memcpy(dst
, src
, stat
.st_size
);
664 munmap(src
, stat
.st_size
);
665 munmap(dst
, stat
.st_size
);
672 munmap(src
, stat
.st_size
);
681 static int unconfigure_ip_addresses(const char *directory
)
683 char path
[MAXPATHLEN
];
685 snprintf(path
, MAXPATHLEN
, "%s/ipv4", directory
);
686 delete_info(path
, "addresses");
689 snprintf(path
, MAXPATHLEN
, "%s/ipv6", directory
);
690 delete_info(path
, "addresses");
696 static int unconfigure_network_cb(const char *name
, const char *directory
,
697 const char *file
, void *data
)
699 char path
[MAXPATHLEN
];
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
);
715 static int unconfigure_network(const char *name
)
717 char directory
[MAXPATHLEN
];
719 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
720 lxc_dir_for_each(name
, directory
, unconfigure_network_cb
, NULL
);
726 static int unconfigure_cgroup_cb(const char *name
, const char *directory
,
727 const char *file
, void *data
)
729 return delete_info(directory
, file
);
732 static int unconfigure_cgroup(const char *name
)
734 char filename
[MAXPATHLEN
];
737 snprintf(filename
, MAXPATHLEN
, LXCPATH
"/%s/cgroup", name
);
739 if (stat(filename
, &s
)) {
740 lxc_log_syserror("failed to stat '%s'", filename
);
744 if (S_ISDIR(s
.st_mode
)) {
745 /* old cgroup configuration */
746 lxc_dir_for_each(name
, filename
, unconfigure_cgroup_cb
, NULL
);
755 static int unconfigure_rootfs(const char *name
)
757 char path
[MAXPATHLEN
];
759 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
761 #warning deprecated code to be removed in the next version
763 /* ugly but for backward compatibily, */
764 delete_info(path
, "rootfs");
771 static int unconfigure_pts(const char *name
)
773 char path
[MAXPATHLEN
];
775 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
776 delete_info(path
, "pts");
781 static int unconfigure_tty(const char *name
)
783 char path
[MAXPATHLEN
];
785 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
786 delete_info(path
, "tty");
791 static int unconfigure_mount(const char *name
)
793 char path
[MAXPATHLEN
];
795 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
796 delete_info(path
, "fstab");
801 static int unconfigure_utsname(const char *name
)
803 char path
[MAXPATHLEN
];
805 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
806 delete_info(path
, "utsname");
811 static int setup_utsname(const char *name
)
814 char path
[MAXPATHLEN
];
815 struct utsname utsname
;
817 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
819 ret
= read_info(path
, "utsname", utsname
.nodename
,
820 sizeof(utsname
.nodename
));
822 lxc_log_syserror("failed to read utsname info");
826 if (!ret
&& sethostname(utsname
.nodename
, strlen(utsname
.nodename
))) {
827 lxc_log_syserror("failed to set the hostname to '%s'",
835 static int setup_tty(const char *name
, const struct lxc_tty_info
*tty_info
)
837 char path
[MAXPATHLEN
];
840 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
842 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
844 if (conf_has_rootfs(name
))
845 snprintf(path
, MAXPATHLEN
,
846 LXCPATH
"/%s/rootfs/dev/tty%d", name
, i
+ 1);
848 snprintf(path
, MAXPATHLEN
, "/dev/tty%d", i
+ 1);
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 :( */
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
);
864 static int setup_rootfs(const char *name
)
866 char path
[MAXPATHLEN
];
868 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
871 lxc_log_syserror("failed to set chroot %s", path
);
875 if (chdir(getenv("HOME")) && chdir("/")) {
876 lxc_log_syserror("failed to change to home directory");
883 static int setup_pts(const char *name
)
885 char mountname
[MAXPATHLEN
];
887 if (!access("/dev/pts/ptmx", F_OK
) && umount("/dev/pts")) {
888 lxc_log_syserror("failed to umount 'dev/pts'");
892 snprintf(mountname
, MAXPATHLEN
, "%spts", name
);
894 if (mount(mountname
, "/dev/pts", "devpts", MS_MGC_VAL
, "newinstance")) {
895 lxc_log_syserror("failed to mount a new instance of '/dev/pts'");
899 if (chmod("/dev/pts/ptmx", 0666)) {
900 lxc_log_syserror("failed to set permission for '/dev/pts/ptmx'");
904 if (access("/dev/ptmx", F_OK
)) {
905 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
907 lxc_log_syserror("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
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'");
920 static int setup_console(const char *name
, const char *tty
)
922 char console
[MAXPATHLEN
];
924 snprintf(console
, MAXPATHLEN
, LXCPATH
"/%s/rootfs/dev/console", name
);
926 if (access(console
, R_OK
|W_OK
))
929 if (mount(tty
, console
, "none", MS_BIND
, 0)) {
930 lxc_log_error("failed to mount the console");
937 static int setup_cgroup_cb(void* buffer
, void *data
)
939 char *key
= buffer
, *value
;
943 value
= strchr(key
, '=');
950 ret
= lxc_cgroup_set(name
, key
, value
);
952 lxc_log_syserror("failed to set cgroup '%s' = '%s' for '%s'",
957 static int setup_convert_cgroup_cb(const char *name
, const char *directory
,
958 const char *file
, void *data
)
961 char line
[MAXPATHLEN
];
963 if (read_info(directory
, file
, line
, MAXPATHLEN
)) {
964 lxc_log_error("failed to read %s", file
);
968 fprintf(f
, "%s=%s\n", file
, line
);
973 static int setup_convert_cgroup(const char *name
, char *directory
)
975 char filename
[MAXPATHLEN
];
979 snprintf(filename
, MAXPATHLEN
, LXCPATH
"/%s/cgroup.new", name
);
981 file
= fopen(filename
, "w+");
985 ret
= lxc_dir_for_each(name
, directory
, setup_convert_cgroup_cb
, file
);
989 ret
= unconfigure_cgroup(name
);
993 ret
= rename(filename
, directory
);
1005 static int setup_cgroup(const char *name
)
1007 char filename
[MAXPATHLEN
];
1008 char line
[MAXPATHLEN
];
1011 snprintf(filename
, MAXPATHLEN
, LXCPATH
"/%s/cgroup", name
);
1013 if (stat(filename
, &s
)) {
1014 lxc_log_syserror("failed to stat '%s'", filename
);
1018 if (S_ISDIR(s
.st_mode
)) {
1019 if (setup_convert_cgroup(name
, filename
)) {
1020 lxc_log_error("failed to convert old cgroup configuration");
1025 return lxc_file_for_each_line(filename
, setup_cgroup_cb
,
1026 line
, MAXPATHLEN
, (void *)name
);
1029 static int setup_mount(const char *name
)
1031 char path
[MAXPATHLEN
];
1032 struct mntent
*mntent
;
1035 unsigned long mntflags
= 0;
1037 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/fstab", name
);
1039 file
= setmntent(path
, "r");
1041 if (errno
== ENOENT
)
1043 lxc_log_syserror("failed to open '%s'", path
);
1047 while((mntent
= getmntent(file
))) {
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
;
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
);
1071 static int setup_ipv4_addr_cb(void *buffer
, void *data
)
1073 char *ifname
= data
;
1074 char *cursor
, *slash
, *addr
, *bcast
= NULL
, *prefix
= NULL
;
1078 cursor
= strstr(addr
, " ");
1082 cursor
= strstr(bcast
, "\n");
1087 slash
= strstr(addr
, "/");
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
:"");
1105 static int setup_ipv6_addr_cb(void *buffer
, void *data
)
1107 char *ifname
= data
;
1108 char *cursor
, *slash
, *addr
, *bcast
= NULL
, *prefix
= NULL
;
1112 cursor
= strstr(addr
, " ");
1116 cursor
= strstr(bcast
, "\n");
1121 slash
= strstr(addr
, "/");
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
:"");
1139 static int setup_hw_addr(char *hwaddr
, const char *ifname
)
1141 struct sockaddr sockaddr
;
1145 if (lxc_convert_mac(hwaddr
, &sockaddr
)) {
1146 fprintf(stderr
, "conversion has failed\n");
1150 memcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
1151 memcpy((char *) &ifr
.ifr_hwaddr
, (char *) &sockaddr
, sizeof(sockaddr
));
1153 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1159 ret
= ioctl(fd
, SIOCSIFHWADDR
, &ifr
);
1167 static int setup_ip_addr(const char *directory
, const char *ifname
)
1169 char path
[MAXPATHLEN
], line
[MAXLINELEN
];
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
);
1180 static int setup_ip6_addr(const char *directory
, const char *ifname
)
1182 char path
[MAXPATHLEN
], line
[MAXLINELEN
];
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
);
1193 static int setup_network_cb(const char *name
, const char *directory
,
1194 const char *file
, void *data
)
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
;
1204 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1206 if (read_info(path
, "ifindex", strindex
, sizeof(strindex
))) {
1207 lxc_log_error("failed to read ifindex info");
1211 ifindex
= atoi(strindex
);
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");
1221 if (!if_indextoname(ifindex
, current_ifname
)) {
1222 lxc_log_error("no interface corresponding to index '%d'",
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",
1233 current_ifname
= newname
;
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'",
1244 if (setup_ip_addr(path
, current_ifname
)) {
1245 lxc_log_error("failed to setup ip addresses for '%s'",
1250 if (setup_ip6_addr(path
, current_ifname
)) {
1251 lxc_log_error("failed to setup ipv6 addresses for '%s'",
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
);
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");
1272 static int setup_network(const char *name
)
1274 char directory
[MAXPATHLEN
];
1276 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1277 return lxc_dir_for_each(name
, directory
, setup_network_cb
, NULL
);
1280 int conf_has(const char *name
, const char *info
)
1283 char path
[MAXPATHLEN
];
1286 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/%s", name
, info
);
1288 if (!stat(path
, &st
) || !lstat(path
, &st
)) {
1293 if (errno
== ENOENT
) {
1298 lxc_log_syserror("failed to stat %s info", info
);
1303 int lxc_conf_init(struct lxc_conf
*conf
)
1305 conf
->rootfs
= NULL
;
1307 conf
->utsname
= NULL
;
1310 lxc_list_init(&conf
->cgroup
);
1311 lxc_list_init(&conf
->networks
);
1315 int lxc_configure(const char *name
, struct lxc_conf
*conf
)
1320 if (conf
->utsname
&& configure_utsname(name
, conf
->utsname
)) {
1321 lxc_log_error("failed to configure the utsname");
1322 return -LXC_ERROR_CONF_UTSNAME
;
1325 if (configure_cgroup(name
, &conf
->cgroup
)) {
1326 lxc_log_error("failed to configure the control group");
1327 return -LXC_ERROR_CONF_CGROUP
;
1330 if (configure_network(name
, &conf
->networks
)) {
1331 lxc_log_error("failed to configure the network");
1332 return -LXC_ERROR_CONF_NETWORK
;
1335 if (conf
->tty
&& configure_tty(name
, conf
->tty
)) {
1336 lxc_log_error("failed to configure the tty");
1337 return -LXC_ERROR_CONF_TTY
;
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
;
1345 if (conf
->rootfs
&& configure_rootfs(name
, conf
->rootfs
)) {
1346 lxc_log_error("failed to configure the rootfs");
1347 return -LXC_ERROR_CONF_ROOTFS
;
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
;
1358 int lxc_unconfigure(const char *name
)
1360 if (conf_has_utsname(name
) && unconfigure_utsname(name
))
1361 lxc_log_error("failed to cleanup utsname");
1363 if (conf_has_network(name
) && unconfigure_network(name
))
1364 lxc_log_error("failed to cleanup the network");
1366 if (conf_has_cgroup(name
) && unconfigure_cgroup(name
))
1367 lxc_log_error("failed to cleanup cgroup");
1369 if (conf_has_tty(name
) && unconfigure_tty(name
))
1370 lxc_log_error("failed to cleanup tty");
1372 if (conf_has_rootfs(name
) && unconfigure_rootfs(name
))
1373 lxc_log_error("failed to cleanup rootfs");
1375 if (conf_has_fstab(name
) && unconfigure_mount(name
))
1376 lxc_log_error("failed to cleanup mount");
1378 if (conf_has_pts(name
) && unconfigure_pts(name
))
1379 lxc_log_error("failed to cleanup pts");
1384 static int instanciate_veth(const char *directory
, const char *file
, pid_t pid
)
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;
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");
1398 if (read_info(path
, "link", bridge
, IFNAMSIZ
)) {
1399 lxc_log_error("failed to read bridge info");
1403 if (lxc_veth_create(veth1
, veth2
)) {
1404 lxc_log_error("failed to create %s-%s/%s", veth1
, veth2
, bridge
);
1408 if (!read_info(path
, "mtu", strmtu
, MAXMTULEN
)) {
1409 if (sscanf(strmtu
, "%u", &mtu
) < 1) {
1410 lxc_log_error("invalid mtu size '%d'", mtu
);
1414 if (lxc_device_set_mtu(veth1
, mtu
)) {
1415 lxc_log_error("failed to set mtu for '%s'", veth1
);
1419 if (lxc_device_set_mtu(veth2
, mtu
)) {
1420 lxc_log_error("failed to set mtu for '%s'", veth2
);
1425 if (lxc_bridge_attach(bridge
, veth1
)) {
1426 lxc_log_error("failed to attach '%s' to the bridge '%s'",
1431 ifindex
= if_nametoindex(veth2
);
1433 lxc_log_error("failed to retrieve the index for %s", veth2
);
1437 if (!asprintf(&strindex
, "%d", ifindex
)) {
1438 lxc_log_syserror("failed to allocate memory");
1442 if (write_info(path
, "ifindex", strindex
)) {
1443 lxc_log_error("failed to write interface index to %s", path
);
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
);
1463 lxc_device_delete(veth1
);
1466 static int instanciate_macvlan(const char *directory
, const char *file
, pid_t pid
)
1468 char path
[MAXPATHLEN
], *strindex
= NULL
, *peer
= NULL
;
1469 char link
[IFNAMSIZ
];
1470 int ifindex
, ret
= -1;
1472 if (!asprintf(&peer
, "%s~%d", file
, pid
)) {
1473 lxc_log_syserror("failed to allocate memory");
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");
1483 if (lxc_macvlan_create(link
, peer
)) {
1484 lxc_log_error("failed to create macvlan interface '%s' on '%s'",
1489 ifindex
= if_nametoindex(peer
);
1491 lxc_log_error("failed to retrieve the index for %s", peer
);
1495 if (!asprintf(&strindex
, "%d", ifindex
)) {
1496 lxc_log_syserror("failed to allocate memory");
1500 if (write_info(path
, "ifindex", strindex
)) {
1501 lxc_log_error("failed to write interface index to %s", path
);
1512 static int instanciate_phys(const char *directory
, const char *file
, pid_t pid
)
1514 char path
[MAXPATHLEN
], *strindex
= NULL
;
1515 char link
[IFNAMSIZ
];
1516 int ifindex
, ret
= -1;
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");
1524 ifindex
= if_nametoindex(link
);
1526 lxc_log_error("failed to retrieve the index for %s", link
);
1530 if (!asprintf(&strindex
, "%d", ifindex
)) {
1531 lxc_log_syserror("failed to allocate memory");
1535 if (write_info(path
, "ifindex", strindex
)) {
1536 lxc_log_error("failed to write interface index to %s", path
);
1546 static int instanciate_empty(const char *directory
, const char *file
, pid_t pid
)
1548 char path
[MAXPATHLEN
], *strindex
= NULL
;
1551 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1552 if (!asprintf(&strindex
, "%d", 0)) {
1553 lxc_log_error("not enough memory");
1557 if (write_info(path
, "ifindex", strindex
)) {
1558 lxc_log_error("failed to write interface index to %s", path
);
1568 static int instanciate_netdev_cb(const char *name
, const char *directory
,
1569 const char *file
, void *data
)
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
);
1585 static int instanciate_netdev(const char *name
, pid_t pid
)
1587 char directory
[MAXPATHLEN
];
1589 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1590 return lxc_dir_for_each(name
, directory
, instanciate_netdev_cb
, &pid
);
1593 static int move_netdev_cb(const char *name
, const char *directory
,
1594 const char *file
, void *data
)
1596 char path
[MAXPATHLEN
], ifname
[IFNAMSIZ
], strindex
[MAXINDEXLEN
];
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
);
1606 ifindex
= atoi(strindex
);
1610 if (!if_indextoname(ifindex
, ifname
)) {
1611 lxc_log_error("interface with index %d does not exist",
1616 if (lxc_device_move(ifname
, *pid
)) {
1617 lxc_log_error("failed to move %s to %d", ifname
, *pid
);
1624 static int move_netdev(const char *name
, pid_t pid
)
1626 char directory
[MAXPATHLEN
];
1627 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1628 return lxc_dir_for_each(name
, directory
, move_netdev_cb
, &pid
);
1631 int conf_create_network(const char *name
, pid_t pid
)
1633 if (instanciate_netdev(name
, pid
)) {
1634 lxc_log_error("failed to instantiate the network devices");
1638 if (move_netdev(name
, pid
)) {
1639 lxc_log_error("failed to move the netdev to the container");
1646 #ifdef NETWORK_DESTROY
1647 static int delete_netdev_cb(const char *name
, const char *directory
,
1648 const char *file
, void *data
)
1650 char strindex
[MAXINDEXLEN
];
1651 char path
[MAXPATHLEN
];
1652 char ifname
[IFNAMSIZ
];
1655 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1657 if (read_info(path
, "ifindex", strindex
, MAXINDEXLEN
)) {
1658 lxc_log_error("failed to read ifindex info");
1662 ifindex
= atoi(strindex
);
1666 /* TODO : temporary code - needs wait on namespace */
1667 for (i
= 0; i
< 120; i
++) {
1668 if (if_indextoname(ifindex
, ifname
))
1671 printf("waiting for interface #%d to come back\n", ifindex
);
1673 printf("."); fflush(stdout
);
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
);
1683 delete_info(path
, "ifindex");
1689 int conf_destroy_network(const char *name
)
1691 #ifdef NETWORK_DESTROY
1692 char directory
[MAXPATHLEN
];
1694 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1696 if (lxc_dir_for_each(name
, directory
, delete_netdev_cb
, NULL
)) {
1697 lxc_log_error("failed to remove the network devices");
1704 int lxc_create_tty(const char *name
, struct lxc_tty_info
*tty_info
)
1706 char path
[MAXPATHLEN
];
1710 tty_info
->nbtty
= 0;
1712 if (!conf_has_tty(name
))
1715 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
1717 if (read_info(path
, "tty", tty
, sizeof(tty
)) < 0) {
1718 lxc_log_syserror("failed to read tty info");
1722 tty_info
->nbtty
= atoi(tty
);
1723 tty_info
->pty_info
=
1724 malloc(sizeof(*tty_info
->pty_info
)*tty_info
->nbtty
);
1726 if (!tty_info
->pty_info
) {
1727 lxc_log_syserror("failed to allocate pty_info");
1731 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
1733 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
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
);
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
);
1753 free(tty_info
->pty_info
);
1757 void lxc_delete_tty(struct lxc_tty_info
*tty_info
)
1761 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
1762 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
1764 close(pty_info
->master
);
1765 close(pty_info
->slave
);
1768 free(tty_info
->pty_info
);
1769 tty_info
->nbtty
= 0;
1772 enum { utsname
, network
, cgroup
, fstab
, console
, tty
, rootfs
, pts
};
1774 static int conf_is_set(long flags
, int subsystem
)
1776 return flags
& (1 << subsystem
);
1779 static void conf_set_flag(long *flags
, int subsystem
)
1781 *flags
|= 1 << subsystem
;
1784 static long make_conf_flagset(const char *name
, const char *cons
,
1785 const struct lxc_tty_info
*tty_info
)
1789 if (conf_has_utsname(name
))
1790 conf_set_flag(&flags
, utsname
);
1792 if (conf_has_network(name
))
1793 conf_set_flag(&flags
, network
);
1795 if (conf_has_cgroup(name
))
1796 conf_set_flag(&flags
, cgroup
);
1798 if (conf_has_fstab(name
))
1799 conf_set_flag(&flags
, fstab
);
1801 if (conf_has_rootfs(name
))
1802 conf_set_flag(&flags
, rootfs
);
1804 if (conf_has_pts(name
))
1805 conf_set_flag(&flags
, pts
);
1807 if (tty_info
->nbtty
)
1808 conf_set_flag(&flags
, tty
);
1811 conf_set_flag(&flags
, console
);
1816 int lxc_setup(const char *name
, const char *cons
,
1817 const struct lxc_tty_info
*tty_info
)
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
);
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;