prototype of dumm GUI

This commit is contained in:
Martin Willi 2008-04-28 16:43:30 +00:00
parent e8a680d94a
commit a47486b5e4
13 changed files with 873 additions and 866 deletions

View File

@ -20,6 +20,7 @@ AC_INIT(strongSwan,4.2.2)
AM_INIT_AUTOMAKE(tar-ustar)
AC_C_BIGENDIAN
AC_SUBST(confdir, '${sysconfdir}')
PKG_PROG_PKG_CONFIG
dnl =================================
dnl check --enable-xxx & --with-xxx
@ -581,11 +582,17 @@ if test x$curl = xtrue; then
fi
if test x$xml = xtrue; then
PKG_CHECK_MODULES(xml, [libxml-2.0],, AC_MSG_ERROR([No libxml2 package information found]))
PKG_CHECK_MODULES(xml, [libxml-2.0])
AC_SUBST(xml_CFLAGS)
AC_SUBST(xml_LIBS)
fi
if test x$dumm = xtrue; then
PKG_CHECK_MODULES(gtk, [gtk+-2.0 vte])
AC_SUBST(gtk_CFLAGS)
AC_SUBST(gtk_LIBS)
fi
if test x$fast = xtrue; then
AC_HAVE_LIBRARY([neo_cgi],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_cgi not found!])])
AC_HAVE_LIBRARY([neo_utl],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_utl not found!])])

View File

@ -1,12 +1,12 @@
lib_LTLIBRARIES = libdumm.la
ipsec_PROGRAMS = dumm
libdumm_la_SOURCES = dumm.c dumm.h guest.c guest.h iface.c iface.h bridge.c bridge.h mconsole.c mconsole.h cowfs.h cowfs.c
libdumm_la_SOURCES = dumm.c dumm.h guest.c guest.h iface.c iface.h \
bridge.c bridge.h mconsole.c mconsole.h cowfs.h cowfs.c
dumm_SOURCES = main.c
libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lpthread -lbridge -lfuse -lutil ${xml_LIBS}
dumm_LDADD = -ldumm -lreadline
INCLUDES = -I$(top_srcdir)/src/libstrongswan ${xml_CFLAGS}
libdumm_la_LIBADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lbridge -lfuse -lutil
dumm_LDADD = -ldumm ${gtk_LIBS}
INCLUDES = -I$(top_srcdir)/src/libstrongswan ${gtk_CFLAGS}
AM_CFLAGS = -D_FILE_OFFSET_BITS=64

View File

