Commit 0ad19a3f by dlezcano

Joined liblxc and lxc directory

parent abfd666c
INCLUDES= -I$(top_srcdir)/src/liblxc -I$(top_srcdir)/src INCLUDES= -I$(top_srcdir)/src
lib_LTLIBRARIES = liblxc.la
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_la_SOURCES = \
create.c \
destroy.c \
start.c \
stop.c \
execute.c \
monitor.c monitor.h \
kill.c \
freezer.c \
lxc_cgroup.c lxc_cgroup.h \
lxc.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
liblxc_la_LDFLAGS = -release @PACKAGE_VERSION@
bin_SCRIPTS = \ bin_SCRIPTS = \
lxc-ps lxc-ps
...@@ -11,56 +49,56 @@ bin_PROGRAMS = \ ...@@ -11,56 +49,56 @@ bin_PROGRAMS = \
lxc-execute \ lxc-execute \
lxc-monitor \ lxc-monitor \
lxc-console \ lxc-console \
lxc-state \
lxc-kill \ lxc-kill \
lxc-freeze \ lxc-freeze \
lxc-info \
lxc-unfreeze \ lxc-unfreeze \
lxc-priority lxc-priority
lxc_create_SOURCES = lxc_create.c lxc_config.c lxc_config.h lxc_create_SOURCES = lxc_create.c lxc_config.c lxc_config.h
lxc_create_LDADD = \ lxc_create_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_destroy_SOURCES = lxc_destroy.c lxc_destroy_SOURCES = lxc_destroy.c
lxc_destroy_LDADD = \ lxc_destroy_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_start_SOURCES = lxc_start.c lxc_start_SOURCES = lxc_start.c
lxc_start_LDADD = \ lxc_start_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_stop_SOURCES = lxc_stop.c lxc_stop_SOURCES = lxc_stop.c
lxc_stop_LDADD = \ lxc_stop_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_execute_SOURCES = lxc_execute.c lxc_execute_SOURCES = lxc_execute.c
lxc_execute_LDADD = \ lxc_execute_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_monitor_SOURCES = lxc_monitor.c lxc_monitor_SOURCES = lxc_monitor.c
lxc_monitor_LDADD = \ lxc_monitor_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_console_SOURCES = lxc_console.c lxc_console_SOURCES = lxc_console.c
lxc_console_LDADD = \ lxc_console_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_state_SOURCES = lxc_state.c lxc_info_SOURCES = lxc_info.c
lxc_state_LDADD = \ lxc_info_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_kill_SOURCES = lxc_kill.c lxc_kill_SOURCES = lxc_kill.c
lxc_kill_LDADD = \ lxc_kill_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_freeze_SOURCES = lxc_freeze.c lxc_freeze_SOURCES = lxc_freeze.c
lxc_freeze_LDADD = \ lxc_freeze_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_unfreeze_SOURCES = lxc_unfreeze.c lxc_unfreeze_SOURCES = lxc_unfreeze.c
lxc_unfreeze_LDADD = \ lxc_unfreeze_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
lxc_priority_SOURCES = lxc_priority.c lxc_priority_SOURCES = lxc_priority.c
lxc_priority_LDADD = \ lxc_priority_LDADD = \
$(top_builddir)/src/liblxc/liblxc.la $(top_builddir)/src/lxc/liblxc.la
/*
* 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 <dirent.h>
#include <unistd.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/inotify.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
static int dir_filter(const struct dirent *dirent)
{
if (!strcmp(dirent->d_name, ".") ||
!strcmp(dirent->d_name, ".."))
return 0;
return 1;
}
static int is_empty_directory(const char *dirname)
{
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 n == 0;
}
static int create_lxc_directory(const char *dirname)
{
char path[MAXPATHLEN];
if (mkdir(LXCPATH, 0755) && errno != EEXIST) {
lxc_log_syserror("failed to created %s directory", LXCPATH);
return -1;
}
sprintf(path, LXCPATH "/%s", dirname);
if (mkdir(path, 0755)) {
lxc_log_syserror("failed to created %s directory", path);
return -1;
}
return 0;
}
static int remove_lxc_directory(const char *dirname)
{
char path[MAXPATHLEN];
sprintf(path, LXCPATH "/%s", dirname);
if (rmdir(path)) {
lxc_log_syserror("failed to remove %s directory", path);
return -1;
}
if (is_empty_directory(LXCPATH)) {
if (rmdir(LXCPATH)) {
lxc_log_syserror("failed to remove %s directory", LXCPATH);
return -1;
}
}
return 0;
}
int lxc_create(const char *name, struct lxc_conf *conf)
{
int lock, err = -1;
if (create_lxc_directory(name)) {
lxc_log_error("failed to create %s directory", name);
return -1;
}
lock = lxc_get_lock(name);
if (!lock) {
lxc_log_error("'%s' is busy", name);
goto err;
}
if (lock < 0) {
lxc_log_error("failed to acquire lock on '%s':%s",
name, strerror(-lock));
goto err;
}
if (lxc_mkstate(name)) {
lxc_log_error("failed to create the state file for %s", name);
goto err;
}
if (lxc_setstate(name, STOPPED)) {
lxc_log_error("failed to set state for %s", name);
goto err_state;
}
if (lxc_configure(name, conf)) {
lxc_log_error("failed to set configuration for %s", name);
goto err_state;
}
err = 0;
out:
lxc_put_lock(lock);
return err;
err_state:
lxc_unconfigure(name);
if (lxc_rmstate(name))
lxc_log_error("failed to remove state file for %s", name);
err:
if (remove_lxc_directory(name))
lxc_log_error("failed to cleanup lxc directory for %s", name);
goto out;
}
/*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/inotify.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
static int dir_filter(const struct dirent *dirent)
{
if (!strcmp(dirent->d_name, ".") ||
!strcmp(dirent->d_name, ".."))
return 0;
return 1;
}
static int is_empty_directory(const char *dirname)
{
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 n == 0;
}
static int remove_lxc_directory(const char *dirname)
{
char path[MAXPATHLEN];
sprintf(path, LXCPATH "/%s", dirname);
if (rmdir(path)) {
lxc_log_syserror("failed to remove %s directory", path);
return -1;
}
if (is_empty_directory(LXCPATH)) {
if (rmdir(LXCPATH)) {
lxc_log_syserror("failed to remove %s directory", LXCPATH);
return -1;
}
}
return 0;
}
int lxc_destroy(const char *name)
{
int ret = -1, lock;
lock = lxc_get_lock(name);
if (!lock) {
lxc_log_error("'%s' is busy", name);
goto out;
}
if (lock < 0) {
lxc_log_error("failed to acquire the lock for '%s':%s",
name, strerror(-lock));
goto out;
}
if (lxc_rmstate(name)) {
lxc_log_error("failed to remove state file for %s", name);
goto out_lock;
}
lxc_monitor_cleanup(name);
if (lxc_unconfigure(name)) {
lxc_log_error("failed to cleanup %s", name);
goto out_lock;
}
if (remove_lxc_directory(name)) {
lxc_log_syserror("failed to remove '%s'", name);
goto out_lock;
}
ret = 0;
out_lock:
lxc_put_lock(lock);
out:
return ret;
}
/*
* 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 <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <sys/mount.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
LXC_TTY_HANDLER(SIGINT);
LXC_TTY_HANDLER(SIGQUIT);
int lxc_execute(const char *name, int argc, char *argv[],
lxc_callback_t preexec, void *data)
{
char *init = NULL, *val = NULL, *vinit = "[vinit]";
int fd, lock, sv[2], sync = 0, err = -1;
pid_t pid;
int clone_flags;
lock = lxc_get_lock(name);
if (!lock) {
lxc_log_error("'%s' is busy", name);
return -1;
}
if (lock < 0) {
lxc_log_error("failed to acquire lock on '%s':%s",
name, strerror(-lock));
return -1;
}
if (lxc_setstate(name, STARTING)) {
lxc_log_error("failed to set state %s", lxc_state2str(STARTING));
goto out;
}
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
lxc_log_syserror("failed to create communication socketpair");
goto err;
}
LXC_TTY_ADD_HANDLER(SIGINT);
LXC_TTY_ADD_HANDLER(SIGQUIT);
clone_flags = CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
if (conf_has_utsname(name))
clone_flags |= CLONE_NEWUTS;
if (conf_has_network(name))
clone_flags |= CLONE_NEWNET;
pid = fork_ns(clone_flags);
if (pid < 0) {
lxc_log_syserror("failed to fork into a new namespace");
goto err_fork_ns;
}
if (!pid) {
pid = fork();
if (pid < 0) {
lxc_log_syserror("failed to fork");
return 1;
}
if (!pid) {
close(sv[1]);
fcntl(sv[0], F_SETFD, FD_CLOEXEC);
if (write(sv[0], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to write socket");
return 1;
}
if (read(sv[0], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to read socket");
return 1;
}
if (lxc_setup(name)) {
lxc_log_error("failed to setup the container");
goto error;
}
if (mount("proc", "/proc", "proc", 0, NULL)) {
lxc_log_syserror("failed to mount '/proc'");
goto error;
}
if (conf_has_network(name))
if (mount("sysfs", "/sys", "sysfs", 0, NULL)) {
lxc_log_syserror("failed to mount '/sys'");
/* continue: non fatal error until sysfs not per
namespace */
}
if (preexec)
if (preexec(name, argc, argv, data)) {
lxc_log_error("preexec callback has failed");
return -1;
}
execvp(argv[0], argv);
lxc_log_syserror("failed to exec %s", argv[0]);
error:
if (write(sv[0], &sync, sizeof(sync)) < 0)
lxc_log_syserror("failed to write the socket");
exit(1);
}
setsid();
close(0);
close(1);
close(2);
if (prctl(PR_SET_NAME, vinit, 0, 0, 0))
lxc_log_syserror("failed to set process name");
close(sv[0]);
close(sv[1]);
for (;;) {
int status;
if (wait(&status) < 0) {
if (errno == ECHILD)
return 0;
if (errno == EINTR)
continue;
lxc_log_syserror("failed to wait child");
return 1;
}
}
}
close(sv[0]);
if (read(sv[1], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to read the socket");
goto err_pipe_read;
}
if (clone_flags & CLONE_NEWNET && conf_create_network(name, pid)) {
lxc_log_error("failed to create the configured network");
goto err_create_network;
}
if (write(sv[1], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to write the socket");
goto err_pipe_write;
}
err = read(sv[1], &sync, sizeof(sync));
if (err < 0) {
lxc_log_error("failed to read the socket");
goto err_pipe_read2;
}
if (err > 0) {
lxc_log_error("something went wrong with %d", pid);
/* TODO : check status etc ... */
waitpid(pid, NULL, 0);
goto err_child_failed;
}
asprintf(&init, LXCPATH "/%s/init", name);
fd = open(init, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (fd < 0) {
lxc_log_syserror("failed to open %s", init);
goto err_open;
}
asprintf(&val, "%d", pid);
if (write(fd, val, strlen(val)) < 0) {
lxc_log_syserror("failed to write init pid");
goto err_write;
}
if (lxc_link_nsgroup(name, pid))
lxc_log_warning("cgroupfs not found: cgroup disabled");
if (lxc_setstate(name, RUNNING)) {
lxc_log_error("failed to set state to %s", lxc_state2str(RUNNING));
goto err_state_failed;
}
wait_again:
if (waitpid(pid, NULL, 0) < 0) {
if (errno == EINTR)
goto wait_again;
lxc_log_syserror("failed to wait the pid %d", pid);
goto err_waitpid_failed;
}
if (lxc_setstate(name, STOPPING))
lxc_log_error("failed to set state %s", lxc_state2str(STOPPING));
if (clone_flags & CLONE_NEWNET && conf_destroy_network(name))
lxc_log_error("failed to destroy the network");
err = 0;
out:
if (lxc_setstate(name, STOPPED))
lxc_log_error("failed to set state %s", lxc_state2str(STOPPED));
lxc_unlink_nsgroup(name);
unlink(init);
free(init);
free(val);
lxc_put_lock(lock);
return err;
err_write:
close(fd);
err_state_failed:
err_child_failed:
err_pipe_read2:
err_pipe_write:
conf_destroy_network(name);
err_create_network:
err_pipe_read:
err_open:
err_waitpid_failed:
if (lxc_setstate(name, ABORTING))
lxc_log_error("failed to set state %s", lxc_state2str(STOPPED));
kill(pid, SIGKILL);
err_fork_ns:
LXC_TTY_DEL_HANDLER(SIGQUIT);
LXC_TTY_DEL_HANDLER(SIGINT);
close(sv[0]);
close(sv[1]);
err:
goto out;
}
/*
* 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 <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>
static int freeze_unfreeze(const char *name, int freeze)
{
char *freezer, *f = freeze?"FROZEN":"RUNNING";
int fd, ret = -1;
asprintf(&freezer, LXCPATH "/%s/nsgroup/freezer.state", name);
fd = open(freezer, O_WRONLY);
if (fd < 0) {
lxc_log_syserror("failed to open freezer for '%s'", name);
goto out;
}
ret = write(fd, f, strlen(f) + 1) < 0;
close(fd);
if (ret)
lxc_log_syserror("failed to write to '%s'", freezer);
out:
free(freezer);
return ret;
}
int lxc_freeze(const char *name)
{
return freeze_unfreeze(name, 1);
}
int lxc_unfreeze(const char *name)
{
return freeze_unfreeze(name, 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
*/
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <linux/genetlink.h>
#include <linux/rtnetlink.h>
#include <nl.h>
#include <genl.h>
static int genetlink_resolve_family(const char *family)
{
struct nl_handler handler;
struct nlattr *attr;
struct genlmsg *request, *reply;
struct genlmsghdr *genlmsghdr;
int len, ret;
request = genlmsg_alloc(GENLMSG_GOOD_SIZE);
if (!request)
return -ENOMEM;
reply = genlmsg_alloc(GENLMSG_GOOD_SIZE);
if (!reply) {
genlmsg_free(request);
return -ENOMEM;
}
request->nlmsghdr.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
request->nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
request->nlmsghdr.nlmsg_type = GENL_ID_CTRL;
genlmsghdr = NLMSG_DATA(&request->nlmsghdr);
genlmsghdr->cmd = CTRL_CMD_GETFAMILY;
ret = netlink_open(&handler, NETLINK_GENERIC);
if (ret)
return ret;
ret = nla_put_string((struct nlmsg *)&request->nlmsghdr,
CTRL_ATTR_FAMILY_NAME, family);
if (ret)
goto out;
ret = netlink_transaction(&handler, (struct nlmsg *)&request->nlmsghdr,
(struct nlmsg *)&reply->nlmsghdr);
if (ret < 0)
goto out;
genlmsghdr = NLMSG_DATA(&reply->nlmsghdr);
len = reply->nlmsghdr.nlmsg_len;
ret = -ENOMSG;
if (reply->nlmsghdr.nlmsg_type != GENL_ID_CTRL)
goto out;
if (genlmsghdr->cmd != CTRL_CMD_NEWFAMILY)
goto out;
ret = -EMSGSIZE;
len -= NLMSG_LENGTH(GENL_HDRLEN);
if (len < 0)
goto out;
attr = (struct nlattr *)GENLMSG_DATA(reply);
attr = (struct nlattr *)((char *)attr + NLA_ALIGN(attr->nla_len));
ret = -ENOMSG;
if (attr->nla_type != CTRL_ATTR_FAMILY_ID)
goto out;
ret = *(__u16 *) NLA_DATA(attr);
out:
genlmsg_free(request);
genlmsg_free(reply);
netlink_close(&handler);
return ret;
}
extern int genetlink_open(struct genl_handler *handler, const char *family)
{
int ret;
handler->family = genetlink_resolve_family(family);
if (handler->family < 0)
return handler->family;
ret = netlink_open(&handler->nlh, NETLINK_GENERIC);
return ret;
}
extern int genetlink_close(struct genl_handler *handler)
{
return netlink_close(&handler->nlh);
}
extern int genetlink_rcv(struct genl_handler *handler, struct genlmsg *genlmsg)
{
return netlink_rcv(&handler->nlh, (struct nlmsg *)&genlmsg->nlmsghdr);
}
extern int genetlink_send(struct genl_handler *handler, struct genlmsg *genlmsg)
{
return netlink_send(&handler->nlh, (struct nlmsg *)&genlmsg->nlmsghdr);
}
extern int genetlink_transaction(struct genl_handler *handler,
struct genlmsg *request, struct genlmsg *answer)
{
return netlink_transaction(&handler->nlh, (struct nlmsg *)&request->nlmsghdr,
(struct nlmsg *)&answer->nlmsghdr);
}
extern struct genlmsg *genlmsg_alloc(size_t size)
{
size_t len = NLMSG_LENGTH(GENL_HDRLEN) + size;
return (struct genlmsg *)nlmsg_alloc(len);
}
extern void genlmsg_free(struct genlmsg *genlmsg)
{
free(genlmsg);
}
/*
* 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 __genl_h
#define __genl_h
/*
* Use this as a good size to allocate generic netlink messages
*/
#define GENLMSG_GOOD_SIZE NLMSG_GOOD_SIZE
#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
/*
* struct genl_handler : the structure which store the netlink handler
* and the family number resulting of the auto-generating id family
* for the generic netlink protocol
*
* @nlh: the netlink socket handler
* @family: the generic netlink family assigned number
*/
struct genl_handler
{
struct nl_handler nlh;
int family;
};
/*
* struct genlmsg : the struct containing the generic netlink message
* format
*
* @nlmsghdr: a netlink message header
* @genlmsghdr: a generic netlink message header pointer
*
*/
/* __attribute__ ((aligned(4))); */
struct genlmsg {
struct nlmsghdr nlmsghdr;
struct genlmsghdr genlmsghdr;
};
static inline int genetlink_len(const struct genlmsg *genlmsg)
{
return ((genlmsg->nlmsghdr.nlmsg_len) - GENL_HDRLEN - NLMSG_HDRLEN);
}
/*
* genetlink_open : resolve family number id and open a generic netlink socket
*
* @handler: a struct genl_handler pointer
* @family: the family name of the generic netlink protocol
*
* Returns 0 on success, < 0 otherwise
*/
int genetlink_open(struct genl_handler *handler, const char *family);
/*
* genetlink_close : close a generic netlink socket
*
* @handler: the handler of the socket to be closed
*
* Returns 0 on success, < 0 otherwise
*/
int genetlink_close(struct genl_handler *handler);
/*
* genetlink_rcv : receive a generic netlink socket, it is up
* to the caller to manage the allocation of the generic netlink message
*
* @handler: the handler of the generic netlink socket
* @genlmsg: the pointer to a generic netlink message pre-allocated
*
* Returns 0 on success, < 0 otherwise
*/
int genetlink_rcv(struct genl_handler *handler, struct genlmsg *genlmsg);
/*
* genetlink_send : send a generic netlink socket, it is up
* to the caller to manage the allocation of the generic netlink message
*
* @handler: the handler of the generic netlink socket
* @genlmsg: the pointer to a generic netlink message pre-allocated
*
* Returns 0 on success, < 0 otherwise
*/
int genetlink_send(struct genl_handler *handler, struct genlmsg *genlmsg);
struct genlmsg *genlmsg_alloc(size_t size);
void genlmsg_free(struct genlmsg *genlmsg);
/*
* genetlink_transaction : send and receive a generic netlink message in one shot
*
* @handler: the handler of the generic netlink socket
* @request: a generic netlink message containing the request to be sent
* @answer: a pre-allocated generic netlink message to receive the response
*
* Returns 0 on success, < 0 otherwise
*/
int genetlink_transaction(struct genl_handler *handler,
struct genlmsg *request, struct genlmsg *answer);
#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 <unistd.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
int lxc_kill(const char *name, int signum)
{
char *freezer = NULL, *signal = NULL;
int fd = -1, ret = -1;
if (signum < SIGHUP || signum > SIGRTMAX) {
lxc_log_error("bad signal value %d", signum);
goto out;
}
asprintf(&freezer, LXCPATH "/%s/nsgroup/freezer.kill", name);
asprintf(&signal, "%d", signum);
fd = open(freezer, O_WRONLY);
if (fd < 0) {
lxc_log_syserror("failed to open %s for %s", freezer, name);
goto out;
}
if (write(fd, &signal, strlen(signal)) < 0) {
lxc_log_syserror("failed to write to %s", freezer);
goto out;
}
ret = 0;
out:
close(fd);
free(freezer);
free(signal);
return ret;
}
/*
* 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 list {
void *elem;
struct list *next;
struct list *prev;
};
#define init_list(l) { .next = l, .prev = l, }
#define list_for_each(__iterator, __list) \
for (__iterator = (__list)->next; \
__iterator != __list; \
__iterator = __iterator->next)
static inline void list_init(struct list *list)
{
list->elem = NULL;
list->next = list->prev = list;
}
static inline void list_add_elem(struct list *list, void *elem)
{
list->elem = elem;
}
static inline void *list_first_elem(struct list *list)
{
return list->next->elem;
}
static inline int list_empty(struct list *list)
{
return list == list->next;
}
static inline void list_add(struct list *list, struct list *new)
{
struct list *next = list->next;
next->prev = new;
new->next = next;
new->prev = list;
list->next = new;
}
static inline void list_del(struct list *list)
{
struct 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
*/
#ifndef __lxc_h
#define __lxc_h
#ifdef __cplusplus
extern "C" {
#endif
/**
Following code is for liblxc.
liblxc/lxc.h will contain exports of liblxc
**/
#include <lxc/lxc_state.h>
#include <lxc/lxc_list.h>
#include <lxc/lxc_conf.h>
#include <lxc/lxc_log.h>
#include <lxc/lxc_lock.h>
#include <lxc/lxc_cgroup.h>
#include <lxc/lxc_namespace.h>
#include <lxc/lxc_utils.h>
#define LXCPATH "/var/lxc"
#define MAXPIDLEN 20
struct lxc_mem_stat;
typedef int (*lxc_callback_t)(const char *name, int argc,
char *argv[], void *data);
/*
* Create the container object. Creates the /lxc/<name> directory
* and fills it with the files corresponding to the configuration
* structure passed as parameter.
* The first container will create the /lxc directory.
* @name : the name of the container
* @conf : the configuration data for the container
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_create(const char *name, struct lxc_conf *conf);
/*
* Destroy the container object. Removes the files into the /lxc/<name>
* directory and removes the <name> directory.
* The last container will remove the /lxc directory.
* @name : the name of the container to be detroyed
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_destroy(const char *name);
/*
* Start the container previously created with lxc_create.
* @name : the name of the container
* @argc : the number of arguments of the command line
* @argv : an array of char * corresponding to the commande line
* @prestart : hooks will be called just before the command execs
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_start(const char *name, int argc, char *argv[],
lxc_callback_t prestart, void *data);
/*
* Create the container and start it directly, using the argc, argv
* parameter. This command is for application container.
* At the end of the exec'ed command, the container will
* automatically autodestroy.
* @name : the name of the container
* @conf : the configuration data
* @argc : the number of arguments of the command line
* @argv : an array of char * corresponding to the commande line
* @preexec : hooks will be called just before the command execs
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_execute(const char *name, int argc, char *argv[],
lxc_callback_t preexec, void *data);
/*
* Stop the container previously started with lxc_start or lxc_exec
* @name : the name of the container
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_stop(const char *name);
/*
* Monitor the container, each time the state of the container
* is changed, a state data is send through a file descriptor passed to
* the function with output_fd.
* The function will block until the container is destroyed.
* @name : the name of the container
* @output_fd : the file descriptor where to send the states
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_monitor(const char *name, int output_fd);
/*
* Open the monitoring mechanism for a specific container
* The function will return an fd corresponding to the events
* @name : the name of the container
* Returns a file descriptor on success, < 0 otherwise
*/
extern int lxc_monitor_open(const char *name);
/*
* Read the state of the container if this one has changed
* The function will block until there is an event available
* @fd : the file descriptor provided by lxc_monitor_open
* @state : the variable which will be filled with the state
* Returns 0 if the monitored container has exited, > 0 if
* data was readen, < 0 otherwise
*/
extern int lxc_monitor_read(int fd, lxc_state_t *state);
/*
* Close the fd associated with the monitoring
* @fd : the file descriptor provided by lxc_monitor_open
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_monitor_close(int fd);
/*
* Show the console of the container.
* @name : the name of container
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_console(const char *name);
/*
* Freeze all the tasks running inside the container <name>
* @name : the container name
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_freeze(const char *name);
/*
* Unfreeze all previously frozen tasks.
* @name : the name of the container
* Return 0 on sucess, < 0 otherwise
*/
extern int lxc_unfreeze(const char *name);
/*
* Retrieve the container state
* @name : the name of the container
* Returns the state of the container on success, < 0 otherwise
*/
extern lxc_state_t lxc_state(const char *name);
/*
* Send a signal to all processes of the container. This is the same
* behavior of the well-known 'killpg' command except it is related
* to all tasks belonging to a container.
* @name : the name of the container
* @signum : the signal number to be sent
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_kill(const char *name, int signum);
/*
* Change the priority of the container
* @name : the name of the container
* @priority : an integer representing the desired priority
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_cgroup_set_priority(const char *name, int priority);
/*
* Retrieve the priority of the container
* @name : the name of the container
* @priority : a pointer to an int where the priority will be stored
* Returns 0 on success, < 0 otherwise
*/
extern int lxc_cgroup_get_priority(const char *name, int *priority);
/*
* Set the maximum memory usable by the container
* @name : the name of the container
* @memmax : the maximum usable memory in bytes
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_cgroup_set_memory(const char *name, size_t memmax);
/*
* Get the maximum memory usable by the container
* @name : the name of the container
* @memmax : a pointer to a size_t where the value will be stored
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_cgroup_get_memory(const char *name, size_t *memmax);
/*
* Get the memory statistics of the container
* @name : the name of the container
* @memstat : a pointer to a structure defining the memory statistic
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_cgroup_get_memstat(const char *name,
struct lxc_mem_stat *memstat);
/*
* Set the cpuset for the container
* @name : the name of the container
* @cpumask : a bitmask representing the cpu maps
* @len : the len of the bitmask
* @shared : a boolean specifying if the cpu could be shared with
* processes not belonging to the container
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_cgroup_set_cpuset(const char *name, long *cpumask,
int len, int shared);
/*
* Get the actual cpuset for the container
* @cpumask : a bitmask representing the cpu maps
* @len : the len of the bitmask
* @shared : a boolean specifying if the cpu is shared with
* processes not belonging to the container
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_cgroup_get_cpuset(const char *name, long *cpumask,
int len, int *shared);
/*
* Get the cpu usage of the container
* @name : the name of the container
* @usage : a value to be filled with the current container cpu usage
* Returns 0 on sucess, < 0 otherwise
*/
extern int lxc_cgroup_get_cpu_usage(const char *name, long long *usage);
#ifdef __cplusplus
}
#endif
#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 <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_type, "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_cgroup_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_cgroup_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 ret;
}
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
*/
#ifndef _conf_h
#define _conf_h
#include <netinet/in.h>
enum {
EMPTY,
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 <stdio.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/types.h>
#include <lxc.h>
void usage(char *cmd)
{
fprintf(stderr, "%s <command>\n", basename(cmd));
fprintf(stderr, "\t -n <name> : name of the container\n");
_exit(1);
}
int main(int argc, char *argv[])
{
char opt;
char *name = NULL;
int state, nbargs = 0;
while ((opt = getopt(argc, argv, "n:")) != -1) {
switch (opt) {
case 'n':
name = optarg;
break;
}
nbargs++;
}
if (!name)
usage(argv[0]);
state = lxc_getstate(name);
if (state < 0) {
fprintf(stderr, "failed to freeze '%s'\n", name);
return 1;
}
printf("'%s' is %s\n", name, lxc_state2str(state));
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
*/
#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 *head, struct lxc_list *list)
{
struct lxc_list *next = head->next;
next->prev = list;
list->next = next;
list->prev = head;
head->next = list;
}
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;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
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, "[syserr] \t%s:%d: %s - " format "\n", \
__FUNCTION__, __LINE__, strerror(errno), \
##__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
...@@ -21,46 +21,172 @@ ...@@ -21,46 +21,172 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <libgen.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <lxc.h> #include <lxc.h>
#include "monitor.h"
static char *strstate[] = {
"STOPPED", "STARTING", "RUNNING", "STOPPING",
"ABORTING", "FREEZING", "FROZEN",
};
const char *lxc_state2str(lxc_state_t state)
{
if (state < STOPPED || state > MAX_STATE - 1)
return NULL;
return strstate[state];
}
void usage(char *cmd) lxc_state_t lxc_str2state(const char *state)
{ {
fprintf(stderr, "%s <command>\n", basename(cmd)); int i, len;
fprintf(stderr, "\t -n <name> : name of the container\n"); len = sizeof(strstate)/sizeof(strstate[0]);
_exit(1); for (i = 0; i < len; i++)
if (!strcmp(strstate[i], state))
return i;
return -1;
} }
int main(int argc, char *argv[]) int lxc_setstate(const char *name, lxc_state_t state)
{ {
char opt; int fd, err;
char *name = NULL; char file[MAXPATHLEN];
int state, nbargs = 0; const char *str = lxc_state2str(state);
while ((opt = getopt(argc, argv, "n:")) != -1) { if (!str)
switch (opt) { return -1;
case 'n':
name = optarg; snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name);
break;
} fd = open(file, O_WRONLY);
if (fd < 0) {
nbargs++; lxc_log_syserror("failed to open %s file", file);
return -1;
} }
if (!name) if (flock(fd, LOCK_EX)) {
usage(argv[0]); 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;
}
state = lxc_getstate(name); if (write(fd, str, strlen(str)) < 0) {
if (state < 0) { lxc_log_syserror("failed to write state to %s", file);
fprintf(stderr, "failed to freeze '%s'\n", name); goto out;
return 1;
} }
printf("'%s' is %s\n", name, lxc_state2str(state)); err = 0;
out:
close(fd);
lxc_monitor_send_state(name, state);
/* 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 lxc_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 lxc_rmstate(const char *name)
{
char file[MAXPATHLEN];
snprintf(file, MAXPATHLEN, LXCPATH "/%s/state", name);
unlink(file);
return 0; 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 lxc_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)
return -1;
err = fscanf(file, "%s", status);
fclose(file);
if (err == EOF) {
lxc_log_syserror("failed to read %s", freezer);
return -1;
}
return lxc_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 int lxc_mkstate(const char *name);
extern int lxc_rmstate(const char *name);
extern int lxc_setstate(const char *name, lxc_state_t state);
extern lxc_state_t lxc_getstate(const char *name);
extern lxc_state_t lxc_str2state(const char *state);
extern const char *lxc_state2str(lxc_state_t state);
#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
/*
* 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 <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/inotify.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif
int lxc_monitor(const char *name, int output_fd)
{
char path[MAXPATHLEN];
int err = -1, nfd, wfd, state;
nfd = inotify_init();
if (nfd < 0) {
lxc_log_syserror("failed to initialize inotify");
return -1;
}
snprintf(path, MAXPATHLEN, LXCPATH "/%s/state", name);
wfd = inotify_add_watch(nfd, path, IN_DELETE_SELF|IN_CLOSE_WRITE);
if (wfd < 0) {
lxc_log_syserror("failed to add a watch on %s", path);
goto out;
}
for(;;) {
struct inotify_event evt;
if (read(nfd, &evt, sizeof(evt)) < 0) {
lxc_log_syserror("failed to read inotify event");
goto out;
}
if (evt.mask & IN_CLOSE_WRITE) {
state = lxc_getstate(name);
if (state < 0) {
lxc_log_error("failed to get the state for %s",
name);
goto out;
}
if (write(output_fd, &state, sizeof(state)) < 0) {
lxc_log_syserror("failed to send state to %d",
output_fd);
goto out;
}
continue;
}
if (evt.mask & IN_DELETE_SELF) {
close(output_fd);
err = 0;
goto out;
}
lxc_log_error("unknown evt for inotity (%d)", evt.mask);
goto out;
}
out:
inotify_rm_watch(nfd, wfd);
close(nfd);
return err;
}
void lxc_monitor_send_state(const char *name, lxc_state_t state)
{
int fd;
struct sockaddr_un addr;
fd = socket(PF_UNIX, SOCK_DGRAM, 0);
if (fd < 0)
lxc_log_syserror("failed to create notification socket");
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name);
sendto(fd, &state, sizeof(state), 0,
(const struct sockaddr *)&addr, sizeof(addr));
close(fd);
}
void lxc_monitor_cleanup(const char *name)
{
char path[UNIX_PATH_MAX];
snprintf(path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name);
unlink(path);
}
int lxc_monitor_open(const char *name)
{
int fd;
struct sockaddr_un addr;
fd = socket(PF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
lxc_log_syserror("failed to create notification socket");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, UNIX_PATH_MAX, LXCPATH "/%s/notification", name);
unlink(addr.sun_path);
if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr))) {
lxc_log_syserror("failed to bind to '%s'", addr.sun_path);
close(fd);
return -1;
}
return fd;
}
int lxc_monitor_read(int fd, lxc_state_t *state)
{
int ret;
ret = recv(fd, state, sizeof(*state), 0);
if (ret < 0) {
lxc_log_syserror("failed to received state");
return -1;
}
return ret;
}
int lxc_monitor_close(int fd)
{
return close(fd);
}
/*
* 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 __monitor_h
#define __monitor_h
void lxc_monitor_send_state(const char *name, lxc_state_t state);
void lxc_monitor_cleanup(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 __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
*/
#ifndef _network_h
#define _network_h
/*
* Create a macvlan network device
*/
extern int lxc_configure_macvlan(const char *link, const char *peer);
/*
* Create a veth pair virtual device
*/
extern int lxc_configure_veth(const char *veth1, const char *veth2,
const char *bridge);
/*
* Convert a string mac address to a socket structure
*/
extern int lxc_convert_mac(char *macaddr, struct sockaddr *sockaddr);
/*
* Move a device between namespaces
*/
extern int device_move(const char *name, pid_t pid);
/*
* Delete a network device
*/
extern int device_delete(const char *name);
/*
* Set the device network up
*/
extern int device_up(const char *name);
/*
* Set the device network down
*/
extern int device_down(const char *name);
/*
* Change the device name
*/
extern int device_rename(const char *oldname, const char *newname);
/*
* Create a veth network device
*/
extern int veth_create(const char *name1, const char *name2);
/*
* Create a macvlan network device
*/
extern int macvlan_create(const char *master, const char *name);
/*
* Activate forwarding
*/
extern int ip_forward_on(const char *name, int family);
/*
* Disable forwarding
*/
extern int ip_forward_off(const char *name, int family);
/*
* Set ip address
*/
extern int ip_addr_add(const char *ifname, const char *addr,
int prefix, const char *bcast);
extern int ip6_addr_add(const char *ifname, const char *addr,
int prefix, const char *bcast);
/*
* Attach an interface to the bridge
*/
extern int bridge_attach(const char *bridge, const char *ifname);
/*
* Detach an interface from the bridge
*/
extern int bridge_detach(const char *bridge, const char *ifname);
/*
* Create default gateway
*/
extern int route_create_default(const char *addr, const char *ifname, int gateway);
/*
* Delete default gateway
*/
extern int route_delete_default(const char *addr, const char *ifname, int gateway);
/*
* Activate neighbor proxying
*/
extern int neigh_proxy_on(const char *name, int family);
/*
* Disable neighbor proxying
*/
extern int neigh_proxy_off(const char *name, int family);
#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 <sys/socket.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <nl.h>
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
extern size_t nlmsg_len(const struct nlmsg *nlmsg)
{
return nlmsg->nlmsghdr.nlmsg_len - NLMSG_HDRLEN;
}
extern void *nlmsg_data(struct nlmsg *nlmsg)
{
char *data = ((char *)nlmsg) + NLMSG_ALIGN(sizeof(struct nlmsghdr));
if (!nlmsg_len(nlmsg))
return NULL;
return data;
}
static int nla_put(struct nlmsg *nlmsg, int attr,
const void *data, size_t len)
{
struct rtattr *rta;
size_t rtalen = RTA_LENGTH(len);
rta = NLMSG_TAIL(&nlmsg->nlmsghdr);
rta->rta_type = attr;
rta->rta_len = rtalen;
memcpy(RTA_DATA(rta), data, len);
nlmsg->nlmsghdr.nlmsg_len =
NLMSG_ALIGN(nlmsg->nlmsghdr.nlmsg_len) + RTA_ALIGN(rtalen);
return 0;
}
extern int nla_put_buffer(struct nlmsg *nlmsg, int attr,
const void *data, size_t size)
{
return nla_put(nlmsg, attr, data, size);
}
extern int nla_put_string(struct nlmsg *nlmsg, int attr, const char *string)
{
return nla_put(nlmsg, attr, string, strlen(string) + 1);
}
extern int nla_put_u32(struct nlmsg *nlmsg, int attr, int value)
{
return nla_put(nlmsg, attr, &value, sizeof(value));
}
extern int nla_put_attr(struct nlmsg *nlmsg, int attr)
{
return nla_put(nlmsg, attr, NULL, 0);
}
struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr)
{
struct rtattr *rtattr = NLMSG_TAIL(&nlmsg->nlmsghdr);
if (nla_put_attr(nlmsg, attr))
return NULL;
return rtattr;
}
void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr)
{
attr->rta_len = (void *)NLMSG_TAIL(&nlmsg->nlmsghdr) - (void *)attr;
}
extern struct nlmsg *nlmsg_alloc(size_t size)
{
struct nlmsg *nlmsg;
size_t len = NLMSG_ALIGN(size) + NLMSG_ALIGN(sizeof(struct nlmsghdr *));
nlmsg = (struct nlmsg *)malloc(len);
if (!nlmsg)
return NULL;
memset(nlmsg, 0, len);
nlmsg->nlmsghdr.nlmsg_len = NLMSG_ALIGN(size);
return nlmsg;
}
extern void nlmsg_free(struct nlmsg *nlmsg)
{
free(nlmsg);
}
extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer)
{
int ret;
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = answer,
.iov_len = answer->nlmsghdr.nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
again:
ret = recvmsg(handler->fd, &msg, 0);
if (ret < 0) {
if (errno == EINTR)
goto again;
return -errno;
}
if (!ret)
return 0;
if (msg.msg_flags & MSG_TRUNC)
return -EMSGSIZE;
return ret;
}
extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg)
{
struct sockaddr_nl nladdr;
struct iovec iov = {
.iov_base = (void*)nlmsg,
.iov_len = nlmsg->nlmsghdr.nlmsg_len,
};
struct msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
int ret;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
nladdr.nl_pid = 0;
nladdr.nl_groups = 0;
ret = sendmsg(handler->fd, &msg, 0);
if (ret < 0) {
return -errno;
}
return ret;
}
extern int netlink_transaction(struct nl_handler *handler,
struct nlmsg *request, struct nlmsg *answer)
{
int ret;
ret = netlink_send(handler, request);
if (ret < 0)
return ret;
ret = netlink_rcv(handler, answer);
if (ret < 0)
return ret;
if (answer->nlmsghdr.nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer);
errno = -err->error;
return -errno;
}
return 0;
}
extern int netlink_open(struct nl_handler *handler, int protocol)
{
socklen_t socklen;
int sndbuf = 32768;
int rcvbuf = 32768;
memset(handler, 0, sizeof(*handler));
handler->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
if (handler->fd < 0)
return -errno;
if (setsockopt(handler->fd, SOL_SOCKET, SO_SNDBUF,
&sndbuf, sizeof(sndbuf)) < 0)
return -errno;
if (setsockopt(handler->fd, SOL_SOCKET, SO_RCVBUF,
&rcvbuf,sizeof(rcvbuf)) < 0)
return -errno;
memset(&handler->local, 0, sizeof(handler->local));
handler->local.nl_family = AF_NETLINK;
handler->local.nl_groups = 0;
if (bind(handler->fd, (struct sockaddr*)&handler->local,
sizeof(handler->local)) < 0)
return -errno;
socklen = sizeof(handler->local);
if (getsockname(handler->fd, (struct sockaddr*)&handler->local,
&socklen) < 0)
return -errno;
if (socklen != sizeof(handler->local))
return -EINVAL;
if (handler->local.nl_family != AF_NETLINK)
return -EINVAL;
handler->seq = time(NULL);
return 0;
}
extern int netlink_close(struct nl_handler *handler)
{
close(handler->fd);
handler->fd = -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 __nl_h
#define __nl_h
/*
* Use this as a good size to allocate generic netlink messages
*/
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#define NLMSG_GOOD_SIZE (2*PAGE_SIZE)
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
#define NLA_NEXT_ATTR(attr) ((void *)((char *)attr) + NLA_ALIGN(attr->nla_len))
/*
* struct nl_handler : the handler for netlink sockets, this structure
* is used all along the netlink socket life cycle to specify the
* netlink socket to be used.
*
* @fd: the file descriptor of the netlink socket
* @seq: the sequence number of the netlink messages
* @local: the bind address
* @peer: the peer address
*/
struct nl_handler {
int fd;
int seq;
struct sockaddr_nl local;
struct sockaddr_nl peer;
};
/*
* struct nlmsg : the netlink message structure, it consists just
* on a definition for a nlmsghdr. This message is to be used to
* be allocated with netlink_alloc.
* @nlmsghdr : a pointer to a netlink message header, this field
* _must_ be always the first field of this structure
*/
struct nlmsg {
struct nlmsghdr nlmsghdr;
};
/*
* netlink_open : open a netlink socket, the function will
* fill the handler with the right value
*
* @handler: a netlink handler to be used all along the netlink
* socket life cycle
* @protocol: specify the protocol to be used when opening the
* netlink socket
*
* Return 0 on success, < 0 otherwise
*/
int netlink_open(struct nl_handler *handler, int protocol);
/*
* netlink_close : close a netlink socket, after this call,
* the handler is no longer valid
*
* @handler: a handler to the netlink socket
*
* Returns 0 on success, < 0 otherwise
*/
int netlink_close(struct nl_handler *handler);
/*
* netlink_rcv : receive a netlink message from the kernel.
* It is up to the caller to manage the allocation of the
* netlink message
*
* @handler: a handler to the netlink socket
* @nlmsg: a netlink message
*
* Returns 0 on success, < 0 otherwise
*/
int netlink_rcv(struct nl_handler *handler, struct nlmsg *nlmsg);
/*
* netlink_send: send a netlink message to the kernel. It is up
* to the caller to manage the allocate of the netlink message
*
* @handler: a handler to the netlink socket
* @nlmsg: a netlink message
*
* Returns 0 on success, < 0 otherwise
*/
int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg);
/*
* netlink_transaction: send a request to the kernel and read the response.
* This is useful for transactional protocol. It is up to the caller
* to manage the allocation of the netlink message.
*
* @handler: a handler to a opened netlink socket
* @request: a netlink message pointer containing the request
* @answer: a netlink message pointer to receive the result
*
* Returns 0 on success, < 0 otherwise
*/
int netlink_transaction(struct nl_handler *handler,
struct nlmsg *request, struct nlmsg *anwser);
/*
* nla_put_string: copy a null terminated string to a netlink message
* attribute
*
* @nlmsg: the netlink message to be filled
* @attr: the attribute name of the string
* @string: a null terminated string to be copied to the netlink message
*
* Returns 0 on success, < 0 otherwise
*/
int nla_put_string(struct nlmsg *nlmsg, int attr, const char *string);
/*
* nla_put_buffer: copy a buffer with a specified size to a netlink
* message attribute
*
* @nlmsg: the netlink message to be filled
* @attr: the attribute name of the string
* @data: a pointer to a buffer
* @size: the size of the buffer
*
* Returns 0 on success, < 0 otherwise
*/
int nla_put_buffer(struct nlmsg *nlmsg, int attr,
const void *data, size_t size);
/*
* nla_put_u32: copy an integer to a netlink message attribute
*
* @nlmsg: the netlink message to be filled
* @attr: the attribute name of the integer
* @string: an integer to be copied to the netlink message
*
* Returns 0 on success, < 0 otherwise
*/
int nla_put_u32(struct nlmsg *nlmsg, int attr, int value);
/*
* nla_put_attr: add an attribute name to a netlink
*
* @nlmsg: the netlink message to be filled
* @attr: the attribute name of the integer
*
* Returns 0 on success, < 0 otherwise
*/
int nla_put_attr(struct nlmsg *nlmsg, int attr);
/*
* nla_begin_nested: begin the nesting attribute
*
* @nlmsg: the netlink message to be filled
* @attr: the netsted attribute name
*
* Returns current nested pointer to be reused
* to nla_end_nested.
*/
struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr);
/*
* nla_end_nested: end the nesting attribute
*
* @nlmsg: the netlink message
* @nested: the nested pointer
*
* Returns the current
*/
void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr);
/*
* nlmsg_allocate : allocate a netlink message. The netlink format message
* is a header, a padding, a payload and a padding again.
* When a netlink message is allocated, the size specify the
* payload we want. So the real size of the allocated message
* is sizeof(header) + sizeof(padding) + payloadsize + sizeof(padding),
* in other words, the function will allocate more than specified. When
* the buffer is allocated, the content is zeroed.
* The function will also fill the field nlmsg_len with computed size.
* If the allocation must be for the specified size, just use malloc.
*
* @size: the size of the payload to be allocated
*
* Returns a pointer to the newly allocated netlink message, NULL otherwise
*/
struct nlmsg *nlmsg_alloc(size_t size);
/*
* nlmsg_free : free a previously allocate message
*
* @nlmsg: the netlink message to be freed
*/
void nlmsg_free(struct nlmsg *nlmsg);
/*
* nlmsg_data : returns a pointer to the data contained in the netlink message
*
* @nlmsg : the netlink message to get the data
*
* Returns a pointer to the netlink data or NULL if there is no data
*/
void *nlmsg_data(struct nlmsg *nlmsg);
#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 <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <nl.h>
#include <rtnl.h>
extern int rtnetlink_open(struct rtnl_handler *handler)
{
return netlink_open(&handler->nlh, NETLINK_ROUTE);
}
extern int rtnetlink_close(struct rtnl_handler *handler)
{
return netlink_close(&handler->nlh);
}
extern int rtnetlink_rcv(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg)
{
return netlink_rcv(&handler->nlh, (struct nlmsg *)&rtnlmsg->nlmsghdr);
}
extern int rtnetlink_send(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg)
{
return netlink_send(&handler->nlh, (struct nlmsg *)&rtnlmsg->nlmsghdr);
}
extern int rtnetlink_transaction(struct rtnl_handler *handler,
struct rtnlmsg *request, struct rtnlmsg *answer)
{
return netlink_transaction(&handler->nlh, (struct nlmsg *)&request->nlmsghdr,
(struct nlmsg *)&answer->nlmsghdr);
}
extern struct rtnlmsg *rtnlmsg_alloc(size_t size)
{
/* size_t len = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct rtnlmsghdr))) + size; */
/* return (struct rtnlmsg *)nlmsg_alloc(len); */
return NULL;
}
extern void rtnlmsg_free(struct rtnlmsg *rtnlmsg)
{
free(rtnlmsg);
}
/*
* 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 __genl_h
#define __genl_h
/*
* Use this as a good size to allocate route netlink messages
*/
#define RTNLMSG_GOOD_SIZE NLMSG_GOOD_SIZE
#define RTNLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + RTNL_HDRLEN))
/*
* struct genl_handler : the structure which store the netlink handler
* and the family number
*
* @nlh: the netlink socket handler
*/
struct rtnl_handler
{
struct nl_handler nlh;
};
/*
* struct rtnlmsg : the struct containing the route netlink message
* format
*
* @nlmsghdr: a netlink message header
* @rtnlmsghdr: a route netlink message header pointer
*
*/
struct rtnlmsg {
struct nlmsghdr nlmsghdr;
};
/*
* rtnetlink_open : open a route netlink socket
*
* @handler: a struct rtnl_handler pointer
*
* Returns 0 on success, < 0 otherwise
*/
int rtnetlink_open(struct rtnl_handler *handler);
/*
* genetlink_close : close a route netlink socket
*
* @handler: the handler of the socket to be closed
*
* Returns 0 on success, < 0 otherwise
*/
int rtnetlink_close(struct rtnl_handler *handler);
/*
* rtnetlink_rcv : receive a route netlink socket, it is up
* to the caller to manage the allocation of the route netlink message
*
* @handler: the handler of the route netlink socket
* @rtnlmsg: the pointer to a route netlink message pre-allocated
*
* Returns 0 on success, < 0 otherwise
*/
int rtnetlink_rcv(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg);
/*
* rtnetlink_send : send a route netlink socket, it is up
* to the caller to manage the allocation of the route netlink message
*
* @handler: the handler of the route netlink socket
* @rtnlmsg: the pointer to a netlink message pre-allocated
*
* Returns 0 on success, < 0 otherwise
*/
int rtnetlink_send(struct rtnl_handler *handler, struct rtnlmsg *rtnlmsg);
struct genlmsg *genlmsg_alloc(size_t size);
void rtnlmsg_free(struct rtnlmsg *rtnlmsg);
/*
* rtnetlink_transaction : send and receive a route netlink message in one shot
*
* @handler: the handler of the route netlink socket
* @request: a route netlink message containing the request to be sent
* @answer: a pre-allocated route netlink message to receive the response
*
* Returns 0 on success, < 0 otherwise
*/
int rtnetlink_transaction(struct rtnl_handler *handler,
struct rtnlmsg *request, struct rtnlmsg *answer);
#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 <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <mntent.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
LXC_TTY_HANDLER(SIGINT);
LXC_TTY_HANDLER(SIGQUIT);
int lxc_start(const char *name, int argc, char *argv[],
lxc_callback_t prestart, void *data)
{
char *init = NULL, *val = NULL;
int fd, lock, sv[2], sync = 0, err = -1;
pid_t pid;
int clone_flags;
lock = lxc_get_lock(name);
if (!lock) {
lxc_log_error("'%s' is busy", name);
return -1;
}
if (lock < 0) {
lxc_log_error("failed to acquire lock on '%s':%s",
name, strerror(-lock));
return -1;
}
fcntl(lock, F_SETFD, FD_CLOEXEC);
/* Begin the set the state to STARTING*/
if (lxc_setstate(name, STARTING)) {
lxc_log_error("failed to set state %s", lxc_state2str(STARTING));
goto out;
}
/* Synchro socketpair */
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
lxc_log_syserror("failed to create communication socketpair");
goto err;
}
/* Avoid signals from terminal */
LXC_TTY_ADD_HANDLER(SIGINT);
LXC_TTY_ADD_HANDLER(SIGQUIT);
clone_flags = CLONE_NEWPID|CLONE_NEWIPC;
if (conf_has_fstab(name))
clone_flags |= CLONE_NEWNS;
if (conf_has_utsname(name))
clone_flags |= CLONE_NEWUTS;
if (conf_has_network(name))
clone_flags |= CLONE_NEWNET;
/* Create a process in a new set of namespaces */
pid = fork_ns(clone_flags);
if (pid < 0) {
lxc_log_syserror("failed to fork into a new namespace");
goto err_fork_ns;
}
if (!pid) {
close(sv[1]);
/* Be sure we don't inherit this after the exec */
fcntl(sv[0], F_SETFD, FD_CLOEXEC);
/* Tell our father he can begin to configure the container */
if (write(sv[0], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to write socket");
return 1;
}
/* Wait for the father to finish the configuration */
if (read(sv[0], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to read socket");
return 1;
}
/* Setup the container, ip, names, utsname, ... */
if (lxc_setup(name)) {
lxc_log_error("failed to setup the container");
if (write(sv[0], &sync, sizeof(sync)) < 0)
lxc_log_syserror("failed to write the socket");
return -1;
}
/* If a callback has been passed, call it before doing exec */
if (prestart)
if (prestart(name, argc, argv, data)) {
lxc_log_error("prestart callback has failed");
return -1;
}
execvp(argv[0], argv);
lxc_log_syserror("failed to exec %s", argv[0]);
/* If the exec fails, tell that to our father */
if (write(sv[0], &sync, sizeof(sync)) < 0)
lxc_log_syserror("failed to write the socket");
exit(1);
}
close(sv[0]);
/* Wait for the child to be ready */
if (read(sv[1], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to read the socket");
goto err_pipe_read;
}
/* Create the network configuration */
if (clone_flags & CLONE_NEWNET && conf_create_network(name, pid)) {
lxc_log_error("failed to create the configured network");
goto err_create_network;
}
/* Tell the child to continue its initialization */
if (write(sv[1], &sync, sizeof(sync)) < 0) {
lxc_log_syserror("failed to write the socket");
goto err_pipe_write;
}
/* Wait for the child to exec or returning an error */
err = read(sv[1], &sync, sizeof(sync));
if (err < 0) {
lxc_log_error("failed to read the socket");
goto err_pipe_read2;
}
if (err > 0) {
lxc_log_error("something went wrong with %d", pid);
/* TODO : check status etc ... */
waitpid(pid, NULL, 0);
goto err_child_failed;
}
asprintf(&val, "%d\n", pid);
asprintf(&init, LXCPATH "/%s/init", name);
fd = open(init, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (fd < 0) {
lxc_log_syserror("failed to open '%s'", init);
goto err_write;
}
if (write(fd, val, strlen(val)) < 0) {
lxc_log_syserror("failed to write the init pid");
goto err_write;
}
close(fd);
if (lxc_link_nsgroup(name, pid))
lxc_log_warning("cgroupfs not found: cgroup disabled");
if (lxc_setstate(name, RUNNING)) {
lxc_log_error("failed to set state to %s",
lxc_state2str(RUNNING));
goto err_state_failed;
}
wait_again:
if (waitpid(pid, NULL, 0) < 0) {
if (errno == EINTR)
goto wait_again;
lxc_log_syserror("failed to wait the pid %d", pid);
goto err_waitpid_failed;
}
if (lxc_setstate(name, STOPPING))
lxc_log_error("failed to set state %s", lxc_state2str(STOPPING));
if (clone_flags & CLONE_NEWNET && conf_destroy_network(name))
lxc_log_error("failed to destroy the network");
err = 0;
out:
if (lxc_setstate(name, STOPPED))
lxc_log_error("failed to set state %s", lxc_state2str(STOPPED));
lxc_unlink_nsgroup(name);
unlink(init);
free(init);
free(val);
lxc_put_lock(lock);
return err;
err_write:
close(fd);
err_state_failed:
err_child_failed:
err_pipe_read2:
err_pipe_write:
if (clone_flags & CLONE_NEWNET)
conf_destroy_network(name);
err_create_network:
err_pipe_read:
err_waitpid_failed:
if (lxc_setstate(name, ABORTING))
lxc_log_error("failed to set state %s", lxc_state2str(STOPPED));
kill(pid, SIGKILL);
err_fork_ns:
LXC_TTY_DEL_HANDLER(SIGQUIT);
LXC_TTY_DEL_HANDLER(SIGINT);
close(sv[0]);
close(sv[1]);
err:
goto out;
}
/*
* 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 <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/file.h>
#include <netinet/in.h>
#include <net/if.h>
#include <lxc.h>
int lxc_stop(const char *name)
{
char init[MAXPATHLEN];
char val[MAXPIDLEN];
int fd, lock, ret = -1;
size_t pid;
lock = lxc_get_lock(name);
if (lock > 0) {
lxc_log_error("'%s' is not running", name);
lxc_put_lock(lock);
return -1;
}
if (lock < 0) {
lxc_log_error("failed to acquire the lock on '%s':%s",
name, strerror(-lock));
return -1;
}
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_unlock;
}
if (read(fd, val, sizeof(val)) < 0) {
lxc_log_syserror("failed to read %s", init);
goto out_close;
}
pid = atoi(val);
if (kill(pid, SIGKILL)) {
lxc_log_syserror("failed to kill %zd", pid);
goto out_close;
}
if (unlink(init)) {
lxc_log_syserror("failed to unlink %s", init);
goto out_close;
}
ret = 0;
out_close:
close(fd);
out_unlock:
lxc_put_lock(lock);
return ret;
}
/*
* 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
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