]>
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 lxc_log_define(lxc_conf
, lxc
);
58 #define MAXINDEXLEN 20
60 #define MAXLINELEN 128
66 typedef int (*instanciate_cb
)(const char *directory
,
67 const char *file
, pid_t pid
);
81 static int instanciate_veth(const char *, const char *, pid_t
);
82 static int instanciate_macvlan(const char *, const char *, pid_t
);
83 static int instanciate_phys(const char *, const char *, pid_t
);
84 static int instanciate_empty(const char *, const char *, pid_t
);
85 static int unconfigure_cgroup(const char *name
);
87 static struct netdev_conf netdev_conf
[MAXCONFTYPE
+ 1] = {
88 [VETH
] = { "veth", instanciate_veth
, 0 },
89 [MACVLAN
] = { "macvlan", instanciate_macvlan
, 0, },
90 [PHYS
] = { "phys", instanciate_phys
, 0, },
91 [EMPTY
] = { "empty", instanciate_empty
, 0, },
94 static struct mount_opt mount_opt
[] = {
96 { "ro", 0, MS_RDONLY
},
97 { "rw", 1, MS_RDONLY
},
98 { "suid", 1, MS_NOSUID
},
99 { "nosuid", 0, MS_NOSUID
},
100 { "dev", 1, MS_NODEV
},
101 { "nodev", 0, MS_NODEV
},
102 { "exec", 1, MS_NOEXEC
},
103 { "noexec", 0, MS_NOEXEC
},
104 { "sync", 0, MS_SYNCHRONOUS
},
105 { "async", 1, MS_SYNCHRONOUS
},
106 { "remount", 0, MS_REMOUNT
},
107 { "mand", 0, MS_MANDLOCK
},
108 { "nomand", 1, MS_MANDLOCK
},
109 { "atime", 1, MS_NOATIME
},
110 { "noatime", 0, MS_NOATIME
},
111 { "diratime", 1, MS_NODIRATIME
},
112 { "nodiratime", 0, MS_NODIRATIME
},
113 { "bind", 0, MS_BIND
},
114 { "rbind", 0, MS_BIND
|MS_REC
},
118 static int write_info(const char *path
, const char *file
, const char *info
)
123 snprintf(f
, MAXPATHLEN
, "%s/%s", path
, file
);
128 if (write(fd
, info
, strlen(info
)) < 0 ||
129 write(fd
, "\n", strlen("\n") + 1) < 0)
141 static int read_info(const char *path
, const char *file
, char *info
, size_t len
)
144 char f
[MAXPATHLEN
], *token
;
146 snprintf(f
, MAXPATHLEN
, "%s/%s", path
, file
);
147 fd
= open(f
, O_RDONLY
);
154 ret
= read(fd
, info
, len
);
158 token
= strstr(info
, "\n");
167 static int delete_info(const char *path
, const char *file
)
169 char info
[MAXPATHLEN
];
172 snprintf(info
, MAXPATHLEN
, "%s/%s", path
, file
);
178 static int configure_ip4addr(int fd
, struct lxc_inetdev
*in
)
180 char addr
[INET6_ADDRSTRLEN
];
181 char bcast
[INET_ADDRSTRLEN
];
182 char line
[MAXLINELEN
];
185 if (!inet_ntop(AF_INET
, &in
->addr
, addr
, sizeof(addr
))) {
186 SYSERROR("failed to convert ipv4 address");
190 if (!inet_ntop(AF_INET
, &in
->bcast
, bcast
, sizeof(bcast
))) {
191 SYSERROR("failed to convert ipv4 broadcast");
196 snprintf(line
, MAXLINELEN
, "%s/%d %s\n", addr
, in
->prefix
, bcast
);
198 snprintf(line
, MAXLINELEN
, "%s %s\n", addr
, bcast
);
200 if (write(fd
, line
, strlen(line
)) < 0) {
201 SYSERROR("failed to write address info");
210 static int configure_ip6addr(int fd
, struct lxc_inet6dev
*in6
)
212 char addr
[INET6_ADDRSTRLEN
];
213 char line
[MAXLINELEN
];
216 if (!inet_ntop(AF_INET6
, &in6
->addr
, addr
, sizeof(addr
))) {
217 SYSERROR("failed to convert ipv4 address");
221 snprintf(line
, MAXLINELEN
, "%s/%d\n", addr
, in6
->prefix
?in6
->prefix
:64);
223 if (write(fd
, line
, strlen(line
)) < 0) {
224 SYSERROR("failed to write address info");
233 static int configure_ip_address(const char *path
, struct lxc_list
*ip
, int family
)
235 char file
[MAXPATHLEN
];
236 struct lxc_list
*iterator
;
239 if (mkdir(path
, 0755)) {
240 SYSERROR("failed to create directory %s", path
);
244 snprintf(file
, MAXPATHLEN
, "%s/addresses", path
);
245 fd
= creat(file
, 0755);
247 SYSERROR("failed to create %s file", file
);
251 lxc_list_for_each(iterator
, ip
) {
252 err
= family
== AF_INET
?
253 configure_ip4addr(fd
, iterator
->elem
):
254 configure_ip6addr(fd
, iterator
->elem
);
267 static int configure_netdev(const char *path
, struct lxc_netdev
*netdev
)
270 char dir
[MAXPATHLEN
];
272 if (mkdir(path
, 0755)) {
273 SYSERROR("failed to create %s directory", path
);
277 if (netdev
->ifname
) {
278 if (write_info(path
, "link", netdev
->ifname
))
282 if (netdev
->newname
) {
283 if (write_info(path
, "name", netdev
->newname
))
287 if (netdev
->hwaddr
) {
288 if (write_info(path
, "hwaddr", netdev
->hwaddr
))
293 if (write_info(path
, "mtu", netdev
->mtu
))
297 if (netdev
->flags
& IFF_UP
) {
298 if (write_info(path
, "up", ""))
302 if (!lxc_list_empty(&netdev
->ipv4
)) {
303 snprintf(dir
, MAXPATHLEN
, "%s/ipv4", path
);
304 if (configure_ip_address(dir
, &netdev
->ipv4
, AF_INET
))
308 if (!lxc_list_empty(&netdev
->ipv6
)) {
309 snprintf(dir
, MAXPATHLEN
, "%s/ipv6", path
);
310 if (configure_ip_address(dir
, &netdev
->ipv6
, AF_INET6
))
317 delete_info(path
, "ipv4");
319 delete_info(path
, "up");
321 delete_info(path
, "mtu");
323 delete_info(path
, "hwaddr");
325 delete_info(path
, "name");
327 delete_info(path
, "link");
333 static int configure_utsname(const char *name
, struct utsname
*utsname
)
335 char path
[MAXPATHLEN
];
337 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
339 if (write_info(path
, "utsname", utsname
->nodename
)) {
340 ERROR("failed to write the utsname info");
347 static int configure_network(const char *name
, struct lxc_list
*network
)
349 struct lxc_list
*iterator
;
350 struct lxc_network
*n
;
351 char networkpath
[MAXPATHLEN
];
352 char path
[MAXPATHLEN
];
355 if (lxc_list_empty(network
))
358 snprintf(networkpath
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
359 if (mkdir(networkpath
, 0755)) {
360 SYSERROR("failed to create %s directory", networkpath
);
364 lxc_list_for_each(iterator
, network
) {
368 if (n
->type
< 0 || n
->type
> MAXCONFTYPE
) {
369 ERROR("invalid network configuration type '%d'",
374 snprintf(path
, MAXPATHLEN
, "%s/%s%d", networkpath
,
375 netdev_conf
[n
->type
].type
,
376 netdev_conf
[n
->type
].count
++);
378 if (configure_netdev(path
, lxc_list_first_elem(&n
->netdev
))) {
379 ERROR("failed to configure network type %s",
380 netdev_conf
[n
->type
].type
);
390 static int configure_cgroup(const char *name
, struct lxc_list
*cgroup
)
392 char path
[MAXPATHLEN
];
393 struct lxc_list
*iterator
;
394 struct lxc_cgroup
*cg
;
397 if (lxc_list_empty(cgroup
))
400 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/cgroup", name
);
402 file
= fopen(path
, "w+");
404 SYSERROR("failed to open '%s'", path
);
408 lxc_list_for_each(iterator
, cgroup
) {
410 fprintf(file
, "%s=%s\n", cg
->subsystem
, cg
->value
);
418 static int configure_tty(const char *name
, int tty
)
420 char path
[MAXPATHLEN
];
424 if (asprintf(&nbtty
, "%d", tty
) < 0) {
425 ERROR("failed to convert tty number");
429 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
431 ret
= write_info(path
, "tty", nbtty
);
433 ERROR("failed to write the tty info");
440 static int configure_find_fstype_cb(void* buffer
, void *data
)
451 /* we don't try 'nodev' entries */
452 if (strstr(buffer
, "nodev"))
456 fstype
+= lxc_char_left_gc(fstype
, strlen(fstype
));
457 fstype
[lxc_char_right_gc(fstype
, strlen(fstype
))] = '\0';
459 if (mount(cbarg
->rootfs
, cbarg
->testdir
, fstype
, cbarg
->mntopt
, NULL
))
463 umount(cbarg
->testdir
);
464 strcpy(cbarg
->fstype
, fstype
);
469 /* find the filesystem type with brute force */
470 static int configure_find_fstype(const char *rootfs
, char *fstype
, int mntopt
)
473 char buffer
[MAXPATHLEN
];
486 /* first we check with /etc/filesystems, in case the modules
487 * are auto-loaded and fall back to the supported kernel fs
494 cbarg
.testdir
= tempnam("/tmp", "lxc-");
495 if (!cbarg
.testdir
) {
496 SYSERROR("failed to build a temp name");
500 if (mkdir(cbarg
.testdir
, 0755)) {
501 SYSERROR("failed to create temporary directory");
505 for (i
= 0; i
< sizeof(fsfile
)/sizeof(fsfile
[0]); i
++) {
507 found
= lxc_file_for_each_line(fsfile
[i
],
508 configure_find_fstype_cb
,
509 buffer
, sizeof(buffer
), &cbarg
);
512 SYSERROR("failed to read '%s'", fsfile
[i
]);
521 ERROR("failed to determine fs type for '%s'", rootfs
);
526 rmdir(cbarg
.testdir
);
530 static int configure_rootfs_dir_cb(const char *rootfs
, const char *absrootfs
,
533 return fprintf(f
, "%s %s none rbind 0 0\n", absrootfs
, rootfs
);
536 static int configure_rootfs_blk_cb(const char *rootfs
, const char *absrootfs
,
539 char fstype
[MAXPATHLEN
];
541 if (configure_find_fstype(absrootfs
, fstype
, 0)) {
542 ERROR("failed to configure mount for block device '%s'",
547 return fprintf(f
, "%s %s %s defaults 0 0\n", absrootfs
, rootfs
, fstype
);
550 static int configure_rootfs(const char *name
, const char *rootfs
)
552 char path
[MAXPATHLEN
];
553 char absrootfs
[MAXPATHLEN
];
554 char fstab
[MAXPATHLEN
];
559 typedef int (*rootfs_cb
)(const char *, const char *, FILE *);
565 { __S_IFDIR
, configure_rootfs_dir_cb
},
566 { __S_IFBLK
, configure_rootfs_blk_cb
},
569 if (!realpath(rootfs
, absrootfs
)) {
570 SYSERROR("failed to get real path for '%s'", rootfs
);
574 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
576 if (mkdir(path
, 0755)) {
577 SYSERROR("failed to create the '%s' directory", path
);
581 if (access(absrootfs
, F_OK
)) {
582 SYSERROR("'%s' is not accessible", absrootfs
);
586 if (stat(absrootfs
, &s
)) {
587 SYSERROR("failed to stat '%s'", absrootfs
);
591 for (i
= 0; i
< sizeof(rtfs_type
)/sizeof(rtfs_type
[0]); i
++) {
593 if (!__S_ISTYPE(s
.st_mode
, rtfs_type
[i
].type
))
596 snprintf(fstab
, MAXPATHLEN
, LXCPATH
"/%s/fstab", name
);
598 f
= fopen(fstab
, "a+");
600 SYSERROR("failed to open fstab file");
604 ret
= rtfs_type
[i
].cb(path
, absrootfs
, f
);
609 ERROR("failed to add rootfs mount in fstab");
613 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs/rootfs", name
);
615 return symlink(absrootfs
, path
);
618 ERROR("unsupported rootfs type for '%s'", absrootfs
);
622 static int configure_pts(const char *name
, int pts
)
624 char path
[MAXPATHLEN
];
628 if (asprintf(&maxpts
, "%d", pts
) < 0) {
629 ERROR("failed to convert max pts number");
633 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
635 ret
= write_info(path
, "pts", maxpts
);
637 ERROR("failed to write the pts info");
644 static int configure_mount(const char *name
, const char *fstab
)
646 char path
[MAXPATHLEN
];
653 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/fstab", name
);
655 outfd
= open(path
, O_RDWR
|O_CREAT
|O_EXCL
, 0640);
657 SYSERROR("failed to creat '%s'", path
);
661 infd
= open(fstab
, O_RDONLY
);
663 SYSERROR("failed to open '%s'", fstab
);
667 if (fstat(infd
, &stat
)) {
668 SYSERROR("failed to stat '%s'", fstab
);
672 if (lseek(outfd
, stat
.st_size
- 1, SEEK_SET
) < 0) {
673 SYSERROR("failed to seek dest file '%s'", path
);
678 if (write(outfd
, &c
, 1) < 0) {
679 SYSERROR("failed to write to '%s'", path
);
683 src
= mmap(NULL
, stat
.st_size
, PROT_READ
, MAP_SHARED
, infd
, 0L);
684 if (src
== MAP_FAILED
) {
685 SYSERROR("failed to mmap '%s'", fstab
);
689 dst
= mmap(NULL
, stat
.st_size
, PROT_WRITE
, MAP_SHARED
, outfd
, 0L);
690 if (dst
== MAP_FAILED
) {
691 SYSERROR("failed to mmap '%s'", path
);
695 memcpy(dst
, src
, stat
.st_size
);
697 munmap(src
, stat
.st_size
);
698 munmap(dst
, stat
.st_size
);
705 munmap(src
, stat
.st_size
);
714 static int unconfigure_ip_addresses(const char *directory
)
716 char path
[MAXPATHLEN
];
718 snprintf(path
, MAXPATHLEN
, "%s/ipv4", directory
);
719 delete_info(path
, "addresses");
722 snprintf(path
, MAXPATHLEN
, "%s/ipv6", directory
);
723 delete_info(path
, "addresses");
729 static int unconfigure_network_cb(const char *name
, const char *directory
,
730 const char *file
, void *data
)
732 char path
[MAXPATHLEN
];
734 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
735 delete_info(path
, "ifindex");
736 delete_info(path
, "name");
737 delete_info(path
, "addr");
738 delete_info(path
, "link");
739 delete_info(path
, "hwaddr");
740 delete_info(path
, "mtu");
741 delete_info(path
, "up");
742 unconfigure_ip_addresses(path
);
748 static int unconfigure_network(const char *name
)
750 char directory
[MAXPATHLEN
];
752 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
753 lxc_dir_for_each(name
, directory
, unconfigure_network_cb
, NULL
);
759 static int unconfigure_cgroup_cb(const char *name
, const char *directory
,
760 const char *file
, void *data
)
762 return delete_info(directory
, file
);
765 static int unconfigure_cgroup(const char *name
)
767 char filename
[MAXPATHLEN
];
770 snprintf(filename
, MAXPATHLEN
, LXCPATH
"/%s/cgroup", name
);
772 if (stat(filename
, &s
)) {
773 SYSERROR("failed to stat '%s'", filename
);
777 if (S_ISDIR(s
.st_mode
)) {
778 /* old cgroup configuration */
779 lxc_dir_for_each(name
, filename
, unconfigure_cgroup_cb
, NULL
);
788 static int unconfigure_rootfs(const char *name
)
790 char path
[MAXPATHLEN
];
792 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
794 #warning deprecated code to be removed in the next version
796 /* ugly but for backward compatibily, */
797 delete_info(path
, "rootfs");
804 static int unconfigure_pts(const char *name
)
806 char path
[MAXPATHLEN
];
808 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
809 delete_info(path
, "pts");
814 static int unconfigure_tty(const char *name
)
816 char path
[MAXPATHLEN
];
818 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
819 delete_info(path
, "tty");
824 static int unconfigure_mount(const char *name
)
826 char path
[MAXPATHLEN
];
828 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
829 delete_info(path
, "fstab");
834 static int unconfigure_utsname(const char *name
)
836 char path
[MAXPATHLEN
];
838 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
839 delete_info(path
, "utsname");
844 static int setup_utsname(const char *name
)
847 char path
[MAXPATHLEN
];
848 struct utsname utsname
;
850 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
852 ret
= read_info(path
, "utsname", utsname
.nodename
,
853 sizeof(utsname
.nodename
));
855 SYSERROR("failed to read utsname info");
859 if (!ret
&& sethostname(utsname
.nodename
, strlen(utsname
.nodename
))) {
860 SYSERROR("failed to set the hostname to '%s'",
868 static int setup_tty(const char *name
, const struct lxc_tty_info
*tty_info
)
870 char path
[MAXPATHLEN
];
873 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
875 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
877 if (conf_has_rootfs(name
))
878 snprintf(path
, MAXPATHLEN
,
879 LXCPATH
"/%s/rootfs/dev/tty%d", name
, i
+ 1);
881 snprintf(path
, MAXPATHLEN
, "/dev/tty%d", i
+ 1);
883 /* At this point I can not use the "access" function
884 * to check the file is present or not because it fails
885 * with EACCES errno and I don't know why :( */
887 if (mount(pty_info
->name
, path
, "none", MS_BIND
, 0)) {
888 WARN("failed to mount '%s'->'%s'",
889 pty_info
->name
, path
);
897 static int setup_rootfs(const char *name
)
899 char path
[MAXPATHLEN
];
901 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
904 SYSERROR("failed to set chroot %s", path
);
908 if (chdir(getenv("HOME")) && chdir("/")) {
909 SYSERROR("failed to change to home directory");
916 static int setup_pts(const char *name
)
918 char mountname
[MAXPATHLEN
];
920 if (!access("/dev/pts/ptmx", F_OK
) && umount("/dev/pts")) {
921 SYSERROR("failed to umount 'dev/pts'");
925 snprintf(mountname
, MAXPATHLEN
, "%spts", name
);
927 if (mount(mountname
, "/dev/pts", "devpts", MS_MGC_VAL
, "newinstance")) {
928 SYSERROR("failed to mount a new instance of '/dev/pts'");
932 if (chmod("/dev/pts/ptmx", 0666)) {
933 SYSERROR("failed to set permission for '/dev/pts/ptmx'");
937 if (access("/dev/ptmx", F_OK
)) {
938 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
940 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
944 /* fallback here, /dev/pts/ptmx exists just mount bind */
945 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND
, 0)) {
946 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
953 static int setup_console(const char *name
, const char *tty
)
955 char console
[MAXPATHLEN
];
957 snprintf(console
, MAXPATHLEN
, LXCPATH
"/%s/rootfs/dev/console", name
);
959 if (access(console
, R_OK
|W_OK
))
962 if (mount(tty
, console
, "none", MS_BIND
, 0)) {
963 ERROR("failed to mount the console");
970 static int setup_cgroup_cb(void* buffer
, void *data
)
972 char *key
= buffer
, *value
;
976 value
= strchr(key
, '=');
983 ret
= lxc_cgroup_set(name
, key
, value
);
985 SYSERROR("failed to set cgroup '%s' = '%s' for '%s'",
990 static int setup_convert_cgroup_cb(const char *name
, const char *directory
,
991 const char *file
, void *data
)
994 char line
[MAXPATHLEN
];
996 if (read_info(directory
, file
, line
, MAXPATHLEN
)) {
997 ERROR("failed to read %s", file
);
1001 fprintf(f
, "%s=%s\n", file
, line
);
1006 static int setup_convert_cgroup(const char *name
, char *directory
)
1008 char filename
[MAXPATHLEN
];
1012 snprintf(filename
, MAXPATHLEN
, LXCPATH
"/%s/cgroup.new", name
);
1014 file
= fopen(filename
, "w+");
1018 ret
= lxc_dir_for_each(name
, directory
, setup_convert_cgroup_cb
, file
);
1022 ret
= unconfigure_cgroup(name
);
1026 ret
= rename(filename
, directory
);
1038 static int setup_cgroup(const char *name
)
1040 char filename
[MAXPATHLEN
];
1041 char line
[MAXPATHLEN
];
1044 snprintf(filename
, MAXPATHLEN
, LXCPATH
"/%s/cgroup", name
);
1046 if (stat(filename
, &s
)) {
1047 SYSERROR("failed to stat '%s'", filename
);
1051 if (S_ISDIR(s
.st_mode
)) {
1052 if (setup_convert_cgroup(name
, filename
)) {
1053 ERROR("failed to convert old cgroup configuration");
1058 return lxc_file_for_each_line(filename
, setup_cgroup_cb
,
1059 line
, MAXPATHLEN
, (void *)name
);
1062 static void parse_mntopt(char *opt
, unsigned long *flags
, char **data
)
1064 struct mount_opt
*mo
;
1066 /* If opt is found in mount_opt, set or clear flags.
1067 * Otherwise append it to data. */
1069 for (mo
= &mount_opt
[0]; mo
->name
!= NULL
; mo
++) {
1070 if (!strncmp(opt
, mo
->name
, strlen(mo
->name
))) {
1072 *flags
&= ~mo
->flag
;
1084 static int parse_mntopts(struct mntent
*mntent
, unsigned long *mntflags
,
1088 char *p
, *saveptr
= NULL
;
1090 if (!mntent
->mnt_opts
)
1093 s
= strdup(mntent
->mnt_opts
);
1095 SYSERROR("failed to allocate memory");
1099 data
= malloc(strlen(s
) + 1);
1101 SYSERROR("failed to allocate memory");
1107 for (p
= strtok_r(s
, ",", &saveptr
); p
!= NULL
;
1108 p
= strtok_r(NULL
, ",", &saveptr
))
1109 parse_mntopt(p
, mntflags
, &data
);
1120 static int setup_mount(const char *name
)
1122 char path
[MAXPATHLEN
];
1123 struct mntent
*mntent
;
1126 unsigned long mntflags
;
1129 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/fstab", name
);
1131 file
= setmntent(path
, "r");
1133 if (errno
== ENOENT
)
1135 SYSERROR("failed to open '%s'", path
);
1139 while ((mntent
= getmntent(file
))) {
1142 if (parse_mntopts(mntent
, &mntflags
, &mntdata
) < 0) {
1143 ERROR("failed to parse mount option '%s'",
1148 if (mount(mntent
->mnt_fsname
, mntent
->mnt_dir
,
1149 mntent
->mnt_type
, mntflags
, mntdata
)) {
1150 SYSERROR("failed to mount '%s' on '%s'",
1151 mntent
->mnt_fsname
, mntent
->mnt_dir
);
1163 static int setup_ipv4_addr_cb(void *buffer
, void *data
)
1165 char *ifname
= data
;
1166 char *cursor
, *slash
, *addr
, *bcast
= NULL
, *prefix
= NULL
;
1170 cursor
= strstr(addr
, " ");
1174 cursor
= strstr(bcast
, "\n");
1179 slash
= strstr(addr
, "/");
1188 if (lxc_ip_addr_add(ifname
, addr
, p
, bcast
)) {
1189 ERROR("failed to set %s to addr %s/%d %s", ifname
,
1190 addr
, p
, bcast
?bcast
:"");
1197 static int setup_ipv6_addr_cb(void *buffer
, void *data
)
1199 char *ifname
= data
;
1200 char *cursor
, *slash
, *addr
, *bcast
= NULL
, *prefix
= NULL
;
1204 cursor
= strstr(addr
, " ");
1208 cursor
= strstr(bcast
, "\n");
1213 slash
= strstr(addr
, "/");
1222 if (lxc_ip6_addr_add(ifname
, addr
, p
, bcast
)) {
1223 ERROR("failed to set %s to addr %s/%d %s", ifname
,
1224 addr
, p
, bcast
?bcast
:"");
1231 static int setup_hw_addr(char *hwaddr
, const char *ifname
)
1233 struct sockaddr sockaddr
;
1237 if (lxc_convert_mac(hwaddr
, &sockaddr
)) {
1238 fprintf(stderr
, "conversion has failed\n");
1242 memcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
1243 memcpy((char *) &ifr
.ifr_hwaddr
, (char *) &sockaddr
, sizeof(sockaddr
));
1245 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1251 ret
= ioctl(fd
, SIOCSIFHWADDR
, &ifr
);
1259 static int setup_ip_addr(const char *directory
, const char *ifname
)
1261 char path
[MAXPATHLEN
], line
[MAXLINELEN
];
1265 snprintf(path
, MAXPATHLEN
, "%s/ipv4/addresses", directory
);
1266 if (!stat(path
, &s
))
1267 ret
= lxc_file_for_each_line(path
, setup_ipv4_addr_cb
,
1268 line
, MAXPATHLEN
, (void*)ifname
);
1272 static int setup_ip6_addr(const char *directory
, const char *ifname
)
1274 char path
[MAXPATHLEN
], line
[MAXLINELEN
];
1278 snprintf(path
, MAXLINELEN
, "%s/ipv6/addresses", directory
);
1279 if (!stat(path
, &s
))
1280 ret
= lxc_file_for_each_line(path
, setup_ipv6_addr_cb
,
1281 line
, MAXPATHLEN
, (void*)ifname
);
1285 static int setup_network_cb(const char *name
, const char *directory
,
1286 const char *file
, void *data
)
1288 char path
[MAXPATHLEN
];
1289 char strindex
[MAXINDEXLEN
];
1290 char ifname
[IFNAMSIZ
];
1291 char newname
[IFNAMSIZ
];
1292 char hwaddr
[MAXHWLEN
];
1293 char *current_ifname
= ifname
;
1296 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1298 if (read_info(path
, "ifindex", strindex
, sizeof(strindex
))) {
1299 ERROR("failed to read ifindex info");
1303 ifindex
= atoi(strindex
);
1305 if (!read_info(path
, "up", strindex
, sizeof(strindex
)))
1306 if (lxc_device_up("lo")) {
1307 ERROR("failed to set the loopback up");
1313 if (!if_indextoname(ifindex
, current_ifname
)) {
1314 ERROR("no interface corresponding to index '%d'",
1319 if (!read_info(path
, "name", newname
, sizeof(newname
))) {
1320 if (lxc_device_rename(ifname
, newname
)) {
1321 ERROR("failed to rename %s->%s",
1325 current_ifname
= newname
;
1328 if (!read_info(path
, "hwaddr", hwaddr
, sizeof(hwaddr
))) {
1329 if (setup_hw_addr(hwaddr
, current_ifname
)) {
1330 ERROR("failed to setup hw address for '%s'",
1336 if (setup_ip_addr(path
, current_ifname
)) {
1337 ERROR("failed to setup ip addresses for '%s'",
1342 if (setup_ip6_addr(path
, current_ifname
)) {
1343 ERROR("failed to setup ipv6 addresses for '%s'",
1348 if (!read_info(path
, "up", strindex
, sizeof(strindex
))) {
1349 if (lxc_device_up(current_ifname
)) {
1350 ERROR("failed to set '%s' up", current_ifname
);
1354 /* the network is up, make the loopback up too */
1355 if (lxc_device_up("lo")) {
1356 ERROR("failed to set the loopback up");
1364 static int setup_network(const char *name
)
1366 char directory
[MAXPATHLEN
];
1368 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1369 return lxc_dir_for_each(name
, directory
, setup_network_cb
, NULL
);
1372 int conf_has(const char *name
, const char *info
)
1375 char path
[MAXPATHLEN
];
1378 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/%s", name
, info
);
1380 if (!stat(path
, &st
) || !lstat(path
, &st
)) {
1385 if (errno
== ENOENT
) {
1390 SYSERROR("failed to stat %s info", info
);
1395 int lxc_conf_init(struct lxc_conf
*conf
)
1397 conf
->rootfs
= NULL
;
1399 conf
->utsname
= NULL
;
1402 lxc_list_init(&conf
->cgroup
);
1403 lxc_list_init(&conf
->networks
);
1407 int lxc_configure(const char *name
, struct lxc_conf
*conf
)
1412 if (conf
->utsname
&& configure_utsname(name
, conf
->utsname
)) {
1413 ERROR("failed to configure the utsname");
1414 return -LXC_ERROR_CONF_UTSNAME
;
1417 if (configure_cgroup(name
, &conf
->cgroup
)) {
1418 ERROR("failed to configure the control group");
1419 return -LXC_ERROR_CONF_CGROUP
;
1422 if (configure_network(name
, &conf
->networks
)) {
1423 ERROR("failed to configure the network");
1424 return -LXC_ERROR_CONF_NETWORK
;
1427 if (conf
->tty
&& configure_tty(name
, conf
->tty
)) {
1428 ERROR("failed to configure the tty");
1429 return -LXC_ERROR_CONF_TTY
;
1432 if (conf
->fstab
&& configure_mount(name
, conf
->fstab
)) {
1433 ERROR("failed to configure the mount points");
1434 return -LXC_ERROR_CONF_MOUNT
;
1437 if (conf
->rootfs
&& configure_rootfs(name
, conf
->rootfs
)) {
1438 ERROR("failed to configure the rootfs");
1439 return -LXC_ERROR_CONF_ROOTFS
;
1442 if (conf
->pts
&& configure_pts(name
, conf
->pts
)) {
1443 ERROR("failed to configure a new pts instance");
1444 return -LXC_ERROR_CONF_PTS
;
1450 int lxc_unconfigure(const char *name
)
1452 if (conf_has_utsname(name
) && unconfigure_utsname(name
))
1453 ERROR("failed to cleanup utsname");
1455 if (conf_has_network(name
) && unconfigure_network(name
))
1456 ERROR("failed to cleanup the network");
1458 if (conf_has_cgroup(name
) && unconfigure_cgroup(name
))
1459 ERROR("failed to cleanup cgroup");
1461 if (conf_has_tty(name
) && unconfigure_tty(name
))
1462 ERROR("failed to cleanup tty");
1464 if (conf_has_rootfs(name
) && unconfigure_rootfs(name
))
1465 ERROR("failed to cleanup rootfs");
1467 if (conf_has_fstab(name
) && unconfigure_mount(name
))
1468 ERROR("failed to cleanup mount");
1470 if (conf_has_pts(name
) && unconfigure_pts(name
))
1471 ERROR("failed to cleanup pts");
1476 static int instanciate_veth(const char *directory
, const char *file
, pid_t pid
)
1478 char *path
= NULL
, *strindex
= NULL
, *veth1
= NULL
, *veth2
= NULL
;
1479 char bridge
[IFNAMSIZ
];
1480 char strmtu
[MAXMTULEN
];
1481 int ifindex
, mtu
= 0, ret
= -1;
1483 if (!asprintf(&veth1
, "%s_%d", file
, pid
) ||
1484 !asprintf(&veth2
, "%s~%d", file
, pid
) ||
1485 !asprintf(&path
, "%s/%s", directory
, file
)) {
1486 SYSERROR("failed to allocate memory");
1490 if (read_info(path
, "link", bridge
, IFNAMSIZ
)) {
1491 ERROR("failed to read bridge info");
1495 if (lxc_veth_create(veth1
, veth2
)) {
1496 ERROR("failed to create %s-%s/%s", veth1
, veth2
, bridge
);
1500 if (!read_info(path
, "mtu", strmtu
, MAXMTULEN
)) {
1501 if (sscanf(strmtu
, "%u", &mtu
) < 1) {
1502 ERROR("invalid mtu size '%d'", mtu
);
1506 if (lxc_device_set_mtu(veth1
, mtu
)) {
1507 ERROR("failed to set mtu for '%s'", veth1
);
1511 if (lxc_device_set_mtu(veth2
, mtu
)) {
1512 ERROR("failed to set mtu for '%s'", veth2
);
1517 if (lxc_bridge_attach(bridge
, veth1
)) {
1518 ERROR("failed to attach '%s' to the bridge '%s'",
1523 ifindex
= if_nametoindex(veth2
);
1525 ERROR("failed to retrieve the index for %s", veth2
);
1529 if (!asprintf(&strindex
, "%d", ifindex
)) {
1530 SYSERROR("failed to allocate memory");
1534 if (write_info(path
, "ifindex", strindex
)) {
1535 ERROR("failed to write interface index to %s", path
);
1539 if (!read_info(path
, "up", strindex
, sizeof(strindex
))) {
1540 if (lxc_device_up(veth1
)) {
1541 ERROR("failed to set %s up", veth1
);
1555 lxc_device_delete(veth1
);
1558 static int instanciate_macvlan(const char *directory
, const char *file
, pid_t pid
)
1560 char path
[MAXPATHLEN
], *strindex
= NULL
, *peer
= NULL
;
1561 char link
[IFNAMSIZ
];
1562 int ifindex
, ret
= -1;
1564 if (!asprintf(&peer
, "%s~%d", file
, pid
)) {
1565 SYSERROR("failed to allocate memory");
1569 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1570 if (read_info(path
, "link", link
, IFNAMSIZ
)) {
1571 ERROR("failed to read bridge info");
1575 if (lxc_macvlan_create(link
, peer
)) {
1576 ERROR("failed to create macvlan interface '%s' on '%s'",
1581 ifindex
= if_nametoindex(peer
);
1583 ERROR("failed to retrieve the index for %s", peer
);
1587 if (!asprintf(&strindex
, "%d", ifindex
)) {
1588 SYSERROR("failed to allocate memory");
1592 if (write_info(path
, "ifindex", strindex
)) {
1593 ERROR("failed to write interface index to %s", path
);
1604 static int instanciate_phys(const char *directory
, const char *file
, pid_t pid
)
1606 char path
[MAXPATHLEN
], *strindex
= NULL
;
1607 char link
[IFNAMSIZ
];
1608 int ifindex
, ret
= -1;
1610 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1611 if (read_info(path
, "link", link
, IFNAMSIZ
)) {
1612 ERROR("failed to read link info");
1616 ifindex
= if_nametoindex(link
);
1618 ERROR("failed to retrieve the index for %s", link
);
1622 if (!asprintf(&strindex
, "%d", ifindex
)) {
1623 SYSERROR("failed to allocate memory");
1627 if (write_info(path
, "ifindex", strindex
)) {
1628 ERROR("failed to write interface index to %s", path
);
1638 static int instanciate_empty(const char *directory
, const char *file
, pid_t pid
)
1640 char path
[MAXPATHLEN
], *strindex
= NULL
;
1643 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1644 if (!asprintf(&strindex
, "%d", 0)) {
1645 ERROR("not enough memory");
1649 if (write_info(path
, "ifindex", strindex
)) {
1650 ERROR("failed to write interface index to %s", path
);
1660 static int instanciate_netdev_cb(const char *name
, const char *directory
,
1661 const char *file
, void *data
)
1665 if (!strncmp("veth", file
, strlen("veth")))
1666 return instanciate_veth(directory
, file
, *pid
);
1667 else if (!strncmp("macvlan", file
, strlen("macvlan")))
1668 return instanciate_macvlan(directory
, file
, *pid
);
1669 else if (!strncmp("phys", file
, strlen("phys")))
1670 return instanciate_phys(directory
, file
, *pid
);
1671 else if (!strncmp("empty", file
, strlen("empty")))
1672 return instanciate_empty(directory
, file
, *pid
);
1677 static int instanciate_netdev(const char *name
, pid_t pid
)
1679 char directory
[MAXPATHLEN
];
1681 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1682 return lxc_dir_for_each(name
, directory
, instanciate_netdev_cb
, &pid
);
1685 static int move_netdev_cb(const char *name
, const char *directory
,
1686 const char *file
, void *data
)
1688 char path
[MAXPATHLEN
], ifname
[IFNAMSIZ
], strindex
[MAXINDEXLEN
];
1692 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1693 if (read_info(path
, "ifindex", strindex
, MAXINDEXLEN
) < 0) {
1694 ERROR("failed to read index to from %s", path
);
1698 ifindex
= atoi(strindex
);
1702 if (!if_indextoname(ifindex
, ifname
)) {
1703 ERROR("interface with index %d does not exist",
1708 if (lxc_device_move(ifname
, *pid
)) {
1709 ERROR("failed to move %s to %d", ifname
, *pid
);
1716 static int move_netdev(const char *name
, pid_t pid
)
1718 char directory
[MAXPATHLEN
];
1719 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1720 return lxc_dir_for_each(name
, directory
, move_netdev_cb
, &pid
);
1723 int conf_create_network(const char *name
, pid_t pid
)
1725 if (instanciate_netdev(name
, pid
)) {
1726 ERROR("failed to instantiate the network devices");
1730 if (move_netdev(name
, pid
)) {
1731 ERROR("failed to move the netdev to the container");
1738 #ifdef NETWORK_DESTROY
1739 static int delete_netdev_cb(const char *name
, const char *directory
,
1740 const char *file
, void *data
)
1742 char strindex
[MAXINDEXLEN
];
1743 char path
[MAXPATHLEN
];
1744 char ifname
[IFNAMSIZ
];
1747 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1749 if (read_info(path
, "ifindex", strindex
, MAXINDEXLEN
)) {
1750 ERROR("failed to read ifindex info");
1754 ifindex
= atoi(strindex
);
1758 /* TODO : temporary code - needs wait on namespace */
1759 for (i
= 0; i
< 120; i
++) {
1760 if (if_indextoname(ifindex
, ifname
))
1763 printf("waiting for interface #%d to come back\n", ifindex
);
1765 printf("."); fflush(stdout
);
1769 /* do not delete a physical network device */
1770 if (strncmp("phys", file
, strlen("phys")))
1771 if (lxc_device_delete(ifname
)) {
1772 ERROR("failed to remove the netdev %s", ifname
);
1775 delete_info(path
, "ifindex");
1781 int conf_destroy_network(const char *name
)
1783 #ifdef NETWORK_DESTROY
1784 char directory
[MAXPATHLEN
];
1786 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1788 if (lxc_dir_for_each(name
, directory
, delete_netdev_cb
, NULL
)) {
1789 ERROR("failed to remove the network devices");
1796 int lxc_create_tty(const char *name
, struct lxc_tty_info
*tty_info
)
1798 char path
[MAXPATHLEN
];
1802 tty_info
->nbtty
= 0;
1804 if (!conf_has_tty(name
))
1807 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
1809 if (read_info(path
, "tty", tty
, sizeof(tty
)) < 0) {
1810 SYSERROR("failed to read tty info");
1814 tty_info
->nbtty
= atoi(tty
);
1815 tty_info
->pty_info
=
1816 malloc(sizeof(*tty_info
->pty_info
)*tty_info
->nbtty
);
1818 if (!tty_info
->pty_info
) {
1819 SYSERROR("failed to allocate pty_info");
1823 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
1825 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
1827 if (openpty(&pty_info
->master
, &pty_info
->slave
,
1828 pty_info
->name
, NULL
, NULL
)) {
1829 SYSERROR("failed to create pty #%d", i
);
1833 /* Prevent leaking the file descriptors to the container */
1834 fcntl(pty_info
->master
, F_SETFD
, FD_CLOEXEC
);
1835 fcntl(pty_info
->slave
, F_SETFD
, FD_CLOEXEC
);
1845 free(tty_info
->pty_info
);
1849 void lxc_delete_tty(struct lxc_tty_info
*tty_info
)
1853 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
1854 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
1856 close(pty_info
->master
);
1857 close(pty_info
->slave
);
1860 free(tty_info
->pty_info
);
1861 tty_info
->nbtty
= 0;
1864 enum { utsname
, network
, cgroup
, fstab
, console
, tty
, rootfs
, pts
};
1866 static int conf_is_set(long flags
, int subsystem
)
1868 return flags
& (1 << subsystem
);
1871 static void conf_set_flag(long *flags
, int subsystem
)
1873 *flags
|= 1 << subsystem
;
1876 static long make_conf_flagset(const char *name
, const char *cons
,
1877 const struct lxc_tty_info
*tty_info
)
1881 if (conf_has_utsname(name
))
1882 conf_set_flag(&flags
, utsname
);
1884 if (conf_has_network(name
))
1885 conf_set_flag(&flags
, network
);
1887 if (conf_has_cgroup(name
))
1888 conf_set_flag(&flags
, cgroup
);
1890 if (conf_has_fstab(name
))
1891 conf_set_flag(&flags
, fstab
);
1893 if (conf_has_rootfs(name
))
1894 conf_set_flag(&flags
, rootfs
);
1896 if (conf_has_pts(name
))
1897 conf_set_flag(&flags
, pts
);
1899 if (tty_info
->nbtty
)
1900 conf_set_flag(&flags
, tty
);
1903 conf_set_flag(&flags
, console
);
1908 int lxc_setup(const char *name
, const char *cons
,
1909 const struct lxc_tty_info
*tty_info
)
1912 /* store the conf flags set otherwise conf_has will not
1913 * work after chrooting */
1914 long flags
= make_conf_flagset(name
, cons
, tty_info
);
1916 if (conf_is_set(flags
, utsname
) && setup_utsname(name
)) {
1917 ERROR("failed to setup the utsname for '%s'", name
);
1918 return -LXC_ERROR_SETUP_UTSNAME
;
1921 if (conf_is_set(flags
, network
) && setup_network(name
)) {
1922 ERROR("failed to setup the network for '%s'", name
);
1923 return -LXC_ERROR_SETUP_NETWORK
;
1926 if (conf_is_set(flags
, cgroup
) && setup_cgroup(name
)) {
1927 ERROR("failed to setup the cgroups for '%s'", name
);
1928 return -LXC_ERROR_SETUP_CGROUP
;
1931 if (conf_is_set(flags
, fstab
) && setup_mount(name
)) {
1932 ERROR("failed to setup the mounts for '%s'", name
);
1933 return -LXC_ERROR_SETUP_MOUNT
;
1936 if (conf_is_set(flags
, console
) && setup_console(name
, cons
)) {
1937 ERROR("failed to setup the console for '%s'", name
);
1938 return -LXC_ERROR_SETUP_CONSOLE
;
1941 if (conf_is_set(flags
, tty
) && setup_tty(name
, tty_info
)) {
1942 ERROR("failed to setup the ttys for '%s'", name
);
1943 return -LXC_ERROR_SETUP_TTY
;
1946 if (conf_is_set(flags
, rootfs
) && setup_rootfs(name
)) {
1947 ERROR("failed to set rootfs for '%s'", name
);
1948 return -LXC_ERROR_SETUP_ROOTFS
;
1951 if (conf_is_set(flags
, pts
) && setup_pts(name
)) {
1952 ERROR("failed to setup the new pts instance");
1953 return -LXC_ERROR_SETUP_PTS
;