added dynamic interface manipulation for guests
management of tap devices on the host
This commit is contained in:
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
|
|
||||||
dumm: dumm.c dumm.h guest.c guest.h main.c
|
dumm: dumm.c dumm.h guest.c guest.h iface.c iface.h mconsole.c mconsole.h main.c
|
||||||
gcc -o dumm dumm.c guest.c main.c -lreadline -lstrongswan -I../libstrongswan/ -g -Wall
|
gcc -o dumm dumm.c guest.c iface.c mconsole.c main.c -lreadline -lstrongswan -I../libstrongswan/ -g -Wall
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|||||||
@@ -1,3 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef DUMM_H
|
#ifndef DUMM_H
|
||||||
#define DUMM_H
|
#define DUMM_H
|
||||||
|
|
||||||
@@ -45,6 +60,14 @@ struct dumm_t {
|
|||||||
void (*destroy) (dumm_t *this);
|
void (*destroy) (dumm_t *this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new group of UML hosts and networks.
|
||||||
|
*
|
||||||
|
* Dumm uses its working dir to create folders and files it works with.
|
||||||
|
*
|
||||||
|
* @return created UML group, or NULL if failed.
|
||||||
|
*/
|
||||||
dumm_t *dumm_create();
|
dumm_t *dumm_create();
|
||||||
|
|
||||||
#endif /* DUMM_H */
|
#endif /* DUMM_H */
|
||||||
|
|
||||||
|
|||||||
+108
-15
@@ -1,3 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -10,27 +25,88 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <utils/linked_list.h>
|
||||||
|
|
||||||
#include "dumm.h"
|
#include "dumm.h"
|
||||||
#include "guest.h"
|
#include "guest.h"
|
||||||
|
#include "mconsole.h"
|
||||||
|
|
||||||
typedef struct private_guest_t private_guest_t;
|
typedef struct private_guest_t private_guest_t;
|
||||||
|
|
||||||
struct private_guest_t {
|
struct private_guest_t {
|
||||||
|
/** implemented public interface */
|
||||||
guest_t public;
|
guest_t public;
|
||||||
|
/** name of the guest */
|
||||||
char *name;
|
char *name;
|
||||||
|
/** kernel to boot for guest */
|
||||||
char *kernel;
|
char *kernel;
|
||||||
|
/** read only master filesystem guest uses */
|
||||||
char *master;
|
char *master;
|
||||||
|
/** amount of memory for guest, in MB */
|
||||||
int mem;
|
int mem;
|
||||||
|
/** pid of guest child process */
|
||||||
int pid;
|
int pid;
|
||||||
|
/** log file for console 0 */
|
||||||
int bootlog;
|
int bootlog;
|
||||||
|
/** mconsole to control running UML */
|
||||||
|
mconsole_t *mconsole;
|
||||||
|
/** list of interfaces attached to the guest */
|
||||||
|
linked_list_t *ifaces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of guest_t.get_name.
|
||||||
|
*/
|
||||||
static char* get_name(private_guest_t *this)
|
static char* get_name(private_guest_t *this)
|
||||||
{
|
{
|
||||||
return this->name;
|
return this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of guest_t.create_iface.
|
||||||
|
*/
|
||||||
|
static iface_t* create_iface(private_guest_t *this, char *name)
|
||||||
|
{
|
||||||
|
iterator_t *iterator;
|
||||||
|
iface_t *iface;
|
||||||
|
|
||||||
|
if (this->pid == 0)
|
||||||
|
{
|
||||||
|
DBG1("guest '%s' not running, unable to add interface", this->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator = this->ifaces->create_iterator(this->ifaces, TRUE);
|
||||||
|
while (iterator->iterate(iterator, (void**)&iface))
|
||||||
|
{
|
||||||
|
if (streq(name, iface->get_guest(iface)))
|
||||||
|
{
|
||||||
|
DBG1("guest '%s' already has an interface '%s'", this->name, name);
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
|
iface = iface_create(name, this->mconsole);
|
||||||
|
if (iface)
|
||||||
|
{
|
||||||
|
this->ifaces->insert_last(this->ifaces, iface);
|
||||||
|
}
|
||||||
|
return iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of guest_t.create_iface_iterator.
|
||||||
|
*/
|
||||||
|
static iterator_t* create_iface_iterator(private_guest_t *this)
|
||||||
|
{
|
||||||
|
return this->ifaces->create_iterator(this->ifaces, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write format string to a buffer, and advance buffer position
|
||||||
|
*/
|
||||||
static char* write_arg(char **pos, size_t *left, char *format, ...)
|
static char* write_arg(char **pos, size_t *left, char *format, ...)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -50,6 +126,9 @@ static char* write_arg(char **pos, size_t *left, char *format, ...)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of guest_t.start.
|
||||||
|
*/
|
||||||
static bool start(private_guest_t *this)
|
static bool start(private_guest_t *this)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@@ -67,7 +146,7 @@ static bool start(private_guest_t *this)
|
|||||||
args[i++] = write_arg(&pos, &left, "uml_dir=%s/%s", RUN_DIR, this->name);
|
args[i++] = write_arg(&pos, &left, "uml_dir=%s/%s", RUN_DIR, this->name);
|
||||||
args[i++] = write_arg(&pos, &left, "umid=%s", this->name);
|
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, "mem=%dM", this->mem);
|
||||||
//args[i++] = write_arg(&pos, &left, "con=pts");
|
/*args[i++] = write_arg(&pos, &left, "con=pts");*/
|
||||||
args[i++] = write_arg(&pos, &left, "con0=null,fd:%d", this->bootlog);
|
args[i++] = write_arg(&pos, &left, "con0=null,fd:%d", this->bootlog);
|
||||||
args[i++] = write_arg(&pos, &left, "con1=fd:0,fd:1");
|
args[i++] = write_arg(&pos, &left, "con1=fd:0,fd:1");
|
||||||
args[i++] = write_arg(&pos, &left, "con3=null,null");
|
args[i++] = write_arg(&pos, &left, "con3=null,null");
|
||||||
@@ -84,15 +163,30 @@ static bool start(private_guest_t *this)
|
|||||||
dup2(open("/dev/null", 0), 1);
|
dup2(open("/dev/null", 0), 1);
|
||||||
dup2(open("/dev/null", 0), 2);
|
dup2(open("/dev/null", 0), 2);
|
||||||
execvp(args[0], args);
|
execvp(args[0], args);
|
||||||
|
DBG1("starting UML kernel '%s' failed", args[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
case -1:
|
case -1:
|
||||||
this->pid = 0;
|
this->pid = 0;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
default:
|
default:
|
||||||
return TRUE;
|
break;
|
||||||
}
|
}
|
||||||
|
/* open mconsole */
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s/%s/mconsole", RUN_DIR, this->name, this->name);
|
||||||
|
this->mconsole = mconsole_create(buf);
|
||||||
|
if (this->mconsole == NULL)
|
||||||
|
{
|
||||||
|
DBG1("opening mconsole at '%s' failed, stopping guest", buf);
|
||||||
|
kill(this->pid, SIGINT);
|
||||||
|
this->pid = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of guest_t.stop.
|
||||||
|
*/
|
||||||
static void stop(private_guest_t *this)
|
static void stop(private_guest_t *this)
|
||||||
{
|
{
|
||||||
if (this->pid)
|
if (this->pid)
|
||||||
@@ -103,7 +197,7 @@ static void stop(private_guest_t *this)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create a directory
|
* Check if directory exists, create otherwise
|
||||||
*/
|
*/
|
||||||
static bool makedir(char *dir, char *name)
|
static bool makedir(char *dir, char *name)
|
||||||
{
|
{
|
||||||
@@ -138,6 +232,7 @@ static bool umount_unionfs(char *name)
|
|||||||
}
|
}
|
||||||
if (system(cmd) != 0)
|
if (system(cmd) != 0)
|
||||||
{
|
{
|
||||||
|
DBG1("unmounting guest unionfs for %s failed", name);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -151,7 +246,6 @@ static bool mount_unionfs(char *name, char *master)
|
|||||||
char cmd[256];
|
char cmd[256];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* mount unionfs */
|
|
||||||
len = snprintf(cmd, sizeof(cmd), "unionfs %s/%s:%s %s/%s",
|
len = snprintf(cmd, sizeof(cmd), "unionfs %s/%s:%s %s/%s",
|
||||||
HOST_DIR, name, master, MOUNT_DIR, name);
|
HOST_DIR, name, master, MOUNT_DIR, name);
|
||||||
if (len < 0 || len >= sizeof(cmd))
|
if (len < 0 || len >= sizeof(cmd))
|
||||||
@@ -160,7 +254,7 @@ static bool mount_unionfs(char *name, char *master)
|
|||||||
}
|
}
|
||||||
if (system(cmd) != 0)
|
if (system(cmd) != 0)
|
||||||
{
|
{
|
||||||
DBG1("mounting unionfs using '%s' failed.", cmd);
|
DBG1("mounting guest unionfs for %s using '%s' failed", name, cmd);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -183,18 +277,21 @@ static int open_bootlog(char *name)
|
|||||||
fd = open(blg, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
|
fd = open(blg, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
|
DBG1("opening bootlog '%s' for %s failed, using stdout", blg, name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stop guest, unmount mounts
|
* Implementation of guest_t.destroy.
|
||||||
*/
|
*/
|
||||||
static void destroy(private_guest_t *this)
|
static void destroy(private_guest_t *this)
|
||||||
{
|
{
|
||||||
stop(this);
|
stop(this);
|
||||||
umount_unionfs(this->name);
|
umount_unionfs(this->name);
|
||||||
|
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
|
||||||
|
DESTROY_IF(this->mconsole);
|
||||||
free(this->name);
|
free(this->name);
|
||||||
free(this->kernel);
|
free(this->kernel);
|
||||||
free(this->master);
|
free(this->master);
|
||||||
@@ -209,21 +306,15 @@ guest_t *guest_create(char *name, char *kernel, char *master, int mem)
|
|||||||
private_guest_t *this = malloc_thing(private_guest_t);
|
private_guest_t *this = malloc_thing(private_guest_t);
|
||||||
|
|
||||||
this->public.get_name = (void*)get_name;
|
this->public.get_name = (void*)get_name;
|
||||||
|
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.start = (void*)start;
|
this->public.start = (void*)start;
|
||||||
this->public.stop = (void*)stop;
|
this->public.stop = (void*)stop;
|
||||||
this->public.destroy = (void*)destroy;
|
this->public.destroy = (void*)destroy;
|
||||||
|
|
||||||
if (!makedir(HOST_DIR, name) || !makedir(MOUNT_DIR, name) ||
|
if (!makedir(HOST_DIR, name) || !makedir(MOUNT_DIR, name) ||
|
||||||
!makedir(RUN_DIR, name))
|
!makedir(RUN_DIR, name) || !mount_unionfs(name, master))
|
||||||
{
|
{
|
||||||
DBG1("creating guest directories for %s failed failed.", name);
|
|
||||||
free(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mount_unionfs(name, master))
|
|
||||||
{
|
|
||||||
DBG1("mounting guest unionfs for %s failed.", name);
|
|
||||||
free(this);
|
free(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -234,6 +325,8 @@ guest_t *guest_create(char *name, char *kernel, char *master, int mem)
|
|||||||
this->mem = mem;
|
this->mem = mem;
|
||||||
this->pid = 0;
|
this->pid = 0;
|
||||||
this->bootlog = open_bootlog(name);
|
this->bootlog = open_bootlog(name);
|
||||||
|
this->mconsole = NULL;
|
||||||
|
this->ifaces = linked_list_create();
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
+63
-2
@@ -1,23 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef GUEST_H
|
#ifndef GUEST_H
|
||||||
#define GUEST_H
|
#define GUEST_H
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <utils/linked_list.h>
|
#include <utils/iterator.h>
|
||||||
|
|
||||||
|
#include "iface.h"
|
||||||
|
|
||||||
typedef struct guest_t guest_t;
|
typedef struct guest_t guest_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A guest is a UML instance running on the host.
|
||||||
|
**/
|
||||||
struct guest_t {
|
struct guest_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the name of this guest.
|
||||||
|
*
|
||||||
|
* @return name of the guest
|
||||||
|
*/
|
||||||
char* (*get_name) (guest_t *this);
|
char* (*get_name) (guest_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start the guest.
|
||||||
|
*
|
||||||
|
* @return TRUE if guest successfully started
|
||||||
|
*/
|
||||||
bool (*start) (guest_t *this);
|
bool (*start) (guest_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Kill the guest.
|
||||||
|
*
|
||||||
|
* @return TRUE if guest was running and killed
|
||||||
|
*/
|
||||||
bool (*stop) (guest_t *this);
|
bool (*stop) (guest_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new interface for that host.
|
||||||
|
*
|
||||||
|
* @param name name of the interface in the guest
|
||||||
|
* @return created interface, or NULL if failed
|
||||||
|
*/
|
||||||
|
iface_t* (*create_iface)(guest_t *this, char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create an iterator over all guest interfaces.
|
||||||
|
*
|
||||||
|
* @return iterator over iface_t's
|
||||||
|
*/
|
||||||
|
iterator_t* (*create_iface_iterator)(guest_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Close and destroy a guest with all interfaces
|
||||||
|
*/
|
||||||
void (*destroy) (guest_t *this);
|
void (*destroy) (guest_t *this);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new, unstarted guest.
|
||||||
|
*
|
||||||
|
* @param name name of the guest
|
||||||
|
* @param kernel kernel to boot for this guest
|
||||||
|
* @param master read-only master filesystem for guest
|
||||||
|
* @param mem amount of memory to give the guest
|
||||||
|
*/
|
||||||
guest_t *guest_create(char *name, char *kernel, char *master, int mem);
|
guest_t *guest_create(char *name, char *kernel, char *master, int mem);
|
||||||
|
|
||||||
|
|
||||||
#endif /* GUEST_H */
|
#endif /* GUEST_H */
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
* Copyright (C) 2002 Jeff Dike
|
||||||
|
*
|
||||||
|
* Based on the "tunctl" utlity from Jeff Dike.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "iface.h"
|
||||||
|
|
||||||
|
typedef struct private_iface_t private_iface_t;
|
||||||
|
|
||||||
|
struct private_iface_t {
|
||||||
|
/** public interface */
|
||||||
|
iface_t public;
|
||||||
|
/** device name in guest (eth0) */
|
||||||
|
char *guest;
|
||||||
|
/** device name at host (tap0) */
|
||||||
|
char *host;
|
||||||
|
/** tap device handle to manage taps */
|
||||||
|
int tap;
|
||||||
|
/** mconsole for guest */
|
||||||
|
mconsole_t *mconsole;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of iface_t.get_guest.
|
||||||
|
*/
|
||||||
|
static char* get_guest(private_iface_t *this)
|
||||||
|
{
|
||||||
|
return this->guest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of iface_t.get_host.
|
||||||
|
*/
|
||||||
|
static char* get_host(private_iface_t *this)
|
||||||
|
{
|
||||||
|
return this->host;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destroy the tap device
|
||||||
|
*/
|
||||||
|
static bool destroy_tap(private_iface_t *this)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||||
|
strncpy(ifr.ifr_name, this->host, sizeof(ifr.ifr_name) - 1);
|
||||||
|
|
||||||
|
if (ioctl(this->tap, TUNSETIFF, &ifr) < 0 ||
|
||||||
|
ioctl(this->tap, TUNSETPERSIST, 0) < 0)
|
||||||
|
{
|
||||||
|
DBG1("removing %s failed: %m", this->host);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the tap device
|
||||||
|
*/
|
||||||
|
static char* create_tap(private_iface_t *this)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
||||||
|
|
||||||
|
if (ioctl(this->tap, TUNSETIFF, &ifr) < 0 ||
|
||||||
|
ioctl(this->tap, TUNSETPERSIST, 1) < 0)
|
||||||
|
{
|
||||||
|
DBG1("creating new tap device failed: %m");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return strdup(ifr.ifr_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of iface_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(private_iface_t *this)
|
||||||
|
{
|
||||||
|
this->mconsole->del_iface(this->mconsole, this->guest);
|
||||||
|
destroy_tap(this);
|
||||||
|
close(this->tap);
|
||||||
|
free(this->guest);
|
||||||
|
free(this->host);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the iface instance
|
||||||
|
*/
|
||||||
|
iface_t *iface_create(char *guest, mconsole_t *mconsole)
|
||||||
|
{
|
||||||
|
private_iface_t *this = malloc_thing(private_iface_t);
|
||||||
|
|
||||||
|
this->public.get_host = (char*(*)(iface_t*))get_host;
|
||||||
|
this->public.get_guest = (char*(*)(iface_t*))get_guest;
|
||||||
|
this->public.destroy = (void*)destroy;
|
||||||
|
|
||||||
|
this->mconsole = mconsole;
|
||||||
|
this->tap = open(TAP_DEVICE, O_RDWR);
|
||||||
|
if (this->tap < 0)
|
||||||
|
{
|
||||||
|
DBG1("unable to open tap device %s: %m", TAP_DEVICE);
|
||||||
|
free(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
this->guest = strdup(guest);
|
||||||
|
this->host = create_tap(this);
|
||||||
|
if (this->host == NULL)
|
||||||
|
{
|
||||||
|
destroy_tap(this);
|
||||||
|
close(this->tap);
|
||||||
|
free(this->guest);
|
||||||
|
free(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!this->mconsole->add_iface(this->mconsole, this->guest, this->host))
|
||||||
|
{
|
||||||
|
DBG1("creating interface '%s' in guest failed", this->guest);
|
||||||
|
destroy_tap(this);
|
||||||
|
close(this->tap);
|
||||||
|
free(this->guest);
|
||||||
|
free(this->host);
|
||||||
|
free(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IFACE_H
|
||||||
|
#define IFACE_H
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
#include <utils/iterator.h>
|
||||||
|
|
||||||
|
#include "mconsole.h"
|
||||||
|
|
||||||
|
#define TAP_DEVICE "/dev/net/tun"
|
||||||
|
|
||||||
|
typedef struct iface_t iface_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface in a guest, connected to a tap device on the host.
|
||||||
|
*/
|
||||||
|
struct iface_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the interface name in the guest (e.g. eth0).
|
||||||
|
*
|
||||||
|
* @return guest interface name
|
||||||
|
*/
|
||||||
|
char* (*get_guest)(iface_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the interface name at the host (e.g. tap0).
|
||||||
|
*
|
||||||
|
* @return host interface (tap device) name
|
||||||
|
*/
|
||||||
|
char* (*get_host)(iface_t *this);
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool (*up) (iface_t *this);
|
||||||
|
bool (*down) (iface_t *this);
|
||||||
|
bool (*add_addr) (iface_t *this, host_t *addr);
|
||||||
|
bool (*del_addr) (iface_t *this, host_t *addr);
|
||||||
|
iterator_t* (*create_addr_iterator) (iface_t *this);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy an interface
|
||||||
|
*/
|
||||||
|
void (*destroy) (iface_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new interface for a guest
|
||||||
|
*
|
||||||
|
* @param guest name of the interface in the guest
|
||||||
|
* @param mconsole mconsole of guest
|
||||||
|
* @return interface descriptor, or NULL if failed
|
||||||
|
*/
|
||||||
|
iface_t *iface_create(char *guest, mconsole_t *mconsole);
|
||||||
|
|
||||||
|
#endif /* IFACE_H */
|
||||||
+221
-19
@@ -1,3 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -20,7 +35,7 @@ static void usage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* show usage information (commandline arguments)
|
* help for dumm root shell
|
||||||
*/
|
*/
|
||||||
static void help()
|
static void help()
|
||||||
{
|
{
|
||||||
@@ -29,15 +44,29 @@ static void help()
|
|||||||
printf(" kernel=<uml-kernel>\n");
|
printf(" kernel=<uml-kernel>\n");
|
||||||
printf(" master=<read-only root files>\n");
|
printf(" master=<read-only root files>\n");
|
||||||
printf(" memory=<guest memory in MB>\n");
|
printf(" memory=<guest memory in MB>\n");
|
||||||
printf("guests list running guests\n");
|
printf("list list running guests\n");
|
||||||
|
printf("guest <name> open guest menu for <name>\n");
|
||||||
printf("help show this help\n");
|
printf("help show this help\n");
|
||||||
printf("quit kill quests and exit\n");
|
printf("quit kill quests and exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* help for guest shell
|
||||||
|
*/
|
||||||
|
static void help_guest()
|
||||||
|
{
|
||||||
|
printf("addif <name> add an interface to the guest\n");
|
||||||
|
printf("delif <name> remove the interface\n");
|
||||||
|
printf("listif list guests interfaces\n");
|
||||||
|
printf("help show this help\n");
|
||||||
|
printf("quit quit the guest menu\n");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* start an UML guest
|
* start an UML guest
|
||||||
*/
|
*/
|
||||||
static void start(umli_t *umli, char *line)
|
static void start(dumm_t *dumm, char *line)
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
NAME = 0,
|
NAME = 0,
|
||||||
@@ -101,7 +130,7 @@ static void start(umli_t *umli, char *line)
|
|||||||
mem = 128;
|
mem = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (umli->start_guest(umli, name, kernel, master, mem))
|
if (dumm->start_guest(dumm, name, kernel, master, mem))
|
||||||
{
|
{
|
||||||
printf("starting guest '%s'\n", name);
|
printf("starting guest '%s'\n", name);
|
||||||
}
|
}
|
||||||
@@ -112,19 +141,187 @@ static void start(umli_t *umli, char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list running UML guests
|
* add an iface to a guest
|
||||||
*/
|
*/
|
||||||
static void guests(umli_t *umli)
|
static void add_if(guest_t *guest, char *name)
|
||||||
{
|
{
|
||||||
iterator_t *iterator;
|
iface_t *iface;
|
||||||
guest_t *guest;
|
|
||||||
|
|
||||||
iterator = umli->create_guest_iterator(umli);
|
iface = guest->create_iface(guest, name);
|
||||||
while (iterator->iterate(iterator, (void**)&guest))
|
if (iface)
|
||||||
{
|
{
|
||||||
printf("%s\n", guest->get_name(guest));
|
printf("created guest interface '%s' connected to '%s'\n",
|
||||||
|
iface->get_guest(iface), iface->get_host(iface));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("failed to create guest interface\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* delete an iface from a guest
|
||||||
|
*/
|
||||||
|
static void del_if(guest_t *guest, char *name)
|
||||||
|
{
|
||||||
|
iface_t *iface;
|
||||||
|
iterator_t *iterator;
|
||||||
|
bool found = FALSE;
|
||||||
|
|
||||||
|
iterator = guest->create_iface_iterator(guest);
|
||||||
|
while (iterator->iterate(iterator, (void**)&iface))
|
||||||
|
{
|
||||||
|
if (streq(name, iface->get_guest(iface)))
|
||||||
|
{
|
||||||
|
iterator->remove(iterator);
|
||||||
|
printf("removing interface '%s' ('%s') from %s\n",
|
||||||
|
iface->get_guest(iface), iface->get_host(iface),
|
||||||
|
guest->get_name(guest));
|
||||||
|
iface->destroy(iface);
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
printf("guest '%s' has no interface named '%s'\n",
|
||||||
|
guest->get_name(guest), name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list interfaces on a guest
|
||||||
|
*/
|
||||||
|
static void list_if(guest_t *guest)
|
||||||
|
{
|
||||||
|
iface_t *iface;
|
||||||
|
iterator_t *iterator;
|
||||||
|
|
||||||
|
iterator = guest->create_iface_iterator(guest);
|
||||||
|
while (iterator->iterate(iterator, (void**)&iface))
|
||||||
|
{
|
||||||
|
printf("'%s' => '%s'\n", iface->get_guest(iface), iface->get_host(iface));
|
||||||
|
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* subshell for guests
|
||||||
|
*/
|
||||||
|
static void guest(dumm_t *dumm, char *name)
|
||||||
|
{
|
||||||
|
char *line = NULL;
|
||||||
|
char prompt[32];
|
||||||
|
int len;
|
||||||
|
iterator_t *iterator;
|
||||||
|
guest_t *guest;
|
||||||
|
bool found = FALSE;
|
||||||
|
|
||||||
|
iterator = dumm->create_guest_iterator(dumm);
|
||||||
|
while (iterator->iterate(iterator, (void**)&guest))
|
||||||
|
{
|
||||||
|
if (streq(name, guest->get_name(guest)))
|
||||||
|
{
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
printf("guest '%s' not found\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = snprintf(prompt, sizeof(prompt), "dumm@%s# ", name);
|
||||||
|
if (len < 0 || len >= sizeof(prompt))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
QUIT = 0,
|
||||||
|
HELP,
|
||||||
|
ADDIF,
|
||||||
|
DELIF,
|
||||||
|
LISTIF,
|
||||||
|
};
|
||||||
|
char *const opts[] = {
|
||||||
|
[QUIT] = "quit",
|
||||||
|
[HELP] = "help",
|
||||||
|
[ADDIF] = "addif",
|
||||||
|
[DELIF] = "delif",
|
||||||
|
[LISTIF] = "listif",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *pos, *value;
|
||||||
|
|
||||||
|
free(line);
|
||||||
|
line = readline(prompt);
|
||||||
|
if (line == NULL || *line == '\0')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
add_history(line);
|
||||||
|
pos = line;
|
||||||
|
while (*pos != '\0')
|
||||||
|
{
|
||||||
|
if (*pos == ' ')
|
||||||
|
{
|
||||||
|
*pos = ',';
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
pos = line;
|
||||||
|
switch (getsubopt(&pos, opts, &value))
|
||||||
|
{
|
||||||
|
case QUIT:
|
||||||
|
free(line);
|
||||||
|
break;
|
||||||
|
case HELP:
|
||||||
|
help_guest();
|
||||||
|
continue;
|
||||||
|
case ADDIF:
|
||||||
|
add_if(guest, pos);
|
||||||
|
continue;
|
||||||
|
case DELIF:
|
||||||
|
del_if(guest, pos);
|
||||||
|
continue;
|
||||||
|
case LISTIF:
|
||||||
|
list_if(guest);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
printf("command unknown: '%s'\n", line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list running UML guests
|
||||||
|
*/
|
||||||
|
static void list(dumm_t *dumm)
|
||||||
|
{
|
||||||
|
iterator_t *guests, *ifaces;
|
||||||
|
guest_t *guest;
|
||||||
|
iface_t *iface;
|
||||||
|
|
||||||
|
guests = dumm->create_guest_iterator(dumm);
|
||||||
|
while (guests->iterate(guests, (void**)&guest))
|
||||||
|
{
|
||||||
|
printf("%s\n", guest->get_name(guest));
|
||||||
|
ifaces = guest->create_iface_iterator(guest);
|
||||||
|
while (ifaces->iterate(ifaces, (void**)&iface))
|
||||||
|
{
|
||||||
|
printf(" '%s' => '%s'\n", iface->get_guest(iface), iface->get_host(iface));
|
||||||
|
}
|
||||||
|
ifaces->destroy(ifaces);
|
||||||
|
}
|
||||||
|
guests->destroy(guests);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,7 +329,7 @@ static void guests(umli_t *umli)
|
|||||||
*/
|
*/
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
umli_t *umli;
|
dumm_t *dumm;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
@@ -164,7 +361,7 @@ int main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
umli = umli_create();
|
dumm = dumm_create();
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
@@ -172,13 +369,15 @@ int main(int argc, char *argv[])
|
|||||||
QUIT = 0,
|
QUIT = 0,
|
||||||
HELP,
|
HELP,
|
||||||
START,
|
START,
|
||||||
GUESTS,
|
LIST,
|
||||||
|
GUEST,
|
||||||
};
|
};
|
||||||
char *const opts[] = {
|
char *const opts[] = {
|
||||||
[QUIT] = "quit",
|
[QUIT] = "quit",
|
||||||
[HELP] = "help",
|
[HELP] = "help",
|
||||||
[START] = "start",
|
[START] = "start",
|
||||||
[GUESTS] = "guests",
|
[LIST] = "list",
|
||||||
|
[GUEST] = "guest",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
char *pos, *value;
|
char *pos, *value;
|
||||||
@@ -210,10 +409,13 @@ int main(int argc, char *argv[])
|
|||||||
help();
|
help();
|
||||||
continue;
|
continue;
|
||||||
case START:
|
case START:
|
||||||
start(umli, pos);
|
start(dumm, pos);
|
||||||
continue;
|
continue;
|
||||||
case GUESTS:
|
case LIST:
|
||||||
guests(umli);
|
list(dumm);
|
||||||
|
continue;
|
||||||
|
case GUEST:
|
||||||
|
guest(dumm, pos);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
printf("command unknown: '%s'\n", line);
|
printf("command unknown: '%s'\n", line);
|
||||||
@@ -221,7 +423,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
umli->destroy(umli);
|
dumm->destroy(dumm);
|
||||||
clear_history();
|
clear_history();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
* Copyright (C) 2001-2004 Jeff Dike
|
||||||
|
*
|
||||||
|
* Based on the "uml_mconsole" utilty from Jeff Dike.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "mconsole.h"
|
||||||
|
|
||||||
|
#define MCONSOLE_MAGIC 0xcafebabe
|
||||||
|
#define MCONSOLE_VERSION 2
|
||||||
|
#define MCONSOLE_MAX_DATA 512
|
||||||
|
|
||||||
|
typedef struct private_mconsole_t private_mconsole_t;
|
||||||
|
|
||||||
|
struct private_mconsole_t {
|
||||||
|
/** public interface */
|
||||||
|
mconsole_t public;
|
||||||
|
/** mconsole socket */
|
||||||
|
int socket;
|
||||||
|
/** address of uml socket */
|
||||||
|
struct sockaddr_un uml;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* send a request to UML using mconsole
|
||||||
|
*/
|
||||||
|
static bool request(private_mconsole_t *this, char *command)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
u_int32_t magic;
|
||||||
|
u_int32_t version;
|
||||||
|
u_int32_t len;
|
||||||
|
char data[MCONSOLE_MAX_DATA];
|
||||||
|
} request;
|
||||||
|
struct {
|
||||||
|
u_int32_t err;
|
||||||
|
u_int32_t more;
|
||||||
|
u_int32_t len;
|
||||||
|
char data[MCONSOLE_MAX_DATA];
|
||||||
|
} reply;
|
||||||
|
bool first = TRUE, good = TRUE;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
|
request.magic = MCONSOLE_MAGIC;
|
||||||
|
request.version = MCONSOLE_VERSION;
|
||||||
|
request.len = min(strlen(command), sizeof(reply.data) - 1);
|
||||||
|
strncpy(request.data, command, request.len);
|
||||||
|
|
||||||
|
if (sendto(this->socket, &request, sizeof(request), 0,
|
||||||
|
(struct sockaddr*)&this->uml, sizeof(this->uml)) < 0)
|
||||||
|
{
|
||||||
|
DBG1("sending mconsole command to UML failed: %m");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
len = recvfrom(this->socket, &reply, sizeof(reply), 0, NULL, 0);
|
||||||
|
if (len < 0)
|
||||||
|
{
|
||||||
|
DBG1("receiving from mconsole failed: %m");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (first && reply.err)
|
||||||
|
{
|
||||||
|
good = FALSE;
|
||||||
|
DBG1("received error from UML mconsole: %s", reply.data);
|
||||||
|
}
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
while (reply.more);
|
||||||
|
return good;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of mconsole_t.add_iface.
|
||||||
|
*/
|
||||||
|
static bool add_iface(private_mconsole_t *this, char *guest, char *host)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = snprintf(buf, sizeof(buf), "config %s=tuntap,%s", guest, host);
|
||||||
|
if (len < 0 || len >= sizeof(buf))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return request(this, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of mconsole_t.del_iface.
|
||||||
|
*/
|
||||||
|
static bool del_iface(private_mconsole_t *this, char *guest)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = snprintf(buf, sizeof(buf), "remove %s", guest);
|
||||||
|
if (len < 0 || len >= sizeof(buf))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return request(this, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of mconsole_t.destroy.
|
||||||
|
*/
|
||||||
|
static void destroy(private_mconsole_t *this)
|
||||||
|
{
|
||||||
|
close(this->socket);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create the mconsole instance
|
||||||
|
*/
|
||||||
|
mconsole_t *mconsole_create(char *sock)
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
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.destroy = (void*)destroy;
|
||||||
|
|
||||||
|
this->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||||
|
if (this->socket < 0)
|
||||||
|
{
|
||||||
|
DBG1("opening mconsole socket failed: %m");
|
||||||
|
free(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
sprintf(&addr.sun_path[1], "%5d", getpid());
|
||||||
|
if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||||
|
{
|
||||||
|
DBG1("binding mconsole socket failed: %m");
|
||||||
|
destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(&this->uml, 0, sizeof(this->uml));
|
||||||
|
this->uml.sun_family = AF_UNIX;
|
||||||
|
strncpy(this->uml.sun_path, sock, sizeof(this->uml.sun_path));
|
||||||
|
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program 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 General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MCONSOLE_H
|
||||||
|
#define MCONSOLE_H
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
typedef struct mconsole_t mconsole_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief UML mconsole, change running UML configuration using mconsole.
|
||||||
|
*/
|
||||||
|
struct mconsole_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a guest interface and connect it to tap host interface.
|
||||||
|
*
|
||||||
|
* @param guest name of the interface to create in the guest
|
||||||
|
* @param host name of the tap device to connect guest to
|
||||||
|
* @return TRUE if interface created
|
||||||
|
*/
|
||||||
|
bool (*add_iface)(mconsole_t *this, char *guest, char *host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete a guest interface.
|
||||||
|
*
|
||||||
|
* @param guest name of the interface to delete on the guest
|
||||||
|
* @return TRUE if interface deleted
|
||||||
|
*/
|
||||||
|
bool (*del_iface)(mconsole_t *this, char *guest);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy the mconsole instance
|
||||||
|
*/
|
||||||
|
void (*destroy) (mconsole_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new mconsole connection to a guest.
|
||||||
|
*
|
||||||
|
* @param socket guests mconsole socket
|
||||||
|
* @return mconsole instance, or NULL if failed
|
||||||
|
*/
|
||||||
|
mconsole_t *mconsole_create(char *socket);
|
||||||
|
|
||||||
|
#endif /* MCONSOLE_H */
|
||||||
|
|
||||||
Reference in New Issue
Block a user