]>
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_network(const char *name
, struct lxc_list
*network
)
335 struct lxc_list
*iterator
;
336 struct lxc_network
*n
;
337 char networkpath
[MAXPATHLEN
];
338 char path
[MAXPATHLEN
];
341 if (lxc_list_empty(network
))
344 snprintf(networkpath
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
345 if (mkdir(networkpath
, 0755)) {
346 SYSERROR("failed to create %s directory", networkpath
);
350 lxc_list_for_each(iterator
, network
) {
354 if (n
->type
< 0 || n
->type
> MAXCONFTYPE
) {
355 ERROR("invalid network configuration type '%d'",
360 snprintf(path
, MAXPATHLEN
, "%s/%s%d", networkpath
,
361 netdev_conf
[n
->type
].type
,
362 netdev_conf
[n
->type
].count
++);
364 if (configure_netdev(path
, lxc_list_first_elem(&n
->netdev
))) {
365 ERROR("failed to configure network type %s",
366 netdev_conf
[n
->type
].type
);
376 static int configure_find_fstype_cb(void* buffer
, void *data
)
387 /* we don't try 'nodev' entries */
388 if (strstr(buffer
, "nodev"))
392 fstype
+= lxc_char_left_gc(fstype
, strlen(fstype
));
393 fstype
[lxc_char_right_gc(fstype
, strlen(fstype
))] = '\0';
395 if (mount(cbarg
->rootfs
, cbarg
->testdir
, fstype
, cbarg
->mntopt
, NULL
))
399 umount(cbarg
->testdir
);
400 strcpy(cbarg
->fstype
, fstype
);
405 /* find the filesystem type with brute force */
406 static int configure_find_fstype(const char *rootfs
, char *fstype
, int mntopt
)
409 char buffer
[MAXPATHLEN
];
422 /* first we check with /etc/filesystems, in case the modules
423 * are auto-loaded and fall back to the supported kernel fs
430 cbarg
.testdir
= tempnam("/tmp", "lxc-");
431 if (!cbarg
.testdir
) {
432 SYSERROR("failed to build a temp name");
436 if (mkdir(cbarg
.testdir
, 0755)) {
437 SYSERROR("failed to create temporary directory");
441 for (i
= 0; i
< sizeof(fsfile
)/sizeof(fsfile
[0]); i
++) {
443 found
= lxc_file_for_each_line(fsfile
[i
],
444 configure_find_fstype_cb
,
445 buffer
, sizeof(buffer
), &cbarg
);
448 SYSERROR("failed to read '%s'", fsfile
[i
]);
457 ERROR("failed to determine fs type for '%s'", rootfs
);
462 rmdir(cbarg
.testdir
);
466 static int configure_rootfs_dir_cb(const char *rootfs
, const char *absrootfs
,
469 return fprintf(f
, "%s %s none rbind 0 0\n", absrootfs
, rootfs
);
472 static int configure_rootfs_blk_cb(const char *rootfs
, const char *absrootfs
,
475 char fstype
[MAXPATHLEN
];
477 if (configure_find_fstype(absrootfs
, fstype
, 0)) {
478 ERROR("failed to configure mount for block device '%s'",
483 return fprintf(f
, "%s %s %s defaults 0 0\n", absrootfs
, rootfs
, fstype
);
486 static int configure_rootfs(const char *name
, const char *rootfs
)
488 char path
[MAXPATHLEN
];
489 char absrootfs
[MAXPATHLEN
];
490 char fstab
[MAXPATHLEN
];
495 typedef int (*rootfs_cb
)(const char *, const char *, FILE *);
501 { __S_IFDIR
, configure_rootfs_dir_cb
},
502 { __S_IFBLK
, configure_rootfs_blk_cb
},
505 if (!realpath(rootfs
, absrootfs
)) {
506 SYSERROR("failed to get real path for '%s'", rootfs
);
510 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
512 if (mkdir(path
, 0755)) {
513 SYSERROR("failed to create the '%s' directory", path
);
517 if (access(absrootfs
, F_OK
)) {
518 SYSERROR("'%s' is not accessible", absrootfs
);
522 if (stat(absrootfs
, &s
)) {
523 SYSERROR("failed to stat '%s'", absrootfs
);
527 for (i
= 0; i
< sizeof(rtfs_type
)/sizeof(rtfs_type
[0]); i
++) {
529 if (!__S_ISTYPE(s
.st_mode
, rtfs_type
[i
].type
))
532 snprintf(fstab
, MAXPATHLEN
, LXCPATH
"/%s/fstab", name
);
534 f
= fopen(fstab
, "a+");
536 SYSERROR("failed to open fstab file");
540 ret
= rtfs_type
[i
].cb(path
, absrootfs
, f
);
545 ERROR("failed to add rootfs mount in fstab");
549 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs/rootfs", name
);
551 return symlink(absrootfs
, path
);
554 ERROR("unsupported rootfs type for '%s'", absrootfs
);
558 static int unconfigure_ip_addresses(const char *directory
)
560 char path
[MAXPATHLEN
];
562 snprintf(path
, MAXPATHLEN
, "%s/ipv4", directory
);
563 delete_info(path
, "addresses");
566 snprintf(path
, MAXPATHLEN
, "%s/ipv6", directory
);
567 delete_info(path
, "addresses");
573 static int unconfigure_network_cb(const char *name
, const char *directory
,
574 const char *file
, void *data
)
576 char path
[MAXPATHLEN
];
578 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
579 delete_info(path
, "ifindex");
580 delete_info(path
, "name");
581 delete_info(path
, "addr");
582 delete_info(path
, "link");
583 delete_info(path
, "hwaddr");
584 delete_info(path
, "mtu");
585 delete_info(path
, "up");
586 unconfigure_ip_addresses(path
);
592 static int unconfigure_network(const char *name
)
594 char directory
[MAXPATHLEN
];
596 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
597 lxc_dir_for_each(name
, directory
, unconfigure_network_cb
, NULL
);
603 static int unconfigure_cgroup_cb(const char *name
, const char *directory
,
604 const char *file
, void *data
)
606 return delete_info(directory
, file
);
609 static int unconfigure_cgroup(const char *name
)
611 char filename
[MAXPATHLEN
];
614 snprintf(filename
, MAXPATHLEN
, LXCPATH
"/%s/cgroup", name
);
616 if (stat(filename
, &s
)) {
617 SYSERROR("failed to stat '%s'", filename
);
621 if (S_ISDIR(s
.st_mode
)) {
622 /* old cgroup configuration */
623 lxc_dir_for_each(name
, filename
, unconfigure_cgroup_cb
, NULL
);
632 static int unconfigure_rootfs(const char *name
)
634 char path
[MAXPATHLEN
];
636 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/rootfs", name
);
638 #warning deprecated code to be removed in the next version
640 /* ugly but for backward compatibily, */
641 delete_info(path
, "rootfs");
648 static int unconfigure_pts(const char *name
)
650 char path
[MAXPATHLEN
];
652 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
653 delete_info(path
, "pts");
658 static int unconfigure_tty(const char *name
)
660 char path
[MAXPATHLEN
];
662 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
663 delete_info(path
, "tty");
668 static int unconfigure_mount(const char *name
)
670 char path
[MAXPATHLEN
];
672 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
673 delete_info(path
, "fstab");
678 static int unconfigure_utsname(const char *name
)
680 char path
[MAXPATHLEN
];
682 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
683 delete_info(path
, "utsname");
688 static int setup_utsname(struct utsname
*utsname
)
693 if (sethostname(utsname
->nodename
, strlen(utsname
->nodename
))) {
694 SYSERROR("failed to set the hostname to '%s'", utsname
->nodename
);
698 INFO("'%s' hostname has been setup", utsname
->nodename
);
703 static int setup_tty(const char *rootfs
, const struct lxc_tty_info
*tty_info
)
705 char path
[MAXPATHLEN
];
708 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
710 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
712 snprintf(path
, sizeof(path
), "%s/dev/tty%d",
713 rootfs
? rootfs
: "", i
+ 1);
715 /* At this point I can not use the "access" function
716 * to check the file is present or not because it fails
717 * with EACCES errno and I don't know why :( */
719 if (mount(pty_info
->name
, path
, "none", MS_BIND
, 0)) {
720 WARN("failed to mount '%s'->'%s'",
721 pty_info
->name
, path
);
726 INFO("%d tty(s) has been setup", tty_info
->nbtty
);
731 static int setup_rootfs(const char *rootfs
)
739 tmpname
= tempnam("/tmp", "lxc-rootfs");
741 SYSERROR("failed to generate temporary name");
745 if (mkdir(tmpname
, 0700)) {
746 SYSERROR("failed to create temporary directory '%s'", tmpname
);
750 if (mount(rootfs
, tmpname
, "none", MS_BIND
|MS_REC
, NULL
)) {
751 SYSERROR("failed to mount '%s'->'%s'", rootfs
, tmpname
);
755 if (chroot(tmpname
)) {
756 SYSERROR("failed to set chroot %s", tmpname
);
760 if (chdir(getenv("HOME")) && chdir("/")) {
761 SYSERROR("failed to change to home directory");
765 INFO("chrooted to '%s'", rootfs
);
773 static int setup_pts(int pts
)
778 if (!access("/dev/pts/ptmx", F_OK
) && umount("/dev/pts")) {
779 SYSERROR("failed to umount 'dev/pts'");
783 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL
, "newinstance")) {
784 SYSERROR("failed to mount a new instance of '/dev/pts'");
788 if (chmod("/dev/pts/ptmx", 0666)) {
789 SYSERROR("failed to set permission for '/dev/pts/ptmx'");
793 if (access("/dev/ptmx", F_OK
)) {
794 if (!symlink("/dev/pts/ptmx", "/dev/ptmx"))
796 SYSERROR("failed to symlink '/dev/pts/ptmx'->'/dev/ptmx'");
800 /* fallback here, /dev/pts/ptmx exists just mount bind */
801 if (mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND
, 0)) {
802 SYSERROR("mount failed '/dev/pts/ptmx'->'/dev/ptmx'");
806 INFO("created new pts instance");
812 static int setup_console(const char *rootfs
, const char *tty
)
814 char console
[MAXPATHLEN
];
816 snprintf(console
, sizeof(console
), "%s/dev/console",
817 rootfs
? rootfs
: "");
819 /* we have the rootfs with /dev/console but no tty
820 * to be used as console, let's remap /dev/console
821 * to /dev/null to avoid to log to the system console
823 if (rootfs
&& !tty
[0]) {
825 if (!access(console
, F_OK
)) {
827 if (mount("/dev/null", console
, "none", MS_BIND
, 0)) {
828 SYSERROR("failed to mount '/dev/null'->'%s'",
838 if (access(console
, R_OK
|W_OK
))
841 if (mount(tty
, console
, "none", MS_BIND
, 0)) {
842 ERROR("failed to mount the console");
846 INFO("console '%s' mounted to '%s'", tty
, console
);
851 static int setup_cgroup(const char *name
, struct lxc_list
*cgroups
)
853 struct lxc_list
*iterator
;
854 struct lxc_cgroup
*cg
;
856 if (lxc_list_empty(cgroups
))
859 lxc_list_for_each(iterator
, cgroups
) {
863 if (lxc_cgroup_set(name
, cg
->subsystem
, cg
->value
))
866 DEBUG("cgroup '%s' set to '%s'", cg
->subsystem
, cg
->value
);
869 INFO("cgroup has been setup");
874 static void parse_mntopt(char *opt
, unsigned long *flags
, char **data
)
876 struct mount_opt
*mo
;
878 /* If opt is found in mount_opt, set or clear flags.
879 * Otherwise append it to data. */
881 for (mo
= &mount_opt
[0]; mo
->name
!= NULL
; mo
++) {
882 if (!strncmp(opt
, mo
->name
, strlen(mo
->name
))) {
896 static int parse_mntopts(struct mntent
*mntent
, unsigned long *mntflags
,
900 char *p
, *saveptr
= NULL
;
902 if (!mntent
->mnt_opts
)
905 s
= strdup(mntent
->mnt_opts
);
907 SYSERROR("failed to allocate memory");
911 data
= malloc(strlen(s
) + 1);
913 SYSERROR("failed to allocate memory");
919 for (p
= strtok_r(s
, ",", &saveptr
); p
!= NULL
;
920 p
= strtok_r(NULL
, ",", &saveptr
))
921 parse_mntopt(p
, mntflags
, &data
);
932 static int setup_mount(const char *fstab
)
934 struct mntent
*mntent
;
937 unsigned long mntflags
;
943 file
= setmntent(fstab
, "r");
945 SYSERROR("failed to use '%s'", fstab
);
949 while ((mntent
= getmntent(file
))) {
953 if (parse_mntopts(mntent
, &mntflags
, &mntdata
) < 0) {
954 ERROR("failed to parse mount option '%s'",
959 if (mount(mntent
->mnt_fsname
, mntent
->mnt_dir
,
960 mntent
->mnt_type
, mntflags
, mntdata
)) {
961 SYSERROR("failed to mount '%s' on '%s'",
962 mntent
->mnt_fsname
, mntent
->mnt_dir
);
966 DEBUG("mounted %s on %s, type %s", mntent
->mnt_fsname
,
967 mntent
->mnt_dir
, mntent
->mnt_type
);
974 INFO("mount points have been setup");
980 static int setup_ipv4_addr_cb(void *buffer
, void *data
)
983 char *cursor
, *slash
, *addr
, *bcast
= NULL
, *prefix
= NULL
;
987 cursor
= strstr(addr
, " ");
991 cursor
= strstr(bcast
, "\n");
996 slash
= strstr(addr
, "/");
1005 if (lxc_ip_addr_add(ifname
, addr
, p
, bcast
)) {
1006 ERROR("failed to set %s to addr %s/%d %s", ifname
,
1007 addr
, p
, bcast
?bcast
:"");
1011 DEBUG("address '%s/%s' on '%s' has been setup", addr
, prefix
, ifname
);
1016 static int setup_ipv6_addr_cb(void *buffer
, void *data
)
1018 char *ifname
= data
;
1019 char *cursor
, *slash
, *addr
, *bcast
= NULL
, *prefix
= NULL
;
1023 cursor
= strstr(addr
, " ");
1027 cursor
= strstr(bcast
, "\n");
1032 slash
= strstr(addr
, "/");
1041 if (lxc_ip6_addr_add(ifname
, addr
, p
, bcast
)) {
1042 ERROR("failed to set %s to addr %s/%d %s", ifname
,
1043 addr
, p
, bcast
?bcast
:"");
1047 INFO("address '%s/%s' on '%s' has been setup", addr
, prefix
, ifname
);
1052 static int setup_hw_addr(char *hwaddr
, const char *ifname
)
1054 struct sockaddr sockaddr
;
1058 if (lxc_convert_mac(hwaddr
, &sockaddr
)) {
1059 ERROR("conversion has failed");
1063 memcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
1064 memcpy((char *) &ifr
.ifr_hwaddr
, (char *) &sockaddr
, sizeof(sockaddr
));
1066 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1068 ERROR("socket failure : %s", strerror(errno
));
1072 ret
= ioctl(fd
, SIOCSIFHWADDR
, &ifr
);
1075 ERROR("ioctl failure : %s", strerror(errno
));
1077 DEBUG("mac address '%s' on '%s' has been setup", hwaddr
, ifname
);
1082 static int setup_ip_addr(const char *directory
, const char *ifname
)
1084 char path
[MAXPATHLEN
], line
[MAXLINELEN
];
1088 snprintf(path
, MAXPATHLEN
, "%s/ipv4/addresses", directory
);
1089 if (!stat(path
, &s
))
1090 ret
= lxc_file_for_each_line(path
, setup_ipv4_addr_cb
,
1091 line
, MAXPATHLEN
, (void*)ifname
);
1095 static int setup_ip6_addr(const char *directory
, const char *ifname
)
1097 char path
[MAXPATHLEN
], line
[MAXLINELEN
];
1101 snprintf(path
, MAXLINELEN
, "%s/ipv6/addresses", directory
);
1102 if (!stat(path
, &s
))
1103 ret
= lxc_file_for_each_line(path
, setup_ipv6_addr_cb
,
1104 line
, MAXPATHLEN
, (void*)ifname
);
1108 static int setup_network_cb(const char *name
, const char *directory
,
1109 const char *file
, void *data
)
1111 char path
[MAXPATHLEN
];
1112 char strindex
[MAXINDEXLEN
];
1113 char ifname
[IFNAMSIZ
];
1114 char newname
[IFNAMSIZ
];
1115 char hwaddr
[MAXHWLEN
];
1116 char *current_ifname
= ifname
;
1119 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1121 if (read_info(path
, "ifindex", strindex
, sizeof(strindex
))) {
1122 ERROR("failed to read ifindex info");
1126 ifindex
= atoi(strindex
);
1128 if (!read_info(path
, "up", strindex
, sizeof(strindex
)))
1129 if (lxc_device_up("lo")) {
1130 ERROR("failed to set the loopback up");
1136 if (!if_indextoname(ifindex
, current_ifname
)) {
1137 ERROR("no interface corresponding to index '%d'",
1142 /* default: let the system to choose one interface name */
1143 if (read_info(path
, "name", newname
, sizeof(newname
)))
1144 strcpy(newname
, "eth%d");
1146 if (lxc_device_rename(ifname
, newname
)) {
1147 ERROR("failed to rename %s->%s", ifname
, current_ifname
);
1151 /* Re-read the name of the interface because its name has changed
1152 * and would be automatically allocated by the system
1154 if (!if_indextoname(ifindex
, current_ifname
)) {
1155 ERROR("no interface corresponding to index '%d'",
1160 if (!read_info(path
, "hwaddr", hwaddr
, sizeof(hwaddr
))) {
1161 if (setup_hw_addr(hwaddr
, current_ifname
)) {
1162 ERROR("failed to setup hw address for '%s'",
1168 if (setup_ip_addr(path
, current_ifname
)) {
1169 ERROR("failed to setup ip addresses for '%s'",
1174 if (setup_ip6_addr(path
, current_ifname
)) {
1175 ERROR("failed to setup ipv6 addresses for '%s'",
1180 if (!read_info(path
, "up", strindex
, sizeof(strindex
))) {
1181 if (lxc_device_up(current_ifname
)) {
1182 ERROR("failed to set '%s' up", current_ifname
);
1186 /* the network is up, make the loopback up too */
1187 if (lxc_device_up("lo")) {
1188 ERROR("failed to set the loopback up");
1193 DEBUG("'%s' has been setup", current_ifname
);
1198 static int setup_network(const char *name
)
1200 char directory
[MAXPATHLEN
];
1203 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1205 ret
= lxc_dir_for_each(name
, directory
, setup_network_cb
, NULL
);
1209 INFO("network has been setup");
1214 int conf_has(const char *name
, const char *info
)
1217 char path
[MAXPATHLEN
];
1220 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s/%s", name
, info
);
1222 if (!stat(path
, &st
) || !lstat(path
, &st
)) {
1227 if (errno
== ENOENT
) {
1232 SYSERROR("failed to stat %s info", info
);
1237 int lxc_conf_init(struct lxc_conf
*conf
)
1239 conf
->rcfile
= NULL
;
1240 conf
->rootfs
= NULL
;
1242 conf
->utsname
= NULL
;
1245 lxc_list_init(&conf
->cgroup
);
1246 lxc_list_init(&conf
->networks
);
1250 int lxc_configure(const char *name
, struct lxc_conf
*conf
)
1255 if (configure_network(name
, &conf
->networks
)) {
1256 ERROR("failed to configure the network");
1263 int lxc_unconfigure(const char *name
)
1265 if (conf_has_utsname(name
) && unconfigure_utsname(name
))
1266 ERROR("failed to cleanup utsname");
1268 if (conf_has_network(name
) && unconfigure_network(name
))
1269 ERROR("failed to cleanup the network");
1271 if (conf_has_cgroup(name
) && unconfigure_cgroup(name
))
1272 ERROR("failed to cleanup cgroup");
1274 if (conf_has_tty(name
) && unconfigure_tty(name
))
1275 ERROR("failed to cleanup tty");
1277 if (conf_has_rootfs(name
) && unconfigure_rootfs(name
))
1278 ERROR("failed to cleanup rootfs");
1280 if (conf_has_fstab(name
) && unconfigure_mount(name
))
1281 ERROR("failed to cleanup mount");
1283 if (conf_has_pts(name
) && unconfigure_pts(name
))
1284 ERROR("failed to cleanup pts");
1289 static int instanciate_veth(const char *directory
, const char *file
, pid_t pid
)
1291 char *path
= NULL
, *strindex
= NULL
, *veth1
= NULL
, *veth2
= NULL
;
1292 char bridge
[IFNAMSIZ
];
1293 char strmtu
[MAXMTULEN
];
1294 int ifindex
, mtu
= 0, ret
= -1;
1296 if (!asprintf(&veth1
, "%s_%d", file
, pid
) ||
1297 !asprintf(&veth2
, "%s~%d", file
, pid
) ||
1298 !asprintf(&path
, "%s/%s", directory
, file
)) {
1299 SYSERROR("failed to allocate memory");
1303 if (read_info(path
, "link", bridge
, IFNAMSIZ
)) {
1304 ERROR("failed to read bridge info");
1308 if (lxc_veth_create(veth1
, veth2
)) {
1309 ERROR("failed to create %s-%s/%s", veth1
, veth2
, bridge
);
1313 if (!read_info(path
, "mtu", strmtu
, MAXMTULEN
)) {
1314 if (sscanf(strmtu
, "%u", &mtu
) < 1) {
1315 ERROR("invalid mtu size '%d'", mtu
);
1319 if (lxc_device_set_mtu(veth1
, mtu
)) {
1320 ERROR("failed to set mtu for '%s'", veth1
);
1324 if (lxc_device_set_mtu(veth2
, mtu
)) {
1325 ERROR("failed to set mtu for '%s'", veth2
);
1330 if (lxc_bridge_attach(bridge
, veth1
)) {
1331 ERROR("failed to attach '%s' to the bridge '%s'",
1336 ifindex
= if_nametoindex(veth2
);
1338 ERROR("failed to retrieve the index for %s", veth2
);
1342 if (!asprintf(&strindex
, "%d", ifindex
)) {
1343 SYSERROR("failed to allocate memory");
1347 if (write_info(path
, "ifindex", strindex
)) {
1348 ERROR("failed to write interface index to %s", path
);
1352 if (!read_info(path
, "up", strindex
, sizeof(strindex
))) {
1353 if (lxc_device_up(veth1
)) {
1354 ERROR("failed to set %s up", veth1
);
1368 lxc_device_delete(veth1
);
1371 static int instanciate_macvlan(const char *directory
, const char *file
, pid_t pid
)
1373 char path
[MAXPATHLEN
], *strindex
= NULL
, *peer
= NULL
;
1374 char link
[IFNAMSIZ
];
1375 int ifindex
, ret
= -1;
1377 if (!asprintf(&peer
, "%s~%d", file
, pid
)) {
1378 SYSERROR("failed to allocate memory");
1382 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1383 if (read_info(path
, "link", link
, IFNAMSIZ
)) {
1384 ERROR("failed to read bridge info");
1388 if (lxc_macvlan_create(link
, peer
)) {
1389 ERROR("failed to create macvlan interface '%s' on '%s'",
1394 ifindex
= if_nametoindex(peer
);
1396 ERROR("failed to retrieve the index for %s", peer
);
1400 if (!asprintf(&strindex
, "%d", ifindex
)) {
1401 SYSERROR("failed to allocate memory");
1405 if (write_info(path
, "ifindex", strindex
)) {
1406 ERROR("failed to write interface index to %s", path
);
1417 static int instanciate_phys(const char *directory
, const char *file
, pid_t pid
)
1419 char path
[MAXPATHLEN
], *strindex
= NULL
;
1420 char link
[IFNAMSIZ
];
1421 int ifindex
, ret
= -1;
1423 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1424 if (read_info(path
, "link", link
, IFNAMSIZ
)) {
1425 ERROR("failed to read link info");
1429 ifindex
= if_nametoindex(link
);
1431 ERROR("failed to retrieve the index for %s", link
);
1435 if (!asprintf(&strindex
, "%d", ifindex
)) {
1436 SYSERROR("failed to allocate memory");
1440 if (write_info(path
, "ifindex", strindex
)) {
1441 ERROR("failed to write interface index to %s", path
);
1451 static int instanciate_empty(const char *directory
, const char *file
, pid_t pid
)
1453 char path
[MAXPATHLEN
], *strindex
= NULL
;
1456 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1457 if (!asprintf(&strindex
, "%d", 0)) {
1458 ERROR("not enough memory");
1462 if (write_info(path
, "ifindex", strindex
)) {
1463 ERROR("failed to write interface index to %s", path
);
1473 static int instanciate_netdev_cb(const char *name
, const char *directory
,
1474 const char *file
, void *data
)
1478 if (!strncmp("veth", file
, strlen("veth")))
1479 return instanciate_veth(directory
, file
, *pid
);
1480 else if (!strncmp("macvlan", file
, strlen("macvlan")))
1481 return instanciate_macvlan(directory
, file
, *pid
);
1482 else if (!strncmp("phys", file
, strlen("phys")))
1483 return instanciate_phys(directory
, file
, *pid
);
1484 else if (!strncmp("empty", file
, strlen("empty")))
1485 return instanciate_empty(directory
, file
, *pid
);
1490 static int instanciate_netdev(const char *name
, pid_t pid
)
1492 char directory
[MAXPATHLEN
];
1494 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1495 return lxc_dir_for_each(name
, directory
, instanciate_netdev_cb
, &pid
);
1498 static int move_netdev_cb(const char *name
, const char *directory
,
1499 const char *file
, void *data
)
1501 char path
[MAXPATHLEN
], ifname
[IFNAMSIZ
], strindex
[MAXINDEXLEN
];
1505 snprintf(path
, MAXPATHLEN
, "%s/%s", directory
, file
);
1506 if (read_info(path
, "ifindex", strindex
, MAXINDEXLEN
) < 0) {
1507 ERROR("failed to read index to from %s", path
);
1511 ifindex
= atoi(strindex
);
1515 if (!if_indextoname(ifindex
, ifname
)) {
1516 ERROR("interface with index %d does not exist",
1521 if (lxc_device_move(ifname
, *pid
)) {
1522 ERROR("failed to move %s to %d", ifname
, *pid
);
1529 static int move_netdev(const char *name
, pid_t pid
)
1531 char directory
[MAXPATHLEN
];
1532 snprintf(directory
, MAXPATHLEN
, LXCPATH
"/%s/network", name
);
1533 return lxc_dir_for_each(name
, directory
, move_netdev_cb
, &pid
);
1536 int conf_create_network(const char *name
, pid_t pid
)
1538 if (instanciate_netdev(name
, pid
)) {
1539 ERROR("failed to instantiate the network devices");
1543 if (move_netdev(name
, pid
)) {
1544 ERROR("failed to move the netdev to the container");
1551 int lxc_create_tty(const char *name
, struct lxc_tty_info
*tty_info
)
1553 char path
[MAXPATHLEN
];
1557 tty_info
->nbtty
= 0;
1559 if (!conf_has_tty(name
))
1562 snprintf(path
, MAXPATHLEN
, LXCPATH
"/%s", name
);
1564 if (read_info(path
, "tty", tty
, sizeof(tty
)) < 0) {
1565 SYSERROR("failed to read tty info");
1569 tty_info
->nbtty
= atoi(tty
);
1570 tty_info
->pty_info
=
1571 malloc(sizeof(*tty_info
->pty_info
)*tty_info
->nbtty
);
1573 if (!tty_info
->pty_info
) {
1574 SYSERROR("failed to allocate pty_info");
1578 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
1580 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
1582 if (openpty(&pty_info
->master
, &pty_info
->slave
,
1583 pty_info
->name
, NULL
, NULL
)) {
1584 SYSERROR("failed to create pty #%d", i
);
1588 /* Prevent leaking the file descriptors to the container */
1589 fcntl(pty_info
->master
, F_SETFD
, FD_CLOEXEC
);
1590 fcntl(pty_info
->slave
, F_SETFD
, FD_CLOEXEC
);
1597 INFO("tty's configured");
1603 free(tty_info
->pty_info
);
1607 void lxc_delete_tty(struct lxc_tty_info
*tty_info
)
1611 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
1612 struct lxc_pty_info
*pty_info
= &tty_info
->pty_info
[i
];
1614 close(pty_info
->master
);
1615 close(pty_info
->slave
);
1618 free(tty_info
->pty_info
);
1619 tty_info
->nbtty
= 0;
1622 int lxc_setup(const char *name
, struct lxc_handler
*handler
)
1624 if (setup_utsname(handler
->lxc_conf
.utsname
)) {
1625 ERROR("failed to setup the utsname for '%s'", name
);
1629 if (!lxc_list_empty(&handler
->lxc_conf
.networks
) && setup_network(name
)) {
1630 ERROR("failed to setup the network for '%s'", name
);
1634 if (setup_cgroup(name
, &handler
->lxc_conf
.cgroup
)) {
1635 ERROR("failed to setup the cgroups for '%s'", name
);
1639 if (setup_mount(handler
->lxc_conf
.fstab
)) {
1640 ERROR("failed to setup the mounts for '%s'", name
);
1644 if (setup_console(handler
->lxc_conf
.rootfs
, handler
->tty
)) {
1645 ERROR("failed to setup the console for '%s'", name
);
1649 if (setup_tty(handler
->lxc_conf
.rootfs
, &handler
->tty_info
)) {
1650 ERROR("failed to setup the ttys for '%s'", name
);
1654 if (setup_rootfs(handler
->lxc_conf
.rootfs
)) {
1655 ERROR("failed to set rootfs for '%s'", name
);
1659 if (setup_pts(handler
->lxc_conf
.pts
)) {
1660 ERROR("failed to setup the new pts instance");
1664 NOTICE("'%s' is setup.", name
);