diff options
Diffstat (limited to 'src/dumm/iface.c')
-rw-r--r-- | src/dumm/iface.c | 112 |
1 files changed, 102 insertions, 10 deletions
diff --git a/src/dumm/iface.c b/src/dumm/iface.c index b78c10bec..78c6c7c92 100644 --- a/src/dumm/iface.c +++ b/src/dumm/iface.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * Copyright (C) 2002 Jeff Dike @@ -25,6 +26,7 @@ #include <linux/if_tun.h> #include <debug.h> +#include <utils/linked_list.h> #include "iface.h" @@ -39,12 +41,14 @@ struct private_iface_t { char *hostif; /** bridge this interface is attached to */ bridge_t *bridge; + /** guest this interface is attached to */ + guest_t *guest; /** mconsole for guest */ mconsole_t *mconsole; }; /** - * bring an interface up or down + * bring an interface up or down (host side) */ bool iface_control(char *name, bool up) { @@ -96,14 +100,93 @@ static char* get_hostif(private_iface_t *this) } /** + * Implementation of iface_t.add_address + */ +static bool add_address(private_iface_t *this, host_t *addr) +{ + return (this->guest->exec(this->guest, NULL, NULL, "ip addr add %H dev %s", + addr, this->guestif) == 0); +} + +/** + * compile a list of the addresses of an interface + */ +static void compile_address_list(linked_list_t *list, char *address) +{ + host_t *host = host_create_from_string(address, 0); + if (host) + { + list->insert_last(list, host); + } +} + +/** + * delete the list of addresses + */ +static void destroy_address_list(linked_list_t *list) +{ + list->destroy_offset(list, offsetof(host_t, destroy)); +} + +/** + * Implementation of iface_t.create_address_enumerator + */ +static enumerator_t* create_address_enumerator(private_iface_t *this) +{ + linked_list_t *addresses = linked_list_create(); + this->guest->exec_str(this->guest, (void(*)(void*,char*))compile_address_list, + TRUE, addresses, + "ip addr list dev %s scope global | " + "grep '^ \\+\\(inet6\\? \\)' | " + "awk -F '( +|/)' '{ print $3 }'", this->guestif); + return enumerator_create_cleaner(addresses->create_enumerator(addresses), + (void(*)(void*))destroy_address_list, addresses); +} + +/** + * Implementation of iface_t.delete_address + */ +static bool delete_address(private_iface_t *this, host_t *addr) +{ + return (this->guest->exec(this->guest, NULL, NULL, + "ip addr del %H dev %s", addr, this->guestif) == 0); +} + +/** * Implementation of iface_t.set_bridge. */ static void set_bridge(private_iface_t *this, bridge_t *bridge) { + if (this->bridge == NULL && bridge) + { + this->guest->exec(this->guest, NULL, NULL, + "ip link set %s up", this->guestif); + } + else if (this->bridge && bridge == NULL) + { + this->guest->exec(this->guest, NULL, NULL, + "ip link set %s down", this->guestif); + } this->bridge = bridge; } /** + * Implementation of iface_t.get_bridge + */ +static bridge_t *get_bridge(private_iface_t *this) +{ + return this->bridge; +} + +/** + * Implementation of iface_t.get_guest + */ +static guest_t* get_guest(private_iface_t *this) +{ + return this->guest; +} + +/** * destroy the tap device */ static bool destroy_tap(private_iface_t *this) @@ -139,14 +222,15 @@ static bool destroy_tap(private_iface_t *this) /** * create the tap device */ -static char* create_tap(private_iface_t *this, char *guest) +static char* create_tap(private_iface_t *this) { struct ifreq ifr; int tap; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s-%s", guest, this->guestif); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s-%s", + this->guest->get_name(this->guest), this->guestif); tap = open(TAP_DEVICE, O_RDWR); if (tap < 0) @@ -175,6 +259,8 @@ static void destroy(private_iface_t *this) { this->bridge->disconnect_iface(this->bridge, &this->public); } + /* TODO: iface mgmt is not blocking yet, so wait some ticks */ + usleep(50000); this->mconsole->del_iface(this->mconsole, this->guestif); destroy_tap(this); free(this->guestif); @@ -185,18 +271,24 @@ static void destroy(private_iface_t *this) /** * create the iface instance */ -iface_t *iface_create(char *guest, char *guestif, mconsole_t *mconsole) +iface_t *iface_create(char *name, guest_t *guest, mconsole_t *mconsole) { private_iface_t *this = malloc_thing(private_iface_t); this->public.get_hostif = (char*(*)(iface_t*))get_hostif; this->public.get_guestif = (char*(*)(iface_t*))get_guestif; + this->public.add_address = (bool(*)(iface_t*, host_t *addr))add_address; + this->public.create_address_enumerator = (enumerator_t*(*)(iface_t*))create_address_enumerator; + this->public.delete_address = (bool(*)(iface_t*, host_t *addr))delete_address; this->public.set_bridge = (void(*)(iface_t*, bridge_t*))set_bridge; + this->public.get_bridge = (bridge_t*(*)(iface_t*))get_bridge; + this->public.get_guest = (guest_t*(*)(iface_t*))get_guest; this->public.destroy = (void*)destroy; this->mconsole = mconsole; - this->guestif = strdup(guestif); - this->hostif = create_tap(this, guest); + this->guestif = strdup(name); + this->guest = guest; + this->hostif = create_tap(this); this->bridge = NULL; if (this->hostif == NULL) { @@ -205,10 +297,6 @@ 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); @@ -218,6 +306,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); + } return &this->public; } |