diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-10-26 14:10:02 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-10-26 14:10:02 +0000 |
commit | 49104abddf3d71d5abf5cf75dc7f95fa6c55fa63 (patch) | |
tree | 28f7a72e5dec4abf908fd7874bdab776281310bc /src/dumm/iface.c | |
parent | 7b0305f59ddab9ea026b202a8c569912e5bf9a90 (diff) | |
download | vyos-strongswan-49104abddf3d71d5abf5cf75dc7f95fa6c55fa63.tar.gz vyos-strongswan-49104abddf3d71d5abf5cf75dc7f95fa6c55fa63.zip |
[svn-upgrade] Integrating new upstream version, strongswan (4.1.8)
Diffstat (limited to 'src/dumm/iface.c')
-rw-r--r-- | src/dumm/iface.c | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/dumm/iface.c b/src/dumm/iface.c new file mode 100644 index 000000000..3c1bfc470 --- /dev/null +++ b/src/dumm/iface.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2007 Martin Willi + * Hochschule fuer Technik Rapperswil + * Copyright (C) 2002 Jeff Dike + * + * Based on the "tunctl" utility 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 <stdio.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 *guestif; + /** device name at host (tap0) */ + char *hostif; + /** bridge this interface is attached to */ + bridge_t *bridge; + /** mconsole for guest */ + mconsole_t *mconsole; +}; + +/** + * Implementation of iface_t.get_guestif. + */ +static char* get_guestif(private_iface_t *this) +{ + return this->guestif; +} + +/** + * Implementation of iface_t.get_hostif. + */ +static char* get_hostif(private_iface_t *this) +{ + return this->hostif; +} + +/** + * Implementation of iface_t.set_bridge. + */ +static void set_bridge(private_iface_t *this, bridge_t *bridge) +{ + this->bridge = bridge; +} + +/** + * destroy the tap device + */ +static bool destroy_tap(private_iface_t *this) +{ + struct ifreq ifr; + int tap; + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strncpy(ifr.ifr_name, this->hostif, sizeof(ifr.ifr_name) - 1); + + tap = open(TAP_DEVICE, O_RDWR); + if (tap < 0) + { + DBG1("unable to open tap device %s: %m", TAP_DEVICE); + return FALSE; + } + if (ioctl(tap, TUNSETIFF, &ifr) < 0 || + ioctl(tap, TUNSETPERSIST, 0) < 0) + { + DBG1("removing %s failed: %m", this->hostif); + close(tap); + return FALSE; + } + close(tap); + return TRUE; +} + +/** + * create the tap device + */ +static char* create_tap(private_iface_t *this, char *guest) +{ + 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); + + tap = open(TAP_DEVICE, O_RDWR); + if (tap < 0) + { + DBG1("unable to open tap device %s: %m", TAP_DEVICE); + return NULL; + } + if (ioctl(tap, TUNSETIFF, &ifr) < 0 || + ioctl(tap, TUNSETPERSIST, 1) < 0 || + ioctl(tap, TUNSETOWNER, 0)) + { + DBG1("creating new tap device failed: %m"); + close(tap); + return NULL; + } + close(tap); + return strdup(ifr.ifr_name); +} + +/** + * Implementation of iface_t.destroy. + */ +static void destroy(private_iface_t *this) +{ + if (this->bridge) + { + this->bridge->disconnect_iface(this->bridge, &this->public); + } + this->mconsole->del_iface(this->mconsole, this->guestif); + destroy_tap(this); + free(this->guestif); + free(this->hostif); + free(this); +} + +/** + * create the iface instance + */ +iface_t *iface_create(char *guest, char *guestif, 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.set_bridge = (void(*)(iface_t*, bridge_t*))set_bridge; + this->public.destroy = (void*)destroy; + + this->mconsole = mconsole; + this->guestif = strdup(guestif); + this->hostif = create_tap(this, guest); + this->bridge = NULL; + if (this->hostif == NULL) + { + destroy_tap(this); + free(this->guestif); + free(this); + return NULL; + } + if (!this->mconsole->add_iface(this->mconsole, this->guestif, this->hostif)) + { + DBG1("creating interface '%s' in guest failed", this->guestif); + destroy_tap(this); + free(this->guestif); + free(this->hostif); + free(this); + return NULL; + } + return &this->public; +} + |