diff options
author | Martin Willi <martin@strongswan.org> | 2007-07-25 13:23:45 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2007-07-25 13:23:45 +0000 |
commit | f85fdda83598cdfde287ee0acb5581d9cb2f261b (patch) | |
tree | b83ef7735a7eb81b9ae447b8045b0e011eb92bba /src/dumm/guest.c | |
parent | 5c7da9d402a71992a5dc47c5ab25fd6f1479f5a7 (diff) | |
download | strongswan-f85fdda83598cdfde287ee0acb5581d9cb2f261b.tar.bz2 strongswan-f85fdda83598cdfde287ee0acb5581d9cb2f261b.tar.xz |
added dynamic interface manipulation for guests
management of tap devices on the host
Diffstat (limited to 'src/dumm/guest.c')
-rw-r--r-- | src/dumm/guest.c | 123 |
1 files changed, 108 insertions, 15 deletions
diff --git a/src/dumm/guest.c b/src/dumm/guest.c index 202882367..cdb97c7bd 100644 --- a/src/dumm/guest.c +++ b/src/dumm/guest.c @@ -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 #include <sys/types.h> @@ -10,27 +25,88 @@ #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; @@ -50,6 +126,9 @@ static char* write_arg(char **pos, size_t *left, char *format, ...) return res; } +/** + * Implementation of guest_t.start. + */ static bool start(private_guest_t *this) { 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, "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"); @@ -84,15 +163,30 @@ static bool start(private_guest_t *this) 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) @@ -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) { @@ -138,6 +232,7 @@ static bool umount_unionfs(char *name) } if (system(cmd) != 0) { + DBG1("unmounting guest unionfs for %s failed", name); return FALSE; } return TRUE; @@ -151,7 +246,6 @@ static bool mount_unionfs(char *name, char *master) 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)) @@ -160,7 +254,7 @@ static bool mount_unionfs(char *name, char *master) } 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; @@ -183,18 +277,21 @@ static int open_bootlog(char *name) 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); @@ -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); 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; } @@ -234,6 +325,8 @@ guest_t *guest_create(char *name, char *kernel, char *master, int mem) this->mem = mem; this->pid = 0; this->bootlog = open_bootlog(name); + this->mconsole = NULL; + this->ifaces = linked_list_create(); return &this->public; } |