added dynamic interface manipulation for guests

management of tap devices on the host
This commit is contained in:
Martin Willi
2007-07-25 13:23:45 +00:00
parent 5c7da9d402
commit f85fdda835
10 changed files with 886 additions and 38 deletions
+154
View File
@@ -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;
}