-dumm: dumm.c dumm.h guest.c guest.h main.c
- gcc -o dumm dumm.c guest.c main.c -lreadline -lstrongswan -I../libstrongswan/ -g -Wall
+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 iface.c mconsole.c main.c -lreadline -lstrongswan -I../libstrongswan/ -g -Wall
+/*
+ * 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 <debug.h>
+/*
+ * 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
#define DUMM_H
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();
#endif /* DUMM_H */
+
+/*
+ * 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
#include <sys/types.h>
#include <signal.h>
#include <debug.h>
+#include <utils/linked_list.h>
#include "dumm.h"
#include "guest.h"
+#include "mconsole.h"
typedef struct private_guest_t private_guest_t;
struct private_guest_t {
+ /** implemented public interface */
guest_t public;
+ /** name of the guest */
char *name;
+ /** kernel to boot for guest */
char *kernel;
+ /** read only master filesystem guest uses */
char *master;
+ /** amount of memory for guest, in MB */
int mem;
+ /** pid of guest child process */
int pid;
+ /** log file for console 0 */
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)
{
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, ...)
{
size_t len;
return res;
}
+/**
+ * Implementation of guest_t.start.
+ */
static bool start(private_guest_t *this)
{
char buf[1024];
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, "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, "con1=fd:0,fd:1");
args[i++] = write_arg(&pos, &left, "con3=null,null");
dup2(open("/dev/null", 0), 1);
dup2(open("/dev/null", 0), 2);
execvp(args[0], args);
+ DBG1("starting UML kernel '%s' failed", args[0]);
exit(1);
case -1:
this->pid = 0;
return FALSE;
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)
{
if (this->pid)
}
/**
- * create a directory
+ * Check if directory exists, create otherwise
*/
static bool makedir(char *dir, char *name)
{
}
if (system(cmd) != 0)
{
+ DBG1("unmounting guest unionfs for %s failed", name);
return FALSE;
}
return TRUE;
char cmd[256];
size_t len;
- /* mount unionfs */
len = snprintf(cmd, sizeof(cmd), "unionfs %s/%s:%s %s/%s",
HOST_DIR, name, master, MOUNT_DIR, name);
if (len < 0 || len >= sizeof(cmd))
}
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 TRUE;
fd = open(blg, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1)
{
+ DBG1("opening bootlog '%s' for %s failed, using stdout", blg, name);
return 1;
}
return fd;
}
/**
- * stop guest, unmount mounts
+ * Implementation of guest_t.destroy.
*/
static void destroy(private_guest_t *this)
{
stop(this);
umount_unionfs(this->name);
+ this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
+ DESTROY_IF(this->mconsole);
free(this->name);
free(this->kernel);
free(this->master);
private_guest_t *this = malloc_thing(private_guest_t);
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.stop = (void*)stop;
this->public.destroy = (void*)destroy;
if (!makedir(HOST_DIR, name) || !makedir(MOUNT_DIR, name) ||
- !makedir(RUN_DIR, name))
- {
- DBG1("creating guest directories for %s failed failed.", name);
- free(this);
- return NULL;
- }
-
- if (!mount_unionfs(name, master))
+ !makedir(RUN_DIR, name) || !mount_unionfs(name, master))
{
- DBG1("mounting guest unionfs for %s failed.", name);
free(this);
return NULL;
}
this->mem = mem;
this->pid = 0;
this->bootlog = open_bootlog(name);
+ this->mconsole = NULL;
+ this->ifaces = linked_list_create();
return &this->public;
}
+/*
+ * 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
#define GUEST_H
#include <library.h>
-#include <utils/linked_list.h>
+#include <utils/iterator.h>
+
+#include "iface.h"
typedef struct guest_t guest_t;
+/**
+ * @brief A guest is a UML instance running on the host.
+ **/
struct guest_t {
+ /**
+ * @brief Get the name of this guest.
+ *
+ * @return name of the guest
+ */
char* (*get_name) (guest_t *this);
+ /**
+ * @brief Start the guest.
+ *
+ * @return TRUE if guest successfully started
+ */
bool (*start) (guest_t *this);
+ /**
+ * @brief Kill the guest.
+ *
+ * @return TRUE if guest was running and killed
+ */
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);
};
+/**
+ * @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);
-
#endif /* GUEST_H */
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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 */
+/*
+ * 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
#include <stdio.h>
}
/**
- * show usage information (commandline arguments)
+ * help for dumm root shell
*/
static void help()
{
printf(" kernel=<uml-kernel>\n");
printf(" master=<read-only root files>\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("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
*/
-static void start(umli_t *umli, char *line)
+static void start(dumm_t *dumm, char *line)
{
enum {
NAME = 0,
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);
}
}
/**
- * list running UML guests
+ * add an iface to a guest
+ */
+static void add_if(guest_t *guest, char *name)
+{
+ iface_t *iface;
+
+ iface = guest->create_iface(guest, name);
+ if (iface)
+ {
+ 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 guests(umli_t *umli)
+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);
+ 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 = umli->create_guest_iterator(umli);
+ iterator = dumm->create_guest_iterator(dumm);
while (iterator->iterate(iterator, (void**)&guest))
{
- printf("%s\n", guest->get_name(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);
}
/**
*/
int main(int argc, char *argv[])
{
- umli_t *umli;
+ dumm_t *dumm;
char *line = NULL;
while (TRUE)
break;
}
- umli = umli_create();
+ dumm = dumm_create();
while (TRUE)
{
QUIT = 0,
HELP,
START,
- GUESTS,
+ LIST,
+ GUEST,
};
char *const opts[] = {
[QUIT] = "quit",
[HELP] = "help",
[START] = "start",
- [GUESTS] = "guests",
+ [LIST] = "list",
+ [GUEST] = "guest",
NULL
};
char *pos, *value;
help();
continue;
case START:
- start(umli, pos);
+ start(dumm, pos);
+ continue;
+ case LIST:
+ list(dumm);
continue;
- case GUESTS:
- guests(umli);
+ case GUEST:
+ guest(dumm, pos);
continue;
default:
printf("command unknown: '%s'\n", line);
}
break;
}
- umli->destroy(umli);
+ dumm->destroy(dumm);
clear_history();
return 0;
}
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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 */
+