@ -31,6 +31,11 @@ struct private_bridge_t {
/** list of attached interfaces */
linked_list_t *ifaces;
};
/**
* defined in iface.c
*/
bool iface_control(char *name, bool up);
/**
* Implementation of bridge_t.get_name.
@ -41,11 +46,11 @@ static char* get_name(private_bridge_t *this)
}
/**
* Implementation of bridge_t.create_iface_iterator.
* Implementation of bridge_t.create_iface_enumerator.
*/
static iterator_t* create_iface_iterator(private_bridge_t *this)
static enumerator_t* create_iface_enumerator(private_bridge_t *this)
{
return this->ifaces->create_iterator(this->ifaces, TRUE);
return this->ifaces->create_enumerator(this->ifaces);
}
/**
@ -53,12 +58,12 @@ static iterator_t* create_iface_iterator(private_bridge_t *this)
*/
static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
{
iterator_t *iterator;
enumerator_t *enumerator;
iface_t *current;
bool good = FALSE;
iterator = this->ifaces->create_iterator(this->ifaces, TRUE);
while (iterator->iterate(iterator, (void**)&current))
enumerator = this->ifaces->create_enumerator(this->ifaces);
while (enumerator->enumerate(enumerator, (void**)&current))
{
if (current == iface)
{
@ -80,7 +85,7 @@ static bool disconnect_iface(private_bridge_t *this, iface_t *iface)
DBG1("iface '%s' not found on bridge '%s'", iface->get_hostif(iface),
this->name);
}
iterator->destroy(iterator);
enumerator->destroy(enumerator);
return good;
}
@ -120,6 +125,7 @@ static void destroy(private_bridge_t *this)
{
this->ifaces->invoke_function(this->ifaces, (linked_list_invoke_t)unregister);
this->ifaces->destroy(this->ifaces);
iface_control(this->name, FALSE);
if (br_del_bridge(this->name) != 0)
{
DBG1("deleting bridge '%s' from kernel failed: %m", this->name);
@ -150,7 +156,7 @@ bridge_t *bridge_create(char *name)
this = malloc_thing(private_bridge_t);
this->public.get_name = (char*(*)(bridge_t*))get_name;
this->public.create_iface_iterator = (iterator_t*(*)(bridge_t*))create_iface_iterator;
this->public.create_iface_enumerator = (enumerator_t*(*)(bridge_t*))create_iface_enumerator;
this->public.disconnect_iface = (bool(*)(bridge_t*, iface_t *iface))disconnect_iface;
this->public.connect_iface = (bool(*)(bridge_t*, iface_t *iface))connect_iface;
this->public.destroy = (void*)destroy;
@ -161,6 +167,10 @@ bridge_t *bridge_create(char *name)
free(this);
return NULL;
}
if (!iface_control(name, TRUE))
{
DBG1("bringing bridge '%s' up failed: %m", name);
}
this->name = strdup(name);
this->ifaces = linked_list_create();

View File

@ -17,7 +17,7 @@
#define BRIDGE_H
#include <library.h>
#include <utils/iterator.h>
#include <utils/enumerator.h>
typedef struct bridge_t bridge_t;
@ -31,32 +31,32 @@ struct bridge_t {
/**
* @brief Get the name of the bridge.
*
* @return name of the bridge
* @return name of the bridge
*/
char* (*get_name)(bridge_t *this);
/**
* @brief Add an interface to a bridge.
*
* @param iface interface to add
* @return TRUE if interface added
* @param iface interface to add
* @return TRUE if interface added
*/
bool (*connect_iface)(bridge_t *this, iface_t *iface);
/**
* @brief Remove an interface from a bridge.
*
* @param iface interface to remove
* @return TRUE if interface removed
* @param iface interface to remove
* @return TRUE if interface removed
*/
bool (*disconnect_iface)(bridge_t *this, iface_t *iface);
/**
* @brief Create an iterator over all interfaces.
* @brief Create an enumerator over all interfaces.
*
* @return iterator over iface_t's
* @return enumerator over iface_t's
*/
iterator_t* (*create_iface_iterator)(bridge_t *this);
enumerator_t* (*create_iface_enumerator)(bridge_t *this);
/**
* @brief Destroy a bridge

View File

@ -23,6 +23,7 @@
#include <errno.h>
#include <debug.h>
#include <utils/linked_list.h>
#include "dumm.h"
@ -31,11 +32,6 @@
#define TEMPLATE_DIR "templates"
#define TEMPLATE_DIR_DIR "diff"
/**
* instances of dumm, used to deliver signals
*/
static linked_list_t *instances = NULL;
typedef struct private_dumm_t private_dumm_t;
struct private_dumm_t {
@ -74,11 +70,31 @@ static guest_t* create_guest(private_dumm_t *this, char *name, char *kernel,
}
/**
* Implementation of dumm_t.create_guest_iterator.
* Implementation of dumm_t.create_guest_enumerator.
*/
static iterator_t* create_guest_iterator(private_dumm_t *this)
static enumerator_t* create_guest_enumerator(private_dumm_t *this)
{
return this->guests->create_iterator(this->guests, TRUE);
return this->guests->create_enumerator(this->guests);
}
/**
* Implementation of dumm_t.delete_guest.
*/
static void delete_guest(private_dumm_t *this, guest_t *guest)
{
if (this->guests->remove(this->guests, guest, NULL))
{
char buf[512];
int len;
len = snprintf(buf, sizeof(buf), "rm -Rf %s/%s",
this->guest_dir, guest->get_name(guest));
guest->destroy(guest);
if (len > 8 && len < 512)
{
system(buf);
}
}
}
/**
@ -97,11 +113,22 @@ static bridge_t* create_bridge(private_dumm_t *this, char *name)
}
/**
* Implementation of dumm_t.create_bridge_iterator.
* Implementation of dumm_t.create_bridge_enumerator.
*/
static iterator_t* create_bridge_iterator(private_dumm_t *this)
static enumerator_t* create_bridge_enumerator(private_dumm_t *this)
{
return this->bridges->create_iterator(this->bridges, TRUE);
return this->bridges->create_enumerator(this->bridges);
}
/**
* Implementation of dumm_t.delete_bridge.
*/
static void delete_bridge(private_dumm_t *this, bridge_t *bridge)
{
if (this->bridges->remove(this->bridges, bridge, NULL))
{
bridge->destroy(bridge);
}
}
/**
@ -109,26 +136,18 @@ static iterator_t* create_bridge_iterator(private_dumm_t *this)
*/
static void clear_template(private_dumm_t *this)
{
iterator_t *iterator, *ifaces;
enumerator_t *enumerator;
guest_t *guest;
iface_t *iface;
free(this->template);
this->template = NULL;
iterator = this->guests->create_iterator(this->guests, TRUE);
while (iterator->iterate(iterator, (void**)&guest))
enumerator = this->guests->create_enumerator(this->guests);
while (enumerator->enumerate(enumerator, (void**)&guest))
{
guest->load_template(guest, NULL);
ifaces = guest->create_iface_iterator(guest);
while (ifaces->iterate(ifaces, (void**)&iface))
{
ifaces->remove(ifaces);
iface->destroy(iface);
}
ifaces->destroy(ifaces);
}
iterator->destroy(iterator);
enumerator->destroy(enumerator);
}
/**
@ -136,7 +155,7 @@ static void clear_template(private_dumm_t *this)
*/
static bool load_template(private_dumm_t *this, char *name)
{
iterator_t *iterator;
enumerator_t *enumerator;
guest_t *guest;
char dir[PATH_MAX];
size_t len;
@ -169,131 +188,36 @@ static bool load_template(private_dumm_t *this, char *name)
return FALSE;
}
}
iterator = this->guests->create_iterator(this->guests, TRUE);
while (iterator->iterate(iterator, (void**)&guest))
enumerator = this->guests->create_enumerator(this->guests);
while (enumerator->enumerate(enumerator, (void**)&guest))
{
if (!guest->load_template(guest, dir))
{
iterator->destroy(iterator);
enumerator->destroy(enumerator);
clear_template(this);
return FALSE;
}
}
iterator->destroy(iterator);
enumerator->destroy(enumerator);
return TRUE;
}
/**
* signal handler
*/
void signal_handler(int sig, siginfo_t *info, void *ucontext)
{
if (sig == SIGCHLD)
{
switch (info->si_code)
{
case CLD_EXITED:
case CLD_KILLED:
case CLD_DUMPED:
{
private_dumm_t *this;
guest_t *guest;
iterator_t *iterator, *guests;
iterator = instances->create_iterator(instances, TRUE);
while (iterator->iterate(iterator, (void**)&this))
{
if (this->destroying)
{
continue;
}
guests = this->guests->create_iterator(this->guests, TRUE);
while (guests->iterate(guests, (void**)&guest))
{
if (guest->get_pid(guest) == info->si_pid)
{
guest->sigchild(guest);
break;
}
}
guests->destroy(guests);
}
iterator->destroy(iterator);
break;
}
default:
break;
}
}
/* SIGHUP is currently just ignored */
}
/**
* add a dumm instance
*/
static void add_instance(private_dumm_t *this)
{
if (instances == NULL)
{
struct sigaction action;
instances = linked_list_create();
memset(&action, 0, sizeof(action));
action.sa_sigaction = signal_handler;
action.sa_flags = SA_SIGINFO;
if (sigaction(SIGCHLD, &action, NULL) != 0 ||
sigaction(SIGHUP, &action, NULL) != 0)
{
DBG1("installing signal handler failed!");
}
}
instances->insert_last(instances, this);
}
/**
* remove a dumm instance
*/
static void remove_instance(private_dumm_t *this)
{
iterator_t *iterator;
private_dumm_t *current;
iterator = instances->create_iterator(instances, TRUE);
while (iterator->iterate(iterator, (void**)&current))
{
if (current == this)
{
iterator->remove(iterator);
break;
}
}
iterator->destroy(iterator);
if (instances->get_count(instances) == 0)
{
instances->destroy(instances);
instances = NULL;
}
}
/**
* Implementation of dumm_t.destroy
*/
static void destroy(private_dumm_t *this)
{
iterator_t *iterator;
enumerator_t *enumerator;
guest_t *guest;
this->bridges->destroy_offset(this->bridges, offsetof(bridge_t, destroy));
iterator = this->guests->create_iterator(this->guests, TRUE);
while (iterator->iterate(iterator, (void**)&guest))
enumerator = this->guests->create_enumerator(this->guests);
while (enumerator->enumerate(enumerator, (void**)&guest))
{
guest->stop(guest);
guest->stop(guest, NULL);
}
iterator->destroy(iterator);
enumerator->destroy(enumerator);
this->destroying = TRUE;
this->guests->destroy_offset(this->guests, offsetof(guest_t, destroy));
@ -301,7 +225,6 @@ static void destroy(private_dumm_t *this)
free(this->template_dir);
free(this->template);
free(this->dir);
remove_instance(this);
free(this);
}
@ -329,7 +252,6 @@ static void load_guests(private_dumm_t *this)
guest = guest_load(this->guest_dir, ent->d_name);
if (guest)
{
DBG1("loaded guest '%s'", ent->d_name);
this->guests->insert_last(this->guests, guest);
}
else
@ -349,20 +271,35 @@ dumm_t *dumm_create(char *dir)
private_dumm_t *this = malloc_thing(private_dumm_t);
this->public.create_guest = (guest_t*(*)(dumm_t*,char*,char*,char*,int))create_guest;
this->public.create_guest_iterator = (iterator_t*(*)(dumm_t*))create_guest_iterator;
this->public.create_guest_enumerator = (enumerator_t*(*)(dumm_t*))create_guest_enumerator;
this->public.delete_guest = (void(*)(dumm_t*,guest_t*))delete_guest;
this->public.create_bridge = (bridge_t*(*)(dumm_t*, char *name))create_bridge;
this->public.create_bridge_iterator = (iterator_t*(*)(dumm_t*))create_bridge_iterator;
this->public.create_bridge_enumerator = (enumerator_t*(*)(dumm_t*))create_bridge_enumerator;
this->public.delete_bridge = (void(*)(dumm_t*,bridge_t*))delete_bridge;
this->public.load_template = (bool(*)(dumm_t*, char *name))load_template;
this->public.destroy = (void(*)(dumm_t*))destroy;
this->destroying = FALSE;
if (*dir == '/' || getcwd(cwd, sizeof(cwd)) == 0)
if (dir && *dir == '/')
{
this->dir = strdup(dir);
}
else
{
asprintf(&this->dir, "%s/%s", cwd, dir);
if (getcwd(cwd, sizeof(cwd)) == NULL)
{
free(this);
return NULL;
}
if (dir)
{
asprintf(&this->dir, "%s/%s", cwd, dir);
}
else
{
this->dir = strdup(cwd);
}
}
this->template = NULL;
asprintf(&this->guest_dir, "%s/%s", this->dir, GUEST_DIR);
@ -370,8 +307,6 @@ dumm_t *dumm_create(char *dir)
this->guests = linked_list_create();
this->bridges = linked_list_create();
add_instance(this);
if (mkdir(this->guest_dir, PERME) < 0 && errno != EEXIST)
{
DBG1("creating guest directory '%s' failed: %m", this->guest_dir);

View File

@ -19,7 +19,7 @@
#include <signal.h>
#include <library.h>
#include <utils/linked_list.h>
#include <utils/enumerator.h>
#include "guest.h"
#include "bridge.h"
@ -30,8 +30,6 @@ typedef struct dumm_t dumm_t;
* @brief dumm - Dynamic Uml Mesh Modeler
*
* Controls a group of UML guests and their networks.
* Dumm catches SIGCHD and SIGHUP to trace UML child processes and the FUSE
* filesystem. Do not overwrite these signal handlers!
*/
struct dumm_t {
@ -48,11 +46,18 @@ struct dumm_t {
char *master, int mem);
/**
* @brief Create an iterator over all guests.
* @brief Create an enumerator over all guests.
*
* @return iteraotor over guest_t's
* @return enumerator over guest_t's
*/
iterator_t* (*create_guest_iterator) (dumm_t *this);
enumerator_t* (*create_guest_enumerator) (dumm_t *this);
/**
* @brief Delete a guest from disk.
*
* @param guest guest to destroy
*/
void (*delete_guest) (dumm_t *this, guest_t *guest);
/**
* @brief Create a new bridge.
@ -63,11 +68,18 @@ struct dumm_t {
bridge_t* (*create_bridge)(dumm_t *this, char *name);
/**
* @brief Create an iterator over all bridges.
* @brief Create an enumerator over all bridges.
*
* @return iterator over bridge_t's
* @return enumerator over bridge_t's
*/
iterator_t* (*create_bridge_iterator)(dumm_t *this);
enumerator_t* (*create_bridge_enumerator)(dumm_t *this);
/**
* @brief Delete a bridge.
*
* @param bridge bridge to destroy
*/
void (*delete_bridge) (dumm_t *this, bridge_t *bridge);
/**
* @brief Loads a template, create a new one if it does not exist.
@ -86,7 +98,7 @@ struct dumm_t {
/**
* @brief Create a group of UML hosts and networks.
*
* @param dir directory to create guests/load from
* @param dir directory to create guests/load from, NULL for cwd
* @return created UML group, or NULL if failed.
*/
dumm_t *dumm_create(char *dir);

View File

@ -63,8 +63,6 @@ struct private_guest_t {
int pid;
/** state of guest */
guest_state_t state;
/** log file for console 0 */
int bootlog;
/** FUSE cowfs instance */
cowfs_t *cowfs;
/** mconsole to control running UML */
@ -94,7 +92,7 @@ static char* get_name(private_guest_t *this)
*/
static iface_t* create_iface(private_guest_t *this, char *name)
{
iterator_t *iterator;
enumerator_t *enumerator;
iface_t *iface;
if (this->state != GUEST_RUNNING)
@ -103,17 +101,17 @@ static iface_t* create_iface(private_guest_t *this, char *name)
return NULL;
}
iterator = this->ifaces->create_iterator(this->ifaces, TRUE);
while (iterator->iterate(iterator, (void**)&iface))
enumerator = this->ifaces->create_enumerator(this->ifaces);
while (enumerator->enumerate(enumerator, (void**)&iface))
{
if (streq(name, iface->get_guestif(iface)))
{
DBG1("guest '%s' already has an interface '%s'", this->name, name);
iterator->destroy(iterator);
enumerator->destroy(enumerator);
return NULL;
}
}
iterator->destroy(iterator);
enumerator->destroy(enumerator);
iface = iface_create(this->name, name, this->mconsole);
if (iface)
@ -124,11 +122,32 @@ static iface_t* create_iface(private_guest_t *this, char *name)
}
/**
* Implementation of guest_t.create_iface_iterator.
* Implementation of guest_t.destroy_iface.
*/
static iterator_t* create_iface_iterator(private_guest_t *this)
static void destroy_iface(private_guest_t *this, iface_t *iface)
{
return this->ifaces->create_iterator(this->ifaces, TRUE);
enumerator_t *enumerator;
iface_t *current;
enumerator = this->ifaces->create_enumerator(this->ifaces);
while (enumerator->enumerate(enumerator, (void**)&current))
{
if (current == iface)
{
this->ifaces->remove_at(this->ifaces, enumerator);
current->destroy(current);
break;
}
}
enumerator->destroy(enumerator);
}
/**
* Implementation of guest_t.create_iface_enumerator.
*/
static enumerator_t* create_iface_enumerator(private_guest_t *this)
{
return this->ifaces->create_enumerator(this->ifaces);
}
/**
@ -169,22 +188,10 @@ static char* write_arg(char **pos, size_t *left, char *format, ...)
return res;
}
/**
* Implementation of get_t.close_console.
*/
static char* get_console(private_guest_t *this, int console)
{
if (this->state == GUEST_RUNNING)
{
return this->mconsole->get_console_pts(this->mconsole, console);
}
return NULL;
}
/**
* Implementation of guest_t.stop.
*/
static void stop(private_guest_t *this)
static void stop(private_guest_t *this, idle_function_t idle)
{
if (this->state != GUEST_STOPPED)
{
@ -192,23 +199,35 @@ static void stop(private_guest_t *this)
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
this->ifaces = linked_list_create();
kill(this->pid, SIGINT);
waitpid(this->pid, NULL, 0);
this->state = GUEST_STOPPED;
while (this->state != GUEST_STOPPED)
{
if (idle)
{
idle();
}
else
{
usleep(50000);
}
}
}
}
/**
* Implementation of guest_t.start.
*/
static bool start(private_guest_t *this)
static bool start(private_guest_t *this, invoke_function_t invoke, void* data,
idle_function_t idle)
{
char buf[2048];
char *notify;
char *pos = buf;
char *args[16];
char *args[32];
int i = 0;
size_t left = sizeof(buf);
memset(args, 0, sizeof(args));
if (this->state != GUEST_STOPPED)
{
DBG1("unable to start guest in state %N", guest_state_names, this->state);
@ -226,32 +245,20 @@ static bool start(private_guest_t *this)
args[i++] = write_arg(&pos, &left, "umid=%s", this->name);
args[i++] = write_arg(&pos, &left, "mem=%dM", this->mem);
args[i++] = write_arg(&pos, &left, "mconsole=notify:%s", notify);
args[i++] = write_arg(&pos, &left, "con=pts");
args[i++] = write_arg(&pos, &left, "con0=none,fd:%d", this->bootlog);
args[i++] = NULL;
args[i++] = write_arg(&pos, &left, "con=null");
this->pid = fork();
switch (this->pid)
this->pid = invoke(data, &this->public, args, i);
if (!this->pid)
{
case 0: /* child, */
dup2(open("/dev/null", 0), 0);
dup2(this->bootlog, 1);
dup2(this->bootlog, 2);
execvp(args[0], args);
DBG1("starting UML kernel '%s' failed: %m", args[0]);
exit(1);
case -1:
this->state = GUEST_STOPPED;
return FALSE;
default:
break;
this->state = GUEST_STOPPED;
return FALSE;
}
/* open mconsole */
this->mconsole = mconsole_create(notify);
this->mconsole = mconsole_create(notify, idle);
if (this->mconsole == NULL)
{
DBG1("opening mconsole at '%s' failed, stopping guest", buf);
stop(this);
stop(this, NULL);
return FALSE;
}
@ -266,6 +273,7 @@ static bool load_template(private_guest_t *this, char *path)
{
char dir[PATH_MAX];
size_t len;
iface_t *iface;
if (path == NULL)
{
@ -285,7 +293,15 @@ static bool load_template(private_guest_t *this, char *path)
return FALSE;
}
}
return this->cowfs->set_overlay(this->cowfs, dir);
if (!this->cowfs->set_overlay(this->cowfs, dir))
{
return FALSE;
}
while (this->ifaces->remove_last(this->ifaces, (void**)&iface) == SUCCESS)
{
iface->destroy(iface);
}
return TRUE;
}
/**
@ -293,10 +309,6 @@ static bool load_template(private_guest_t *this, char *path)
*/
static void sigchild(private_guest_t *this)
{
if (this->state != GUEST_STOPPING)
{ /* collect zombie if uml crashed */
waitpid(this->pid, NULL, WNOHANG);
}
DESTROY_IF(this->mconsole);
this->mconsole = NULL;
this->state = GUEST_STOPPED;
@ -340,22 +352,6 @@ static bool mount_unionfs(private_guest_t *this)
return FALSE;
}
/**
* open logfile for boot messages
*/
static int open_bootlog(private_guest_t *this)
{
int fd;
fd = openat(this->dir, LOG_FILE, O_WRONLY | O_CREAT, PERM);
if (fd == -1)
{
DBG1("opening bootlog failed, using stdout");
return 1;
}
return fd;
}
/**
* load memory configuration from file
*/
@ -402,12 +398,8 @@ bool savemem(private_guest_t *this, int mem)
*/
static void destroy(private_guest_t *this)
{
stop(this);
stop(this, NULL);
umount_unionfs(this);
if (this->bootlog > 1)
{
close(this->bootlog);
}
if (this->dir > 0)
{
close(this->dir);
@ -430,10 +422,10 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
this->public.get_pid = (pid_t(*)(guest_t*))get_pid;
this->public.get_state = (guest_state_t(*)(guest_t*))get_state;
this->public.create_iface = (iface_t*(*)(guest_t*,char*))create_iface;
this->public.create_iface_iterator = (iterator_t*(*)(guest_t*))create_iface_iterator;
this->public.destroy_iface = (void(*)(guest_t*,iface_t*))destroy_iface;
this->public.create_iface_enumerator = (enumerator_t*(*)(guest_t*))create_iface_enumerator;
this->public.start = (void*)start;
this->public.stop = (void*)stop;
this->public.get_console = (char*(*)(guest_t*,int))get_console;
this->public.load_template = (bool(*)(guest_t*, char *path))load_template;
this->public.sigchild = (void(*)(guest_t*))sigchild;
this->public.destroy = (void*)destroy;
@ -464,7 +456,6 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
this->mconsole = NULL;
this->ifaces = linked_list_create();
this->mem = 0;
this->bootlog = open_bootlog(this);
this->name = strdup(name);
this->cowfs = NULL;

View File

@ -17,11 +17,12 @@
#define GUEST_H
#include <library.h>
#include <utils/iterator.h>
#include <utils/enumerator.h>
#include "iface.h"
typedef enum guest_state_t guest_state_t;
typedef struct guest_t guest_t;
/**
* @brief State of a guest (started, stopped, ...)
@ -44,7 +45,26 @@ enum guest_state_t {
*/
extern enum_name_t *guest_state_names;
typedef struct guest_t guest_t;
/**
* Invoke function which lauches the UML guest.
*
* Consoles are all set to NULL, you may change them by adding additional UML
* options to args before invocation.
*
* @param data callback data
* @param guest guest to start
* @param args args to use for guest invocation, args[0] is kernel
* @param argc number of elements in args
* @param idle
* @return PID of child, 0 if failed
*/
typedef pid_t (*invoke_function_t)(void *data, guest_t *guest,
char *args[], int argc);
/**
* Idle function to pass to start().
*/
typedef void (*idle_function_t)(void);
/**
* @brief A guest is a UML instance running on the host.
@ -75,27 +95,21 @@ struct guest_t {
/**
* @brief Start the guest.
*
* @return TRUE if guest successfully started
* @param invoke UML guest invocation function
* @param data data to pass back to invoke function
* @param idle idle function to call while waiting on child
* @return TRUE if guest successfully started
*/
bool (*start) (guest_t *this);
bool (*start) (guest_t *this, invoke_function_t invoke, void *data,
idle_function_t idle);
/**
* @brief Kill the guest.
*
* @return TRUE if guest was running and killed
* @param idle idle function to call while waiting to termination
* @return TRUE if guest was running and killed
*/
bool (*stop) (guest_t *this);
/**
* @brief Get a console pts device.
*
* Every guest has 5 consoles, numbered from 1 to 5. These are associated
* to a unique pts device on the host.
*
* @param console console number to get (1-5)
* @return pts device file name, NULL if failed
*/
char* (*get_console) (guest_t *this, int console);
bool (*stop) (guest_t *this, idle_function_t idle);
/**
* @brief Create a new interface in the current scenario.
@ -106,11 +120,18 @@ struct guest_t {
iface_t* (*create_iface)(guest_t *this, char *name);
/**
* @brief Create an iterator over all guest interfaces.
* @brief Destroy an interface on guest.
*
* @return iterator over iface_t's
* @param iface interface to destroy
*/
iterator_t* (*create_iface_iterator)(guest_t *this);
void (*destroy_iface)(guest_t *this, iface_t *iface);
/**
* @brief Create an enumerator over all guest interfaces.
*
* @return enumerator over iface_t's
*/
enumerator_t* (*create_iface_enumerator)(guest_t *this);
/**
* @brief Set the template COWFS overlay to use.

View File

@ -43,6 +43,42 @@ struct private_iface_t {
mconsole_t *mconsole;
};
/**
* bring an interface up or down
*/
bool iface_control(char *name, bool up)
{
int s;
bool good = FALSE;
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
s = socket(AF_INET, SOCK_DGRAM, 0);
if (!s)
{
return FALSE;
}
if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0)
{
if (up)
{
ifr.ifr_flags |= IFF_UP;
}
else
{
ifr.ifr_flags &= ~IFF_UP;
}
if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
{
good = TRUE;
}
}
close(s);
return good;
}
/**
* Implementation of iface_t.get_guestif.
*/
@ -74,7 +110,11 @@ static bool destroy_tap(private_iface_t *this)
{
struct ifreq ifr;
int tap;
if (!iface_control(this->hostif, FALSE))
{
DBG1("bringing iface down failed: %m");
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy(ifr.ifr_name, this->hostif, sizeof(ifr.ifr_name) - 1);
@ -165,6 +205,10 @@ iface_t *iface_create(char *guest, char *guestif, mconsole_t *mconsole)
free(this);
return NULL;
}
if (!iface_control(this->hostif, TRUE))
{
DBG1("bringing iface '%s' up failed: %m", this->hostif);
}
if (!this->mconsole->add_iface(this->mconsole, this->guestif, this->hostif))
{
DBG1("creating interface '%s' in guest failed", this->guestif);

View File

@ -17,7 +17,7 @@
#define IFACE_H
#include <library.h>
#include <utils/iterator.h>
#include <utils/enumerator.h>
#define TAP_DEVICE "/dev/net/tun"
@ -53,10 +53,8 @@ struct iface_t {
void (*set_bridge)(iface_t *this, bridge_t *bridge);
/*
bool (*up) (iface_t *this);
bool (*down) (iface_t *this);
bool (*add_addr) (iface_t *this, host_t *addr);
iterator_t* (*create_addr_iterator) (iface_t *this);
enumerator_t* (*create_addr_enumerator) (iface_t *this);
*/
/**

File diff suppressed because it is too large Load Diff

View File

@ -44,6 +44,8 @@ struct private_mconsole_t {
int notify;
/** address of uml socket */
struct sockaddr_un uml;
/** idle function */
void (*idle)(void);
};
/**
@ -91,7 +93,7 @@ static int request(private_mconsole_t *this, char *command,
{
mconsole_request request;
mconsole_reply reply;
int len, total = 0;
int len, total = 0, flags = 0;
memset(&request, 0, sizeof(request));
request.magic = MCONSOLE_MAGIC;
@ -101,19 +103,41 @@ static int request(private_mconsole_t *this, char *command,
*buf = '\0';
(*size)--;
if (sendto(this->console, &request, sizeof(request), 0,
(struct sockaddr*)&this->uml, sizeof(this->uml)) < 0)
if (this->idle)
{
flags = MSG_DONTWAIT;
}
do
{
if (this->idle)
{
this->idle();
}
len = sendto(this->console, &request, sizeof(request), flags,
(struct sockaddr*)&this->uml, sizeof(this->uml));
}
while (len < 0 && (errno == EINTR || errno == EAGAIN));
if (len < 0)
{
snprintf(buf, *size, "sending mconsole command to UML failed: %m");
return -1;
}
do
{
len = recv(this->console, &reply, sizeof(reply), 0);
len = recv(this->console, &reply, sizeof(reply), flags);
if (len < 0 && (errno == EINTR || errno == EAGAIN))
{
if (this->idle)
{
this->idle();
}
continue;
}
if (len < 0)
{
snprintf(buf, *size, "receiving from mconsole failed: %m");
return -1;
return -1;
}
if (len > 0)
{
@ -169,35 +193,6 @@ static bool del_iface(private_mconsole_t *this, char *guest)
}
return TRUE;
}
/**
* Implementation of mconsole_t.get_console_pts.
*/
static char* get_console_pts(private_mconsole_t *this, int con)
{
char buf[128];
char *pos;
int len;
len = snprintf(buf, sizeof(buf), "config con%d", con);
if (len < 0 || len >= sizeof(buf))
{
return NULL;
}
len = sizeof(buf);
if (request(this, buf, buf, &len) != 0)
{
DBG1("getting console pts failed: %.*s", len, buf);
return NULL;
}
pos = memchr(buf, ':', len);
if (pos == NULL)
{
return NULL;
}
pos++;
return strndup(pos, len - (pos - buf));
}
/**
* Poll until guest is ready
@ -220,7 +215,14 @@ static bool wait_bootup(private_mconsole_t *this)
{
return TRUE;
}
usleep(50000);
if (this->idle)
{
this->idle();
}
else
{
usleep(50000);
}
}
}
@ -241,7 +243,7 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
{
struct sockaddr_un addr;
mconsole_notify notify;
int len;
int len, flags = 0;
this->notify = socket(AF_UNIX, SOCK_DGRAM, 0);
if (this->notify < 0)
@ -258,10 +260,20 @@ static bool wait_for_notify(private_mconsole_t *this, char *nsock)
close(this->notify);
return FALSE;
}
if (this->idle)
{
flags = MSG_DONTWAIT;
}
do
{
len = recvfrom(this->notify, &notify, sizeof(notify), 0, NULL, 0);
} while (len < 0 && errno == EINTR);
if (this->idle)
{
this->idle();
}
len = recvfrom(this->notify, &notify, sizeof(notify), flags, NULL, 0);
}
while (len < 0 && (errno == EINTR || errno == EAGAIN));
if (len < 0 || len >= sizeof(notify))
{
DBG1("reading from mconsole notify socket failed: %m");
@ -314,15 +326,16 @@ static bool setup_console(private_mconsole_t *this)
/**
* create the mconsole instance
*/
mconsole_t *mconsole_create(char *notify)
mconsole_t *mconsole_create(char *notify, void(*idle)(void))
{
private_mconsole_t *this = malloc_thing(private_mconsole_t);
this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
this->public.get_console_pts = (char*(*)(mconsole_t*, int con))get_console_pts;
this->public.destroy = (void*)destroy;
this->idle = idle;
if (!wait_for_notify(this, notify))
{
free(this);

View File

@ -42,14 +42,6 @@ struct mconsole_t {
*/
bool (*del_iface)(mconsole_t *this, char *guest);
/**
* @brief Get the pts device file assigned to a console.
*
* @param con console number in guest
* @return allocated device string
*/
char* (*get_console_pts)(mconsole_t *this, int con);
/**
* @brief Destroy the mconsole instance
*/
@ -63,9 +55,10 @@ struct mconsole_t {
* to connect to the mconsole socket supplied in the received notification.
*
* @param notify unix notify socket path
* @param idle idle function to call while waiting for responses
* @return mconsole instance, or NULL if failed
*/
mconsole_t *mconsole_create(char *notify);
mconsole_t *mconsole_create(char *notify, void(*idle)(void));
#endif /* MCONSOLE_H */