Commit 620eff3c by dlezcano

*** empty log message ***

parent 3847ae4b
lib_LIBRARIES = liblxc.a
pkginclude_HEADERS = lxc.h
pkginclude_HEADERS = \
lxc.h \
lxc_cgroup.h \
lxc_conf.h \
lxc_list.h \
lxc_lock.h \
lxc_log.h \
lxc_namespace.h \
lxc_state.h \
lxc_utils.h
liblxc_a_SOURCES = \
create.c \
destroy.c \
......@@ -8,19 +18,19 @@ liblxc_a_SOURCES = \
execute.c \
monitor.c \
kill.c \
state.c \
freezer.c \
cgroup.c cgroup.h \
lxc_state.c lxc_state.h \
lxc_cgroup.c lxc_cgroup.h \
lxc.h \
utils.h \
lock.c lock.h \
namespace.h \
network.c network.h \
conf.c conf.h \
list.h \
state.c state.h \
log.c log.h \
lxc_utils.h \
lxc_lock.c lxc_lock.h \
lxc_namespace.h \
lxc_conf.c lxc_conf.h \
lxc_list.h \
lxc_state.c lxc_state.h \
lxc_log.c lxc_log.h \
\
network.c network.h \
nl.c nl.h \
rtnl.c rtnl.h \
genl.c genl.h
......@@ -35,11 +35,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <list.h>
#include <conf.h>
#include <lock.h>
#include <log.h>
static int dir_filter(const struct dirent *dirent)
{
......
......@@ -37,11 +37,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <list.h>
#include <conf.h>
#include <log.h>
#include <lock.h>
static int dir_filter(const struct dirent *dirent)
{
......
......@@ -39,15 +39,7 @@
#include <netinet/in.h>
#include <net/if.h>
#include <list.h>
#include <conf.h>
#include <log.h>
#include <lxc.h>
#include <lock.h>
#include <state.h>
#include <cgroup.h>
#include <namespace.h>
#include <utils.h>
LXC_TTY_HANDLER(SIGINT);
LXC_TTY_HANDLER(SIGQUIT);
......
......@@ -36,8 +36,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <log.h>
static int freeze_unfreeze(const char *name, int freeze)
{
......
......@@ -36,10 +36,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <list.h>
#include <conf.h>
#include <log.h>
int lxc_kill(const char *name, int signum)
{
......
......@@ -29,17 +29,21 @@
liblxc/lxc.h will contain exports of liblxc
**/
#include <lxc_state.h>
#include <lxc_list.h>
#include <lxc_conf.h>
#include <lxc_log.h>
#include <lxc_lock.h>
#include <lxc_cgroup.h>
#include <lxc_namespace.h>
#include <lxc_utils.h>
#define LXCPATH "/var/lxc"
#define MAXPIDLEN 20
struct lxc_mem_stat;
struct lxc_conf;
typedef enum {
STOPPED, STARTING, RUNNING, STOPPING,
ABORTING, FREEZING, FROZEN, MAX_STATE,
} lxc_state_t;
typedef int (*lxc_callback_t)(const char *name, int argc,
char *argv[], void *data);
......
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
#include <stdlib.h>
#include <errno.h>
#include <mntent.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/inotify.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
#define MAXPRIOLEN 24
#define MTAB "/etc/mtab"
static int get_cgroup_mount(const char *mtab, char *mnt)
{
struct mntent *mntent;
FILE *file = NULL;
int err = -1;
file = setmntent(mtab, "r");
if (!file) {
lxc_log_syserror("failed to open %s", mtab);
goto out;
}
while ((mntent = getmntent(file))) {
if (strcmp(mntent->mnt_fsname, "cgroup"))
continue;
strcpy(mnt, mntent->mnt_dir);
err = 0;
break;
};
fclose(file);
out:
return err;
}
int lxc_link_nsgroup(const char *name, pid_t pid)
{
char *lxc, *nsgroup, cgroup[MAXPATHLEN];
int ret;
if (get_cgroup_mount(MTAB, cgroup)) {
lxc_log_info("cgroup is not mounted");
return -1;
}
asprintf(&lxc, LXCPATH "/%s/nsgroup", name);
asprintf(&nsgroup, "%s/%d", cgroup, pid);
unlink(lxc);
ret = symlink(nsgroup, lxc);
if (ret)
lxc_log_syserror("failed to create symlink %s->%s",
nsgroup, lxc);
free(lxc);
free(nsgroup);
return ret;
}
int lxc_unlink_nsgroup(const char *name)
{
char *nsgroup;
int ret;
asprintf(&nsgroup, LXCPATH "/%s/nsgroup", name);
ret = unlink(nsgroup);
free(nsgroup);
return ret;
}
int lxc_set_priority(const char *name, int priority)
{
int fd;
char *path = NULL, *prio = NULL;
asprintf(&path, LXCPATH "/%s/nsgroup/cpu.shares", name);
fd = open(path, O_WRONLY);
if (fd < 0) {
lxc_log_syserror("failed to open '%s'", path);
goto out;
}
asprintf(&prio, "%d", priority);
if (write(fd, prio, strlen(prio) + 1) < 0) {
lxc_log_syserror("failed to write to '%s'", path);
close(fd);
goto out;
}
close(fd);
out:
free(path);
free(prio);
return 0;
}
int lxc_get_priority(const char *name, int *priority)
{
int fd, ret = -1;
char *path, prio[MAXPRIOLEN];
asprintf(&path, LXCPATH "/%s/nsgroup/cpu.shares", name);
fd = open(path, O_RDONLY);
if (fd < 0) {
lxc_log_syserror("failed to open '%s'", path);
goto out;
}
if (read(fd, prio, MAXPRIOLEN) < 0) {
lxc_log_syserror("failed to read from '%s'", path);
close(fd);
goto out;
}
close(fd);
*priority = atoi(prio);
ret = 0;
out:
free(path);
return 0;
}
int lxc_set_memory(const char *name, size_t memmax)
{
return 0;
}
int lxc_get_memory(const char *name, size_t *memmax)
{
return 0;
}
int lxc_get_memstat(const char *name, struct lxc_mem_stat *memstat)
{
return 0;
}
int lxc_set_cpuset(const char *name, long *cpumask, int len, int shared)
{
return 0;
}
int lxc_get_cpuset(const char *name, long *cpumask, int len, int *shared)
{
return 0;
}
int lxc_get_cpu_usage(const char *name, long long *usage)
{
return 0;
}
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _cgroup_h
#define _cgroup_h
int lxc_get_cgroup_mount(const char *mtab, char *mnt);
int lxc_link_nsgroup(const char *name, pid_t pid);
int lxc_unlink_nsgroup(const char *name);
#endif
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <mntent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
#include <network.h>
#define MAXHWLEN 18
#define MAXINDEXLEN 20
#define MAXLINELEN 128
typedef int (*instanciate_cb)(const char *dirname,
const char *file, pid_t pid);
typedef int (*dir_cb)(const char *name, const char *dirname,
const char *file, void *data);
typedef int (*file_cb)(void* buffer, void *data);
struct netdev_conf {
const char *type;
instanciate_cb cb;
int count;
};
static int instanciate_veth(const char *, const char *, pid_t);
static int instanciate_macvlan(const char *, const char *, pid_t);
static int instanciate_phys(const char *, const char *, pid_t);
static struct netdev_conf netdev_conf[] = {
{ "veth", instanciate_veth, 0 },
{ "macvlan", instanciate_macvlan, 0, },
{ "phys", instanciate_phys, 0, },
};
static int dir_filter(const struct dirent *dirent)
{
if (!strcmp(dirent->d_name, ".") ||
!strcmp(dirent->d_name, ".."))
return 0;
return 1;
}
static int dir_for_each(const char *name, const char *dirname,
dir_cb callback, void *data)
{
struct dirent **namelist;
int n;
n = scandir(dirname, &namelist, dir_filter, alphasort);
if (n < 0) {
lxc_log_syserror("failed to scan %s directory", dirname);
return -1;
}
while (n--) {
if (callback(name, dirname, namelist[n]->d_name, data)) {
lxc_log_error("callback failed");
free(namelist[n]);
return -1;
}
free(namelist[n]);
}
return 0;
}
static int file_for_each_line(const char *file, file_cb callback,
void *buffer, size_t len, void* data)
{
FILE *f;
int err = -1;
f = fopen(file, "r");
if (!f) {
lxc_log_syserror("failed to open %s", file);
return -1;
}
while (fgets(buffer, len, f))
if (callback(buffer, data))
goto out;
err = 0;
out:
fclose(f);
return err;
}
static int write_info(const char *path, const char *file, const char *info)
{
int fd, err = -1;
char *f;
asprintf(&f, "%s/%s", path, file);
fd = creat(f, 0755);
if (fd < 0)
goto out;
if (write(fd, info, strlen(info)) < 0 ||
write(fd, "\n", strlen("\n") + 1) < 0)
goto out_write;
err = 0;
out:
close(fd);
free(f);
return err;
out_write:
unlink(f);
goto out;
}
static int read_info(const char *path, const char *file, char *info, size_t len)
{
int fd, ret = -1;
char *f, *token;
asprintf(&f, "%s/%s", path, file);
fd = open(f, O_RDONLY);
if (fd < 0) {
if (errno == ENOENT)
ret = 1;
goto out;
}
ret = read(fd, info, len);
if (ret < 0)
goto out;
token = strstr(info, "\n");
if (token)
*token = '\0';
ret = 0;
out:
close(fd);
free(f);
return ret;
}
static int delete_info(const char *path, const char *file)
{
char *info;
int ret;
asprintf(&info, "%s/%s", path, file);
ret = unlink(info);
free(info);
return ret;
}
static int configure_ip4addr(int fd, struct lxc_inetdev *in)
{
char addr[INET6_ADDRSTRLEN];
char bcast[INET_ADDRSTRLEN];
char *line = NULL;
int err = -1;
if (!inet_ntop(AF_INET, &in->addr, addr, sizeof(addr))) {
lxc_log_syserror("failed to convert ipv4 address");
goto err;
}
if (!inet_ntop(AF_INET, &in->bcast, bcast, sizeof(bcast))) {
lxc_log_syserror("failed to convert ipv4 broadcast");
goto err;
}
if (in->prefix)
asprintf(&line, "%s/%d %s\n", addr, in->prefix, bcast);
else
asprintf(&line, "%s %s\n", addr, bcast);
if (write(fd, line, strlen(line)) < 0) {
lxc_log_syserror("failed to write address info");
goto err;
}
err = 0;
err:
free(line);
return err;
}
static int configure_ip6addr(int fd, struct lxc_inet6dev *in6)
{
char addr[INET6_ADDRSTRLEN];
char *line = NULL;
int err = -1;
if (!inet_ntop(AF_INET6, &in6->addr, addr, sizeof(addr))) {
lxc_log_syserror("failed to convert ipv4 address");
goto err;
}
asprintf(&line, "%s/%d\n", addr, in6->prefix?in6->prefix:64);
if (write(fd, line, strlen(line)) < 0) {
lxc_log_syserror("failed to write address info");
goto err;
}
err = 0;
err:
free(line);
return err;
}
static int configure_ip_address(const char *path, struct lxc_list *ip, int family)
{
char file[MAXPATHLEN];
struct lxc_list *iterator;
int fd, err = -1;
if (mkdir(path, 0755)) {
lxc_log_syserror("failed to create directory %s", path);
return -1;
}
snprintf(file, MAXPATHLEN, "%s/addresses", path);
fd = creat(file, 0755);
if (fd < 0) {
lxc_log_syserror("failed to create %s file", file);
goto err;
}
lxc_list_for_each(iterator, ip) {
err = family == AF_INET?
configure_ip4addr(fd, iterator->elem):
configure_ip6addr(fd, iterator->elem);
if (err)
goto err;
}
out:
close(fd);
return err;
err:
unlink(file);
rmdir(path);
goto out;
}
static int configure_netdev(const char *path, struct lxc_netdev *netdev)
{
int err = -1;
char dir[MAXPATHLEN];
if (mkdir(path, 0755)) {
lxc_log_syserror("failed to create %s directory", path);
return -1;
}
if (netdev->ifname) {
if (write_info(path, "link", netdev->ifname))
goto out_link;
}
if (netdev->newname) {
if (write_info(path, "name", netdev->newname))
goto out_newname;
}
if (netdev->hwaddr) {
if (write_info(path, "hwaddr", netdev->hwaddr))
goto out_up;
}
if (netdev->flags & IFF_UP) {
if (write_info(path, "up", ""))
goto out_hwaddr;
}
if (!lxc_list_empty(&netdev->ipv4)) {
snprintf(dir, MAXPATHLEN, "%s/ipv4", path);
if (configure_ip_address(dir, &netdev->ipv4, AF_INET))
goto out_ipv4;
}
if (!lxc_list_empty(&netdev->ipv6)) {
snprintf(dir, MAXPATHLEN, "%s/ipv6", path);
if (configure_ip_address(dir, &netdev->ipv6, AF_INET6))
goto out_ipv6;
}
err = 0;
out:
return err;
out_ipv6:
delete_info(path, "ipv4");
out_ipv4:
delete_info(path, "up");
out_hwaddr:
delete_info(path, "hwaddr");
out_up:
delete_info(path, "name");
out_newname:
delete_info(path, "link");
out_link:
rmdir(path);
goto out;
}
static int configure_utsname(const char *name, struct utsname *utsname)
{
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
if (write_info(path, "utsname", utsname->nodename)) {
lxc_log_error("failed to write the utsname info");
return -1;
}
return 0;
}
static int configure_network(const char *name, struct lxc_list *network)
{
struct lxc_list *iterator;
struct lxc_network *n;
char networkpath[MAXPATHLEN];
char path[MAXPATHLEN];
int err = -1;
if (lxc_list_empty(network))
return 0;
snprintf(networkpath, MAXPATHLEN, LXCPATH "/%s/network", name);
if (mkdir(networkpath, 0755)) {
lxc_log_syserror("failed to create %s directory", networkpath);
goto out;
}
lxc_list_for_each(iterator, network) {
n = iterator->elem;
if (n->type < 0 || n->type > MAXCONFTYPE) {
lxc_log_error("invalid network configuration type %d",
n->type);
goto out;
}
snprintf(path, MAXPATHLEN, "%s/%s%d", networkpath,
netdev_conf[n->type].type,
netdev_conf[n->type].count++);
if (configure_netdev(path, lxc_list_first_elem(&n->netdev))) {
lxc_log_error("failed to configure network type %s",
netdev_conf[n->type].type);
goto out;
}
}
err = 0;
out:
return err;
}
static int configure_cgroup(const char *name, struct lxc_cgroup *cgroup)
{
return 0;
}
static int configure_chroot(const char *name, const char *chroot)
{
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, LXCPATH "/%s/chroot", name);
return symlink(chroot, path);
}
static int configure_mount(const char *name, const char *fstab)
{
char *path;
struct stat stat;
int infd, outfd;
void *src, *dst;
char c = '\0';
int ret = -1;
asprintf(&path, LXCPATH "/%s/fstab", name);
outfd = open(path, O_RDWR|O_CREAT|O_EXCL, 0640);
if (outfd < 0) {
lxc_log_syserror("failed to creat '%s'", path);
goto out;
}
infd = open(fstab, O_RDONLY);
if (infd < 0) {
lxc_log_syserror("failed to open '%s'", fstab);
goto out;
}
if (fstat(infd, &stat)) {
lxc_log_syserror("failed to stat '%s'", fstab);
goto out;
}
if (lseek(outfd, stat.st_size - 1, SEEK_SET) < 0) {
lxc_log_syserror("failed to seek dest file '%s'", path);
goto out;
}
/* fixup length */
if (write(outfd, &c, 1) < 0) {
lxc_log_syserror("failed to write to '%s'", path);
goto out;
}
src = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, infd, 0L);
if (src == MAP_FAILED) {
lxc_log_syserror("failed to mmap '%s'", fstab);
goto out;
}
dst = mmap(NULL, stat.st_size, PROT_WRITE, MAP_SHARED, outfd, 0L);
if (dst == MAP_FAILED) {
lxc_log_syserror("failed to mmap '%s'", path);
goto out;
}
memcpy(dst, src, stat.st_size);
munmap(src, stat.st_size);
munmap(dst, stat.st_size);
ret = 0;
out:
free(path);
return ret;
}
static int unconfigure_ip_addresses(const char *dirname)
{
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, "%s/ipv4", dirname);
delete_info(path, "addresses");
rmdir(path);
snprintf(path, MAXPATHLEN, "%s/ipv6", dirname);
delete_info(path, "addresses");
rmdir(path);
return 0;
}
static int unconfigure_network_cb(const char *name, const char *dirname,
const char *file, void *data)
{
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
delete_info(path, "name");
delete_info(path, "addr");
delete_info(path, "link");
delete_info(path, "hwaddr");
delete_info(path, "up");
unconfigure_ip_addresses(path);
rmdir(path);
return 0;
}
static int unconfigure_network(const char *name)
{
char dirname[MAXPATHLEN];
snprintf(dirname, MAXPATHLEN, LXCPATH "/%s/network", name);
dir_for_each(name, dirname, unconfigure_network_cb, NULL);
rmdir(dirname);
return 0;
}
static int unconfigure_cgroup(const char *name)
{
return 0;
}
static int unconfigure_chroot(const char *name)
{
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
delete_info(path, "chroot");
return 0;
}
static int unconfigure_mount(const char *name)
{
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
delete_info(path, "fstab");
return 0;
}
static int unconfigure_utsname(const char *name)
{
char path[MAXPATHLEN];
snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
delete_info(path, "utsname");
return 0;
}
static int setup_utsname(const char *name)
{
int ret;
char path[MAXPATHLEN];
struct utsname utsname;
snprintf(path, MAXPATHLEN, LXCPATH "/%s", name);
ret = read_info(path, "utsname", utsname.nodename,
sizeof(utsname.nodename));
if (ret < 0) {
lxc_log_syserror("failed to read utsname info");
return -1;
}
if (!ret && sethostname(utsname.nodename, strlen(utsname.nodename))) {
lxc_log_syserror("failed to set the hostname to '%s'",
utsname.nodename);
return -1;
}
return 0;
}
static int setup_chroot(const char *name)
{
char path[MAXPATHLEN], chrt[MAXPATHLEN];
snprintf(path, MAXPATHLEN, LXCPATH "/%s/chroot", name);
if (readlink(path, chrt, MAXPATHLEN) > 0) {
if (chroot(chrt)) {
lxc_log_syserror("failed to set chroot %s", path);
return -1;
}
if (chdir(getenv("HOME")) && chdir("/")) {
lxc_log_syserror("failed to change to home directory");
return -1;
}
}
return 0;
}
static int setup_mount(const char *name)
{
char path[MAXPATHLEN];
struct mntent *mntent;
FILE *file;
int ret = -1;
snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
file = setmntent(path, "r");
if (!file) {
if (errno == ENOENT)
return 0;
lxc_log_syserror("failed to open '%s'", path);
goto out;
}
while((mntent = getmntent(file))) {
if (mount(mntent->mnt_fsname, mntent->mnt_dir,
mntent->mnt_type, 0, NULL)) {
lxc_log_syserror("failed to mount '%s' on '%s'",
mntent->mnt_fsname, mntent->mnt_dir);
goto out;
}
}
ret = 0;
out:
endmntent(file);
return ret;
}
static int setup_ipv4_addr_cb(void *buffer, void *data)
{
char *ifname = data;
char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
int p = 24;
addr = buffer;
cursor = strstr(addr, " ");
if (cursor) {
*cursor = '\0';
bcast = cursor + 1;
cursor = strstr(bcast, "\n");
if (cursor)
*cursor = '\0';
}
slash = strstr(addr, "/");
if (slash) {
*slash = '\0';
prefix = slash + 1;
}
if (prefix)
p = atoi(prefix);
if (ip_addr_add(ifname, addr, p, bcast)) {
lxc_log_error("failed to set %s to addr %s/%d %s", ifname,
addr, p, bcast?bcast:"");
return -1;
}
return 0;
}
static int setup_ipv6_addr_cb(void *buffer, void *data)
{
char *ifname = data;
char *cursor, *slash, *addr, *bcast = NULL, *prefix = NULL;
int p = 24;
addr = buffer;
cursor = strstr(addr, " ");
if (cursor) {
*cursor = '\0';
bcast = cursor + 1;
cursor = strstr(bcast, "\n");
if (cursor)
*cursor = '\0';
}
slash = strstr(addr, "/");
if (slash) {
*slash = '\0';
prefix = slash + 1;
}
if (prefix)
p = atoi(prefix);
if (ip6_addr_add(ifname, addr, p, bcast)) {
lxc_log_error("failed to set %s to addr %s/%d %s", ifname,
addr, p, bcast?bcast:"");
return -1;
}
return 0;
}
static int setup_hw_addr(char *hwaddr, const char *ifname)
{
struct sockaddr sockaddr;
struct ifreq ifr;
int ret, fd;
if (lxc_convert_mac(hwaddr, &sockaddr)) {
fprintf(stderr, "conversion has failed\n");
return -1;
}
memcpy(ifr.ifr_name, ifname, IFNAMSIZ);
memcpy((char *) &ifr.ifr_hwaddr, (char *) &sockaddr, sizeof(sockaddr));
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
return -1;
}
ret = ioctl(fd, SIOCSIFHWADDR, &ifr);
close(fd);
if (ret)
perror("ioctl");
return ret;
}
static int setup_ip_addr(const char *dirname, const char *ifname)
{
char path[MAXPATHLEN], line[MAXLINELEN];
struct stat s;
int ret = 0;
snprintf(path, MAXPATHLEN, "%s/ipv4/addresses", dirname);
if (!stat(path, &s))
ret = file_for_each_line(path, setup_ipv4_addr_cb,
line, MAXPATHLEN, (void*)ifname);
return ret;
}
static int setup_ip6_addr(const char *dirname, const char *ifname)
{
char path[MAXPATHLEN], line[MAXLINELEN];
struct stat s;
int ret = 0;
snprintf(path, MAXLINELEN, "%s/ipv6/addresses", dirname);
if (!stat(path, &s))
ret = file_for_each_line(path, setup_ipv6_addr_cb,
line, MAXPATHLEN, (void*)ifname);
return ret;
}
static int setup_network_cb(const char *name, const char *dirname,
const char *file, void *data)
{
char path[MAXPATHLEN];
char strindex[MAXINDEXLEN];
char ifname[IFNAMSIZ];
char newname[IFNAMSIZ];
char hwaddr[MAXHWLEN];
char *current_ifname = ifname;
int ifindex, ret = -1;
snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
if (read_info(path, "ifindex", strindex, sizeof(strindex))) {
lxc_log_error("failed to read ifindex info");
goto out;
}
ifindex = atoi(strindex);
if (!ifindex) {
lxc_log_error("bad index %s", strindex);
goto out;
}
if (!if_indextoname(ifindex, current_ifname)) {
lxc_log_error("no interface corresponding to index '%d'",
ifindex);
goto out;
}
if (!read_info(path, "name", newname, sizeof(newname))) {
if (device_rename(ifname, newname)) {
lxc_log_error("failed to rename %s->%s",
ifname, newname);
goto out;
}
current_ifname = newname;
}
if (!read_info(path, "hwaddr", hwaddr, sizeof(hwaddr))) {
if (setup_hw_addr(hwaddr, current_ifname)) {
lxc_log_error("failed to setup hw address for '%s'",
current_ifname);
goto out;
}
}
if (setup_ip_addr(path, current_ifname)) {
lxc_log_error("failed to setup ip addresses for '%s'",
ifname);
goto out;
}
if (setup_ip6_addr(path, current_ifname)) {
lxc_log_error("failed to setup ipv6 addresses for '%s'",
ifname);
goto out;
}
if (!read_info(path, "up", strindex, sizeof(strindex))) {
if (device_up(current_ifname)) {
lxc_log_error("failed to set '%s' up", current_ifname);
goto out;
}
/* the network is up, make the loopback up too */
if (device_up("lo")) {
lxc_log_error("failed to set the loopback up");
goto out;
}
}
ret = 0;
out:
return ret;
}
static int setup_network(const char *name)
{
char dirname[MAXPATHLEN];
snprintf(dirname, MAXPATHLEN, LXCPATH "/%s/network", name);
return dir_for_each(name, dirname, setup_network_cb, NULL);
}
int conf_has(const char *name, const char *info)
{
int ret;
char path[MAXPATHLEN];
struct stat st;
snprintf(path, MAXPATHLEN, LXCPATH "/%s/%s", name, info);
ret = stat(path, &st);
if (!ret) {
ret = 1;
goto out;
}
if (errno == ENOENT) {
ret = 0;
goto out;
}
lxc_log_syserror("failed to stat %s info", info);
out:
return ret;
}
int lxc_configure(const char *name, struct lxc_conf *conf)
{
if (!conf)
return 0;
if (conf->utsname && configure_utsname(name, conf->utsname)) {
lxc_log_error("failed to configure the utsname");
return -1;
}
if (configure_network(name, &conf->networks)) {
lxc_log_error("failed to configure the network");
return -1;
}
if (conf->cgroup && configure_cgroup(name, conf->cgroup)) {
lxc_log_error("failed to configure the control group");
return -1;
}
if (conf->chroot && configure_chroot(name, conf->chroot)) {
lxc_log_error("failed to configure the chroot");
return -1;
}
if (conf->fstab && configure_mount(name, conf->fstab)) {
lxc_log_error("failed to configure the mount points");
return -1;
}
return 0;
}
int lxc_unconfigure(const char *name)
{
if (conf_has_utsname(name) && unconfigure_utsname(name))
lxc_log_error("failed to cleanup utsname");
if (conf_has_network(name) && unconfigure_network(name))
lxc_log_error("failed to cleanup the network");
if (unconfigure_cgroup(name))
lxc_log_error("failed to cleanup cgroup");
if (conf_has_chroot(name) && unconfigure_chroot(name))
lxc_log_error("failed to cleanup chroot");
if (conf_has_fstab(name) && unconfigure_mount(name))
lxc_log_error("failed to cleanup mount");
return 0;
}
static int instanciate_veth(const char *dirname, const char *file, pid_t pid)
{
char *path = NULL, *strindex = NULL, *veth1 = NULL, *veth2 = NULL;
char bridge[IFNAMSIZ];
int ifindex, ret = -1;
asprintf(&veth1, "%s_%d", file, pid);
asprintf(&veth2, "%s~%d", file, pid);
asprintf(&path, "%s/%s", dirname, file);
if (read_info(path, "link", bridge, IFNAMSIZ)) {
lxc_log_error("failed to read bridge info");
goto out;
}
if (lxc_configure_veth(veth1, veth2, bridge)) {
lxc_log_error("failed to create %s-%s/%s", veth1, veth2, bridge);
goto out;
}
ifindex = if_nametoindex(veth2);
if (!ifindex) {
lxc_log_error("failed to retrieve the index for %s", veth2);
goto out;
}
asprintf(&strindex, "%d", ifindex);
if (write_info(path, "ifindex", strindex)) {
lxc_log_error("failed to write interface index to %s", path);
goto out;
}
if (!read_info(path, "up", strindex, sizeof(strindex))) {
if (device_up(veth1)) {
lxc_log_error("failed to set %s up", veth1);
goto out;
}
}
ret = 0;
out:
free(path);
free(strindex);
free(veth1);
free(veth2);
return ret;
}
static int instanciate_macvlan(const char *dirname, const char *file, pid_t pid)
{
char *path = NULL, *strindex = NULL, *peer = NULL;
char link[IFNAMSIZ];
int ifindex, ret = -1;
asprintf(&peer, "%s~%d", file, pid);
asprintf(&path, "%s/%s", dirname, file);
if (read_info(path, "link", link, IFNAMSIZ)) {
lxc_log_error("failed to read bridge info");
goto out;
}
if (lxc_configure_macvlan(link, peer)) {
lxc_log_error("failed to create macvlan interface %s", peer);
goto out;
}
ifindex = if_nametoindex(peer);
if (!ifindex) {
lxc_log_error("failed to retrieve the index for %s", peer);
goto out;
}
asprintf(&strindex, "%d", ifindex);
if (write_info(path, "ifindex", strindex)) {
lxc_log_error("failed to write interface index to %s", path);
goto out;
}
ret = 0;
out:
free(path);
free(strindex);
free(peer);
return ret;
}
static int instanciate_phys(const char *dirname, const char *file, pid_t pid)
{
char *path = NULL, *strindex = NULL;
char link[IFNAMSIZ];
int ifindex, ret = -1;
asprintf(&path, "%s/%s", dirname, file);
if (read_info(path, "link", link, IFNAMSIZ)) {
lxc_log_error("failed to read link info");
goto out;
}
ifindex = if_nametoindex(link);
if (!ifindex) {
lxc_log_error("failed to retrieve the index for %s", link);
goto out;
}
asprintf(&strindex, "%d", ifindex);
if (write_info(path, "ifindex", strindex)) {
lxc_log_error("failed to write interface index to %s", path);
goto out;
}
ret = 0;
out:
free(path);
free(strindex);
return ret;
}
static int instanciate_netdev_cb(const char *name, const char *dirname,
const char *file, void *data)
{
pid_t *pid = data;
if (!strncmp("veth", file, strlen("veth")))
return instanciate_veth(dirname, file, *pid);
else if (!strncmp("macvlan", file, strlen("macvlan")))
return instanciate_macvlan(dirname, file, *pid);
else if (!strncmp("phys", file, strlen("phys")))
return instanciate_phys(dirname, file, *pid);
return -1;
}
static int instanciate_netdev(const char *name, pid_t pid)
{
char *dirname;
int ret;
asprintf(&dirname, LXCPATH "/%s/network", name);
ret = dir_for_each(name, dirname, instanciate_netdev_cb, &pid);
free(dirname);
return ret;
}
static int move_netdev_cb(const char *name, const char *dirname,
const char *file, void *data)
{
char *path, ifname[IFNAMSIZ], strindex[MAXINDEXLEN];
pid_t *pid = data;
int ifindex, ret = -1;
asprintf(&path, "%s/%s", dirname, file);
if (read_info(path, "ifindex", strindex, MAXINDEXLEN) < 0) {
lxc_log_error("failed to read index to from %s", path);
goto out;
}
ifindex = atoi(strindex);
if (!if_indextoname(ifindex, ifname)) {
lxc_log_error("interface with index %d does not exist",
ifindex);
goto out;
}
if (device_move(ifname, *pid)) {
lxc_log_error("failed to move %s to %d", ifname, *pid);
goto out;
}
ret = 0;
out:
free(path);
return ret;
}
static int move_netdev(const char *name, pid_t pid)
{
char *dirname;
int ret;
asprintf(&dirname, LXCPATH "/%s/network", name);
ret = dir_for_each(name, dirname, move_netdev_cb, &pid);
free(dirname);
return ret;
}
int conf_create_network(const char *name, pid_t pid)
{
if (instanciate_netdev(name, pid)) {
lxc_log_error("failed to instantiate the network devices");
return -1;
}
if (move_netdev(name, pid)) {
lxc_log_error("failed to move the netdev to the container");
return -1;
}
return 0;
}
static int delete_netdev_cb(const char *name, const char *dirname,
const char *file, void *data)
{
char strindex[MAXINDEXLEN];
char path[MAXPATHLEN];
char ifname[IFNAMSIZ];
int i, ifindex;
snprintf(path, MAXPATHLEN, "%s/%s", dirname, file);
if (read_info(path, "ifindex", strindex, MAXINDEXLEN)) {
lxc_log_error("failed to read ifindex info");
return -1;
}
ifindex = atoi(strindex);
if (!ifindex) {
lxc_log_error("bad index %s", strindex);
return -1;
}
/* TODO : temporary code - needs wait on namespace */
for (i = 0; i < 120; i++) {
if (if_indextoname(ifindex, ifname))
break;
if (!i)
printf("waiting for interface #%d to come back\n", ifindex);
else
printf("."); fflush(stdout);
sleep(1);
}
/* do not delete a physical network device */
if (strncmp("phys", file, strlen("phys")))
if (device_delete(ifname)) {
lxc_log_error("failed to remove the netdev %s", ifname);
}
delete_info(path, "ifindex");
return 0;
}
static int delete_netdev(const char *name)
{
char *dirname;
int ret;
asprintf(&dirname, LXCPATH "/%s/network", name);
ret = dir_for_each(name, dirname, delete_netdev_cb, NULL);
free(dirname);
return ret;
}
int conf_destroy_network(const char *name)
{
if (delete_netdev(name)) {
lxc_log_error("failed to remove the network devices");
return -1;
}
return 0;
}
int lxc_setup(const char *name)
{
if (conf_has_utsname(name) && setup_utsname(name)) {
lxc_log_error("failed to setup the utsname for '%s'", name);
return -1;
}
if (conf_has_network(name) && setup_network(name)) {
lxc_log_error("failed to setup the network for '%s'", name);
return -1;
}
if (conf_has_fstab(name) && setup_mount(name)) {
lxc_log_error("failed to setup the mount points for '%s'", name);
return -1;
}
if (conf_has_chroot(name) && setup_chroot(name)) {
lxc_log_error("failed to set chroot for '%s'", name);
return -1;
}
return 0;
}
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _conf_h
#define _conf_h
#include <netinet/in.h>
enum {
VETH,
MACVLAN,
PHYS,
MAXCONFTYPE,
};
/*
* Defines the structure to configure an ipv4 address
* @address : ipv4 address
* @broadcast : ipv4 broadcast address
* @mask : network mask
*/
struct lxc_inetdev {
struct in_addr addr;
struct in_addr bcast;
int prefix;
};
struct lxc_route {
struct in_addr addr;
};
/*
* Defines the structure to configure an ipv6 address
* @flags : set the address up
* @address : ipv6 address
* @broadcast : ipv6 broadcast address
* @mask : network mask
*/
struct lxc_inet6dev {
struct in6_addr addr;
struct in6_addr bcast;
struct in6_addr acast;
int prefix;
};
struct lxc_route6 {
struct in6_addr addr;
};
/*
* Defines a structure to configure a network device
* @ifname : network device name
* @flags : flag of the network device (IFF_UP, ... )
* @ipv4 : a list of ipv4 addresses to be set on the network device
* @ipv6 : a list of ipv6 addresses to be set on the network device
*/
struct lxc_netdev {
int flags;
char *ifname;
char *newname;
char *hwaddr;
struct lxc_list ipv4;
struct lxc_list ipv6;
struct lxc_list route4;
struct lxc_list route6;
};
/*
* Defines the kind of the network to use
* @type : the type of the network virtualization
* @phys : phys configuration type
* @veth : veth configuration type
* @macvlan : macvlan configuration type
*/
struct lxc_network {
int type;
struct lxc_list netdev;
};
/*
* Defines a structure to configure the control data and path
*/
struct lxc_cgroup {
;
};
/*
* Defines the global container configuration
* @chroot : the root directory to run the container
* @mount : the list of mount points
* @network : the network configuration
* @utsname : the container utsname
*/
struct lxc_conf {
char *chroot;
char *fstab;
struct utsname *utsname;
struct lxc_cgroup *cgroup;
struct lxc_list networks;
};
/*
* Configure the external resources for the container
*/
extern int lxc_configure(const char *name, struct lxc_conf *conf);
/*
* Remove the resources created by the configuration
*/
extern int lxc_unconfigure(const char *name);
extern int conf_create_network(const char *name, pid_t pid);
extern int conf_destroy_network(const char *name);
/*
* Configure the container from inside
*/
extern int lxc_setup(const char *name);
extern int conf_has(const char *name, const char *info);
#define conf_has_fstab(__name) conf_has(__name, "fstab")
#define conf_has_chroot(__name) conf_has(__name, "chroot")
#define conf_has_utsname(__name) conf_has(__name, "utsname")
#define conf_has_network(__name) conf_has(__name, "network")
#endif
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <list.h>
#ifndef _list_h
#define _list_h
struct lxc_list {
void *elem;
struct lxc_list *next;
struct lxc_list *prev;
};
#define lxc_init_list(l) { .next = l, .prev = l, }
#define lxc_list_for_each(__iterator, __list) \
for (__iterator = (__list)->next; \
__iterator != __list; \
__iterator = __iterator->next)
static inline void lxc_list_init(struct lxc_list *list)
{
list->elem = NULL;
list->next = list->prev = list;
}
static inline void lxc_list_add_elem(struct lxc_list *list, void *elem)
{
list->elem = elem;
}
static inline void *lxc_list_first_elem(struct lxc_list *list)
{
return list->next->elem;
}
static inline int lxc_list_empty(struct lxc_list *list)
{
return list == list->next;
}
static inline void lxc_list_add(struct lxc_list *list, struct lxc_list *new)
{
struct lxc_list *next = list->next;
next->prev = new;
new->next = next;
new->prev = list;
list->next = new;
}
static inline void lxc_list_del(struct lxc_list *list)
{
struct lxc_list *next, *prev;
next = list->next;
prev = list->prev;
next->prev = prev;
prev->next = next;
}
#endif
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define _GNU_SOURCE
#include <stdio.h>
#undef _GNU_SOURCE
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/file.h>
#include <lxc.h>
int lxc_get_lock(const char *name)
{
char *lock;
int fd, ret;
asprintf(&lock, LXCPATH "/%s", name);
fd = open(lock, O_RDONLY|O_DIRECTORY, S_IRUSR|S_IWUSR);
if (fd < 0) {
ret = -errno;
goto out;
}
if (flock(fd, LOCK_EX|LOCK_NB)) {
ret = errno == EWOULDBLOCK ? 0 : -errno;
close(fd);
goto out;
}
ret = fd;
out:
free(lock);
return ret;
}
void lxc_put_lock(int lock)
{
flock(lock, LOCK_UN);
close(lock);
}
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _lock_h
#define _lock_h
extern int lxc_get_lock(const char *name);
extern void lxc_put_lock(int lock);
#endif
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <lxc_log.h>
#define MAXTIMELEN 47;
#define ERRNO_FORMAT "%d (%s)"
#ifndef _log_h
#define _log_h
#define lxc_log(format, level, ...) do { \
fprintf(stderr, "[%s] \t%s:%d - " format "\n", \
level, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0)
#define lxc_log_error(format, ...) lxc_log(format, "error", ##__VA_ARGS__);
#define lxc_log_warning(format, ...) lxc_log(format, "warning", ##__VA_ARGS__);
#define lxc_log_info(format, ...) lxc_log(format, "info", ##__VA_ARGS__);
#define lxc_log_debug(format, ...) lxc_log(format, "debug", ##__VA_ARGS__);
#define lxc_log_trace(format, ...) lxc_log(format, "trace", ##__VA_ARGS__);
#define lxc_log_syserror(format, ...) do { \
fprintf(stderr, "[SYSERROR][%s] \t%s:%d - " format "\n", \
strerror(errno),__FUNCTION__, __LINE__, \
##__VA_ARGS__); \
} while (0)
#endif
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __namespace_h
#define __namespace_h
#include <syscall.h>
#ifndef CLONE_FS
# define CLONE_FS 0x00000200
#endif
#ifndef CLONE_NEWNS
# define CLONE_NEWNS 0x00020000
#endif
#ifndef CLONE_NEWUTS
# define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWIPC
# define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWUSER
# define CLONE_NEWUSER 0x10000000
#endif
#ifndef CLONE_NEWPID
# define CLONE_NEWPID 0x20000000
#endif
#ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000
#endif
#ifndef __NR_unshare
# ifdef __i386__
# define __NR_unshare 310
# elif __x86_64__
# define __NR_unshare 272
# elif __ia64__
# define __NR_unshare 1296
# elif __s390__
# define __NR_unshare 303
# elif __powerpc__
# define __NR_unshare 282
#else
# error "unsupported architecture"
# endif
#endif
#if __i386__ || __x86_64__ || __s390__ || __powerpc__
# define fork_ns(flags) syscall(SYS_clone, flags|SIGCHLD, NULL);
#elif __ia64__
# define fork_ns(flags) syscall(SYS_clone2, flags|SIGCHLD, NULL);
#else
# error "unsupported architecture"
#endif
#define unshare_ns(flags) syscall(__NR_unshare, flags, NULL);
#endif
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <lxc.h>
static char *strstate[] = {
"STOPPED", "STARTING", "RUNNING", "STOPPING",
"ABORTING", "FREEZING", "FROZEN",
};
const char *state2str(lxc_state_t state)
{
if (state < STOPPED || state > MAX_STATE - 1)
return NULL;
return strstate[state];
}
lxc_state_t str2state(const char *state)
{
int i, len;
len = sizeof(strstate)/sizeof(strstate[0]);
for (i = 0; i < len; i++)
if (!strcmp(strstate[i], state))
return i;
return -1;
}
int lxc_setstate(const char *name, lxc_state_t state)
{
int fd, err;
char file[MAXPATHLEN];
const char *str = state2str(state);
if (!str)
return -1;
snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name);
fd = open(file, O_WRONLY);
if (fd < 0) {
lxc_log_syserror("failed to open %s file", file);
return -1;
}
if (flock(fd, LOCK_EX)) {
lxc_log_syserror("failed to take the lock to %s", file);
goto out;
}
if (ftruncate(fd, 0)) {
lxc_log_syserror("failed to truncate the file %s", file);
goto out;
}
if (write(fd, str, strlen(str)) < 0) {
lxc_log_syserror("failed to write state to %s", file);
goto out;
}
err = 0;
out:
close(fd);
/* let the event to be propagated, crappy but that works,
* otherwise the events will be folded into only one event,
* and I want to have them to be one by one in order
* to follow the different states of the container.
*/
usleep(200000);
return -err;
}
int mkstate(const char *name)
{
int fd;
char file[MAXPATHLEN];
snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name);
fd = creat(file, S_IRUSR|S_IWUSR);
if (fd < 0) {
lxc_log_syserror("failed to create file %s", file);
return -1;
}
close(fd);
return 0;
}
int rmstate(const char *name)
{
char file[MAXPATHLEN];
snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name);
unlink(file);
return 0;
}
lxc_state_t lxc_getstate(const char *name)
{
int fd, err;
char file[MAXPATHLEN];
snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name);
fd = open(file, O_RDONLY);
if (fd < 0) {
lxc_log_syserror("failed to open %s", file);
return -1;
}
if (flock(fd, LOCK_SH)) {
lxc_log_syserror("failed to take the lock to %s", file);
close(fd);
return -1;
}
err = read(fd, file, strlen(file));
if (err < 0) {
lxc_log_syserror("failed to read file %s", file);
close(fd);
return -1;
}
file[err] = '\0';
close(fd);
return str2state(file);
}
static int freezer_state(const char *name)
{
char freezer[MAXPATHLEN];
char status[MAXPATHLEN];
FILE *file;
int err;
snprintf(freezer, MAXPATHLEN,
LXCPATH "/%s/freezer.freeze", name);
file = fopen(freezer, "r");
if (file < 0) {
lxc_log_syserror("failed to open %s", freezer);
return -1;
}
err = fscanf(file, "%s", status);
fclose(file);
if (err == EOF) {
lxc_log_syserror("failed to read %s", freezer);
return -1;
}
return str2state(status);
}
lxc_state_t lxc_state(const char *name)
{
int state = freezer_state(name);
if (state != FROZEN && state != FREEZING)
state = lxc_getstate(name);
return state;
}
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _state_h
#define _state_h
typedef enum {
STOPPED, STARTING, RUNNING, STOPPING,
ABORTING, FREEZING, FROZEN, MAX_STATE,
} lxc_state_t;
extern const char *state2str(lxc_state_t state);
extern lxc_state_t str2state(const char *state);
extern int mkstate(const char *name);
extern int rmstate(const char *name);
extern int lxc_setstate(const char *name, lxc_state_t state);
extern lxc_state_t lxc_getstate(const char *name);
#endif
/*
* lxc: linux Container library
*
* (C) Copyright IBM Corp. 2007, 2008
*
* Authors:
* Daniel Lezcano <dlezcano at fr.ibm.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _utils_h
#define _utils_h
#define LXC_TTY_HANDLER(s) \
static struct sigaction lxc_tty_sa_##s; \
static void tty_##s##_handler(int sig, siginfo_t *info, void *ctx) \
{ \
if (lxc_tty_sa_##s.sa_handler == SIG_DFL || \
lxc_tty_sa_##s.sa_handler == SIG_IGN) \
return; \
(*lxc_tty_sa_##s.sa_sigaction)(sig, info, ctx); \
}
#define LXC_TTY_ADD_HANDLER(s) \
do { \
struct sigaction sa; \
sa.sa_sigaction = tty_##s##_handler; \
sa.sa_flags = SA_SIGINFO; \
sigfillset(&sa.sa_mask); \
/* No error expected with sigaction. */ \
sigaction(s, &sa, &lxc_tty_sa_##s); \
} while (0)
#define LXC_TTY_DEL_HANDLER(s) \
do { \
sigaction(s, &lxc_tty_sa_##s, NULL); \
} while (0)
#endif
......@@ -33,8 +33,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <log.h>
int lxc_monitor(const char *name, int output_fd)
{
......
......@@ -41,15 +41,6 @@
#include <net/if.h>
#include <lxc.h>
#include <namespace.h>
#include <network.h>
#include <state.h>
#include <cgroup.h>
#include <utils.h>
#include <list.h>
#include <conf.h>
#include <log.h>
#include <lock.h>
LXC_TTY_HANDLER(SIGINT);
LXC_TTY_HANDLER(SIGQUIT);
......
......@@ -37,13 +37,10 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <log.h>
#include <lock.h>
int lxc_stop(const char *name)
{
char *init;
char init[MAXPATHLEN];
char val[MAXPIDLEN];
int fd, lock, ret = -1;
size_t pid;
......@@ -61,11 +58,11 @@ int lxc_stop(const char *name)
return -1;
}
asprintf(&init, LXCPATH "/%s/init", name);
snprintf(init, MAXPATHLEN, LXCPATH "/%s/init", name);
fd = open(init, O_RDONLY);
if (fd < 0) {
lxc_log_syserror("failed to open init file for %s", name);
goto out_free;
goto out_unlock;
}
if (read(fd, val, sizeof(val)) < 0) {
......@@ -89,7 +86,7 @@ int lxc_stop(const char *name)
out_close:
close(fd);
out_free:
free(init);
out_unlock:
lxc_put_lock(lock);
return ret;
}
......@@ -33,10 +33,6 @@
#include <net/if.h>
#include <lxc.h>
#include <list.h>
#include <conf.h>
#include <log.h>
typedef int (*file_cb)(char* buffer, void *data);
typedef int (*config_cb)(char *value, struct lxc_conf *lxc_conf);
......@@ -128,11 +124,11 @@ static int char_right_gc(char *buffer, size_t len)
static int config_network_type(char *value, struct lxc_conf *lxc_conf)
{
struct list *networks = &lxc_conf->networks;
struct network *network;
struct netdev *netdev;
struct list *list;
struct list *ndlist;
struct lxc_list *networks = &lxc_conf->networks;
struct lxc_network *network;
struct lxc_netdev *netdev;
struct lxc_list *list;
struct lxc_list *ndlist;
network = malloc(sizeof(*network));
if (!network) {
......@@ -140,7 +136,7 @@ static int config_network_type(char *value, struct lxc_conf *lxc_conf)
return -1;
}
list_init(&network->netdev);
lxc_list_init(&network->netdev);
netdev = malloc(sizeof(*netdev));
if (!netdev) {
......@@ -148,10 +144,10 @@ static int config_network_type(char *value, struct lxc_conf *lxc_conf)
return -1;
}
list_init(&netdev->ipv4);
list_init(&netdev->ipv6);
list_init(&netdev->route4);
list_init(&netdev->route6);
lxc_list_init(&netdev->ipv4);
lxc_list_init(&netdev->ipv6);
lxc_list_init(&netdev->route4);
lxc_list_init(&netdev->route6);
ndlist = malloc(sizeof(*ndlist));
if (!ndlist) {
......@@ -161,7 +157,7 @@ static int config_network_type(char *value, struct lxc_conf *lxc_conf)
ndlist->elem = netdev;
list_add(&network->netdev, ndlist);
lxc_list_add(&network->netdev, ndlist);
list = malloc(sizeof(*list));
if (!list) {
......@@ -169,10 +165,10 @@ static int config_network_type(char *value, struct lxc_conf *lxc_conf)
return -1;
}
list_init(list);
lxc_list_init(list);
list->elem = network;
list_add(networks, list);
lxc_list_add(networks, list);
if (!strcmp(value, "veth"))
network->type = VETH;
......@@ -189,38 +185,38 @@ static int config_network_type(char *value, struct lxc_conf *lxc_conf)
static int config_network_flags(char *value, struct lxc_conf *lxc_conf)
{
struct list *networks = &lxc_conf->networks;
struct network *network;
struct netdev *netdev;
struct lxc_list *networks = &lxc_conf->networks;
struct lxc_network *network;
struct lxc_netdev *netdev;
if (list_empty(networks)) {
if (lxc_list_empty(networks)) {
lxc_log_error("network is not created for '%s' option", value);
return -1;
}
network = list_first_elem(networks);
network = lxc_list_first_elem(networks);
if (!network) {
lxc_log_error("no network defined for '%s' option", value);
return -1;
}
netdev = list_first_elem(&network->netdev);
netdev = lxc_list_first_elem(&network->netdev);
netdev->flags |= IFF_UP;
return 0;
}
static int config_network_link(char *value, struct lxc_conf *lxc_conf)
{
struct list *networks = &lxc_conf->networks;
struct network *network;
struct netdev *netdev;
struct lxc_list *networks = &lxc_conf->networks;
struct lxc_network *network;
struct lxc_netdev *netdev;
if (list_empty(networks)) {
if (lxc_list_empty(networks)) {
lxc_log_error("network is not created for %s", value);
return -1;
}
network = list_first_elem(networks);
network = lxc_list_first_elem(networks);
if (!network) {
lxc_log_error("no network defined for %s", value);
return -1;
......@@ -231,23 +227,23 @@ static int config_network_link(char *value, struct lxc_conf *lxc_conf)
return -1;
}
netdev = list_first_elem(&network->netdev);
netdev = lxc_list_first_elem(&network->netdev);
netdev->ifname = strdup(value);
return 0;
}
static int config_network_name(char *value, struct lxc_conf *lxc_conf)
{
struct list *networks = &lxc_conf->networks;
struct network *network;
struct netdev *netdev;
struct lxc_list *networks = &lxc_conf->networks;
struct lxc_network *network;
struct lxc_netdev *netdev;
if (list_empty(networks)) {
if (lxc_list_empty(networks)) {
lxc_log_error("network is not created for %s", value);
return -1;
}
network = list_first_elem(networks);
network = lxc_list_first_elem(networks);
if (!network) {
lxc_log_error("no network defined for %s", value);
return -1;
......@@ -258,54 +254,54 @@ static int config_network_name(char *value, struct lxc_conf *lxc_conf)
return -1;
}
netdev = list_first_elem(&network->netdev);
netdev = lxc_list_first_elem(&network->netdev);
netdev->newname = strdup(value);
return 0;
}
static int config_network_hwaddr(char *value, struct lxc_conf *lxc_conf)
{
struct list *networks = &lxc_conf->networks;
struct network *network;
struct netdev *netdev;
struct lxc_list *networks = &lxc_conf->networks;
struct lxc_network *network;
struct lxc_netdev *netdev;
if (list_empty(networks)) {
if (lxc_list_empty(networks)) {
lxc_log_error("network is not created for %s", value);
return -1;
}
network = list_first_elem(networks);
network = lxc_list_first_elem(networks);
if (!network) {
lxc_log_error("no network defined for %s", value);
return -1;
}
netdev = list_first_elem(&network->netdev);
netdev = lxc_list_first_elem(&network->netdev);
netdev->hwaddr = strdup(value);
return 0;
}
static int config_network_ipv4(char *value, struct lxc_conf *lxc_conf)
{
struct list *networks = &lxc_conf->networks;
struct network *network;
struct inetdev *inetdev;
struct netdev *netdev;
struct list *list;
struct lxc_list *networks = &lxc_conf->networks;
struct lxc_network *network;
struct lxc_inetdev *inetdev;
struct lxc_netdev *netdev;
struct lxc_list *list;
char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;
if (list_empty(networks)) {
if (lxc_list_empty(networks)) {
lxc_log_error("network is not created for '%s'", value);
return -1;
}
network = list_first_elem(networks);
network = lxc_list_first_elem(networks);
if (!network) {
lxc_log_error("no network defined for '%s'", value);
return -1;
}
netdev = list_first_elem(&network->netdev);
netdev = lxc_list_first_elem(&network->netdev);
if (!netdev) {
lxc_log_error("no netdev defined for '%s'", value);
}
......@@ -323,7 +319,7 @@ static int config_network_ipv4(char *value, struct lxc_conf *lxc_conf)
return -1;
}
list_init(list);
lxc_list_init(list);
list->elem = inetdev;
addr = value;
......@@ -359,27 +355,27 @@ static int config_network_ipv4(char *value, struct lxc_conf *lxc_conf)
if (prefix)
inetdev->prefix = atoi(prefix);
list_add(&netdev->ipv4, list);
lxc_list_add(&netdev->ipv4, list);
return 0;
}
static int config_network_ipv6(char *value, struct lxc_conf *lxc_conf)
{
struct list *networks = &lxc_conf->networks;
struct network *network;
struct netdev *netdev;
struct inet6dev *inet6dev;
struct list *list;
struct lxc_list *networks = &lxc_conf->networks;
struct lxc_network *network;
struct lxc_netdev *netdev;
struct lxc_inet6dev *inet6dev;
struct lxc_list *list;
char *slash;
char *netmask;
if (list_empty(networks)) {
if (lxc_list_empty(networks)) {
lxc_log_error("network is not created for %s", value);
return -1;
}
network = list_first_elem(networks);
network = lxc_list_first_elem(networks);
if (!network) {
lxc_log_error("no network defined for %s", value);
return -1;
......@@ -398,7 +394,7 @@ static int config_network_ipv6(char *value, struct lxc_conf *lxc_conf)
return -1;
}
list_init(list);
lxc_list_init(list);
list->elem = inet6dev;
slash = strstr(value, "/");
......@@ -414,8 +410,8 @@ static int config_network_ipv6(char *value, struct lxc_conf *lxc_conf)
}
netdev = list_first_elem(&network->netdev);
list_add(&netdev->ipv6, list);
netdev = lxc_list_first_elem(&network->netdev);
lxc_list_add(&netdev->ipv6, list);
return 0;
}
......@@ -545,6 +541,6 @@ int config_init(struct lxc_conf *conf)
conf->fstab = NULL;
conf->utsname = NULL;
conf->cgroup = NULL;
list_init(&conf->networks);
lxc_list_init(&conf->networks);
return 0;
}
......@@ -32,9 +32,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <list.h>
#include <conf.h>
#include "config.h"
......
......@@ -26,7 +26,6 @@
#include <sys/types.h>
#include <lxc.h>
#include <state.h>
void usage(char *cmd)
{
......
......@@ -26,7 +26,6 @@
#include <sys/types.h>
#include <lxc.h>
#include <state.h>
void usage(char *cmd)
{
......
......@@ -27,8 +27,8 @@
#include <netinet/in.h>
#include <net/if.h>
#include <list.h>
#include <conf.h>
#include <lxc_list.h>
#include <lxc_conf.h>
/*
* I want to setup a container with a veth attached on a bridge,
......
......@@ -31,9 +31,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <list.h>
#include <conf.h>
#include "../src/lxc/config.h"
......
......@@ -31,9 +31,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <list.h>
#include <conf.h>
static void usage(const char *cmd)
{
......@@ -50,7 +47,7 @@ int main(int argc, char *argv[])
/* struct list mclist2; */
/* struct list vethlist; */
/* struct list vethlist2; */
struct list phylist;
struct lxc_list phylist;
/* struct inetdev idev; */
/* struct list l1 = init_list(&l1); */
......@@ -129,30 +126,30 @@ int main(int argc, char *argv[])
/* }; */
/* mclist2.elem = &macvlan2; */
struct netdev nd = {
struct lxc_netdev nd = {
.ifname = "dummy0",
.ipv4 = init_list(&nd.ipv4),
.ipv6 = init_list(&nd.ipv6),
.ipv4 = lxc_init_list(&nd.ipv4),
.ipv6 = lxc_init_list(&nd.ipv6),
};
struct list ndlist = init_list(&ndlist);
struct lxc_list ndlist = lxc_init_list(&ndlist);
ndlist.elem = &nd;
struct network phys = {
struct lxc_network phys = {
.type = PHYS,
.netdev = init_list(&phys.netdev),
.netdev = lxc_init_list(&phys.netdev),
};
phylist.elem = &phys;
struct lxc_conf lxc_conf = {
.networks = init_list(&lxc_conf.networks),
.networks = lxc_init_list(&lxc_conf.networks),
.chroot = "/mnt/iso",
};
list_add(&phys.netdev, &ndlist);
lxc_list_add(&phys.netdev, &ndlist);
/* list_add(&lxc_conf.networks, &vethlist); */
/* list_add(&lxc_conf.networks, &mclist); */
list_add(&lxc_conf.networks, &phylist);
lxc_list_add(&lxc_conf.networks, &phylist);
/* list_add(&lxc_conf.networks, &mclist); */
/* list_add(&lxc_conf.networks, &vethlist2); */
......
......@@ -26,7 +26,6 @@
#include <libgen.h>
#include <lxc.h>
#include <state.h>
void usage(char *cmd)
{
......
......@@ -34,9 +34,6 @@
#include <net/if.h>
#include <lxc.h>
#include <state.h>
#include <list.h>
#include <conf.h>
void usage(char *cmd)
{
......
......@@ -26,7 +26,6 @@
#include <libgen.h>
#include <lxc.h>
#include <state.h>
void usage(char *cmd)
{
......
#include <stdio.h>
#include <string.h>
#include <list.h>
#include <lxc_list.h>
int main(int argc, char *argv[])
{
struct list *iterator;
struct list head = init_list(&head);
struct list l1 = init_list(&l1);
struct list l2 = init_list(&l2);
struct list l3 = init_list(&l3);
struct list l4 = init_list(&l4);
struct lxc_list *iterator;
struct lxc_list head = lxc_init_list(&head);
struct lxc_list l1 = lxc_init_list(&l1);
struct lxc_list l2 = lxc_init_list(&l2);
struct lxc_list l3 = lxc_init_list(&l3);
struct lxc_list l4 = lxc_init_list(&l4);
struct dummy {
int a;
......@@ -21,7 +21,7 @@ int main(int argc, char *argv[])
struct dummy d3 = { .a = 3 };
struct dummy d4 = { .a = 4 };
if (!list_empty(&head)) {
if (!lxc_list_empty(&head)) {
fprintf(stderr, "expected empty list\n");
return -1;
}
......@@ -31,33 +31,33 @@ int main(int argc, char *argv[])
l3.elem = &d3;
l4.elem = &d4;
list_add(&head, &l1);
list_add(&head, &l2);
list_add(&head, &l3);
list_add(&head, &l4);
lxc_list_add(&head, &l1);
lxc_list_add(&head, &l2);
lxc_list_add(&head, &l3);
lxc_list_add(&head, &l4);
list_for_each(iterator, &head) {
lxc_list_for_each(iterator, &head) {
elem = iterator->elem;
printf("elem has %d\n", elem->a);
}
list_del(&l3);
lxc_list_del(&l3);
list_for_each(iterator, &head) {
lxc_list_for_each(iterator, &head) {
elem = iterator->elem;
printf("elem has %d\n", elem->a);
}
list_del(&l1);
list_del(&l2);
list_del(&l4);
lxc_list_del(&l1);
lxc_list_del(&l2);
lxc_list_del(&l4);
if (!list_empty(&head)) {
if (!lxc_list_empty(&head)) {
fprintf(stderr, "expected empty list\n");
return -1;
}
list_for_each(iterator, &head) {
lxc_list_for_each(iterator, &head) {
fprintf(stderr, "should not loop\n");
return -1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment