mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-11 07:55:58 -06:00
Core driver implementation with ebtables support
This patch implements the core driver and provides - management functionality for managing the filter XMLs - compiling the internal filter representation into ebtables rules - applying ebtables rules on a network (tap,macvtap) interface - tearing down ebtables rules that were applied on behalf of an interface - updating of filters while VMs are running and causing the firewalls to be rebuilt - other bits and pieces Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
This commit is contained in:
parent
e4e20423ff
commit
065b6571bf
12
configure.ac
12
configure.ac
@ -294,6 +294,9 @@ if test x"$with_rhel5_api" = x"yes"; then
|
||||
AC_DEFINE([WITH_RHEL5_API], [1], [whether building for the RHEL-5 API])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG([BASH_PATH], [bash], /bin/bash, [/bin:$PATH])
|
||||
AC_DEFINE_UNQUOTED([BASH_PATH], "$BASH_PATH", [path to bash binary])
|
||||
|
||||
AC_PATH_PROG([IPTABLES_PATH], [iptables], /sbin/iptables, [/usr/sbin:$PATH])
|
||||
AC_DEFINE_UNQUOTED([IPTABLES_PATH], "$IPTABLES_PATH", [path to iptables binary])
|
||||
|
||||
@ -1268,6 +1271,15 @@ if test "$with_secrets" = "yes" ; then
|
||||
fi
|
||||
AM_CONDITIONAL([WITH_SECRETS], [test "$with_secrets" = "yes"])
|
||||
|
||||
with_nwfilter=yes
|
||||
if test "$with_libvirtd" = "no"; then
|
||||
with_nwfilter=no
|
||||
fi
|
||||
if test "$with_nwfilter" = "yes" ; then
|
||||
AC_DEFINE([WITH_NWFILTER], 1, [whether local network filter management driver is available])
|
||||
fi
|
||||
AM_CONDITIONAL([WITH_NWFILTER], [test "$with_nwfilter" = "yes"])
|
||||
|
||||
|
||||
AC_ARG_WITH([storage-fs],
|
||||
AC_HELP_STRING([--with-storage-fs], [with FileSystem backend for the storage driver @<:@default=check@:>@]),[],[with_storage_fs=check])
|
||||
|
@ -116,6 +116,10 @@ endif
|
||||
if WITH_SECRETS
|
||||
libvirtd_LDADD += ../src/libvirt_driver_secret.la
|
||||
endif
|
||||
|
||||
if WITH_NWFILTER
|
||||
libvirtd_LDADD += ../src/libvirt_driver_nwfilter.la
|
||||
endif
|
||||
endif
|
||||
|
||||
libvirtd_LDADD += ../src/libvirt.la
|
||||
|
@ -96,6 +96,9 @@
|
||||
# ifdef WITH_SECRETS
|
||||
# include "secret/secret_driver.h"
|
||||
# endif
|
||||
# ifdef WITH_NWFILTER
|
||||
# include "nwfilter/nwfilter_driver.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -876,6 +879,7 @@ static struct qemud_server *qemudInitialize(void) {
|
||||
virDriverLoadModule("lxc");
|
||||
virDriverLoadModule("uml");
|
||||
virDriverLoadModule("one");
|
||||
virDriverLoadModule("nwfilter");
|
||||
#else
|
||||
# ifdef WITH_NETWORK
|
||||
networkRegister();
|
||||
@ -892,6 +896,9 @@ static struct qemud_server *qemudInitialize(void) {
|
||||
# ifdef WITH_SECRETS
|
||||
secretRegister();
|
||||
# endif
|
||||
# ifdef WITH_NWFILTER
|
||||
nwfilterRegister();
|
||||
# endif
|
||||
# ifdef WITH_QEMU
|
||||
qemuRegister();
|
||||
# endif
|
||||
|
@ -28,6 +28,9 @@ src/node_device/node_device_driver.c
|
||||
src/node_device/node_device_linux_sysfs.c
|
||||
src/node_device/node_device_udev.c
|
||||
src/nodeinfo.c
|
||||
src/nwfilter/nwfilter_driver.c
|
||||
src/nwfilter/nwfilter_ebiptables_driver.c
|
||||
src/nwfilter/nwfilter_gentech_driver.c
|
||||
src/opennebula/one_conf.c
|
||||
src/opennebula/one_driver.c
|
||||
src/openvz/openvz_conf.c
|
||||
|
@ -175,6 +175,7 @@ skipped_types = {
|
||||
'virConnectDomainEventIOErrorCallback': "No function types in python",
|
||||
'virConnectDomainEventGraphicsCallback': "No function types in python",
|
||||
'virEventAddHandleFunc': "No function types in python",
|
||||
'virNWFilterPtr': "No function types in python",
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
@ -273,6 +274,7 @@ skip_impl = (
|
||||
'virConnectListStorageVols',
|
||||
'virConnectListDefinedStorageVols',
|
||||
'virConnectListDefinedInterfaces',
|
||||
'virConnectListNWFilters',
|
||||
'virConnGetLastError',
|
||||
'virGetLastError',
|
||||
'virDomainGetInfo',
|
||||
|
@ -284,6 +284,11 @@ STORAGE_DRIVER_DISK_SOURCES = \
|
||||
STORAGE_HELPER_DISK_SOURCES = \
|
||||
storage/parthelper.c
|
||||
|
||||
# Network filters
|
||||
NWFILTER_DRIVER_SOURCES = \
|
||||
nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \
|
||||
nwfilter/nwfilter_gentech_driver.c \
|
||||
nwfilter/nwfilter_ebiptables_driver.c
|
||||
|
||||
# Security framework and drivers for various models
|
||||
SECURITY_DRIVER_SOURCES = \
|
||||
@ -727,6 +732,22 @@ endif
|
||||
endif
|
||||
|
||||
|
||||
if WITH_NWFILTER
|
||||
if WITH_DRIVER_MODULES
|
||||
mod_LTLIBRARIES += libvirt_driver_nwfilter.la
|
||||
else
|
||||
libvirt_la_LIBADD += libvirt_driver_nwfilter.la
|
||||
noinst_LTLIBRARIES += libvirt_driver_nwfilter.la
|
||||
endif
|
||||
libvirt_driver_nwfilter_la_CFLAGS = \
|
||||
-I@top_srcdir@/src/conf
|
||||
if WITH_DRIVER_MODULES
|
||||
libvirt_driver_nwfilter_la_LDFLAGS = -module -avoid-version ../gnulib/lib/libgnu.la
|
||||
endif
|
||||
libvirt_driver_nwfilter_la_SOURCES = $(NWFILTER_DRIVER_SOURCES)
|
||||
endif
|
||||
|
||||
|
||||
libvirt_driver_security_la_SOURCES = $(SECURITY_DRIVER_SOURCES)
|
||||
noinst_LTLIBRARIES += libvirt_driver_security.la
|
||||
libvirt_la_LIBADD += libvirt_driver_security.la
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "nwfilter_params.h"
|
||||
#include "nwfilter_conf.h"
|
||||
#include "domain_conf.h"
|
||||
#include "nwfilter/nwfilter_gentech_driver.h"
|
||||
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_NWFILTER
|
||||
@ -1605,10 +1606,42 @@ struct cbStruct {
|
||||
};
|
||||
|
||||
static void
|
||||
virNWFilterDomainFWUpdateCB(void *payload ATTRIBUTE_UNUSED,
|
||||
virNWFilterDomainFWUpdateCB(void *payload,
|
||||
const char *name ATTRIBUTE_UNUSED,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
void *data)
|
||||
{
|
||||
virDomainObjPtr obj = payload;
|
||||
virDomainDefPtr vm = obj->def;
|
||||
struct cbStruct *cb = data;
|
||||
int i;
|
||||
|
||||
virDomainObjLock(obj);
|
||||
|
||||
if (virDomainObjIsActive(obj)) {
|
||||
for (i = 0; i < vm->nnets; i++) {
|
||||
virDomainNetDefPtr net = vm->nets[i];
|
||||
if ((net->filter) && (net->ifname)) {
|
||||
switch (cb->step) {
|
||||
case STEP_APPLY_NEW:
|
||||
cb->err = virNWFilterUpdateInstantiateFilter(cb->conn,
|
||||
net);
|
||||
break;
|
||||
|
||||
case STEP_TEAR_NEW:
|
||||
cb->err = virNWFilterRollbackUpdateFilter(cb->conn, net);
|
||||
break;
|
||||
|
||||
case STEP_TEAR_OLD:
|
||||
cb->err = virNWFilterTearOldFilter(cb->conn, net);
|
||||
break;
|
||||
}
|
||||
if (cb->err)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virDomainObjUnlock(obj);
|
||||
}
|
||||
|
||||
|
||||
|
@ -449,6 +449,42 @@ virNodeDeviceGetWWNs;
|
||||
virNodeDeviceGetParentHost;
|
||||
|
||||
|
||||
# nwfilter_conf.h
|
||||
virNWFilterPoolLoadAllConfigs;
|
||||
virNWFilterPoolObjAssignDef;
|
||||
virNWFilterPoolObjSaveDef;
|
||||
virNWFilterPoolObjFindByName;
|
||||
virNWFilterPoolObjFindByUUID;
|
||||
virNWFilterPoolObjLock;
|
||||
virNWFilterPoolObjUnlock;
|
||||
virNWFilterPoolObjRemove;
|
||||
virNWFilterDefFree;
|
||||
virNWFilterDefParseString;
|
||||
virNWFilterPoolObjDeleteDef;
|
||||
virNWFilterPoolObjListFree;
|
||||
virNWFilterDefFormat;
|
||||
virNWFilterChainSuffixTypeToString;
|
||||
virNWFilterRuleActionTypeToString;
|
||||
virNWFilterJumpTargetTypeToString;
|
||||
virNWFilterRegisterCallbackDriver;
|
||||
virNWFilterTestUnassignDef;
|
||||
virNWFilterConfLayerInit;
|
||||
virNWFilterConfLayerShutdown;
|
||||
|
||||
|
||||
#nwfilter_params.h
|
||||
virNWFilterHashTableCreate;
|
||||
virNWFilterHashTableFree;
|
||||
virNWFilterHashTablePut;
|
||||
virNWFilterHashTablePutAll;
|
||||
virNWFilterHashTableRemoveEntry;
|
||||
|
||||
|
||||
# nwfilter_gentech_driver.h
|
||||
virNWFilterInstantiateFilter;
|
||||
virNWFilterTeardownFilter;
|
||||
|
||||
|
||||
# pci.h
|
||||
pciGetDevice;
|
||||
pciFreeDevice;
|
||||
|
@ -380,4 +380,5 @@ LIBVIRT_0.7.8 {
|
||||
virNWFilterUndefine;
|
||||
} LIBVIRT_0.7.7;
|
||||
|
||||
|
||||
# .... define new API here using predicted next version number ....
|
||||
|
416
src/nwfilter/nwfilter_driver.c
Normal file
416
src/nwfilter/nwfilter_driver.c
Normal file
@ -0,0 +1,416 @@
|
||||
/*
|
||||
* nwfilter_driver.c: core driver for network filter APIs
|
||||
* (based on storage_driver.c)
|
||||
*
|
||||
* Copyright (C) 2006-2009 Red Hat, Inc.
|
||||
* Copyright (C) 2006-2008 Daniel P. Berrange
|
||||
* Copyright (C) 2010 IBM Corporation
|
||||
* Copyright (C) 2010 Stefan Berger
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||
* Stefan Berger <stefanb@us.ibm.com>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include "virterror_internal.h"
|
||||
#include "datatypes.h"
|
||||
#include "memory.h"
|
||||
#include "domain_conf.h"
|
||||
#include "nwfilter_driver.h"
|
||||
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_NWFILTER
|
||||
|
||||
#define nwfilterLog(msg...) fprintf(stderr, msg)
|
||||
|
||||
|
||||
static virNWFilterDriverStatePtr driverState;
|
||||
|
||||
static int nwfilterDriverShutdown(void);
|
||||
|
||||
static void nwfilterDriverLock(virNWFilterDriverStatePtr driver)
|
||||
{
|
||||
virMutexLock(&driver->lock);
|
||||
}
|
||||
static void nwfilterDriverUnlock(virNWFilterDriverStatePtr driver)
|
||||
{
|
||||
virMutexUnlock(&driver->lock);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNWFilterStartup:
|
||||
*
|
||||
* Initialization function for the QEmu daemon
|
||||
*/
|
||||
static int
|
||||
nwfilterDriverStartup(int privileged) {
|
||||
char *base = NULL;
|
||||
|
||||
if (virNWFilterConfLayerInit() < 0)
|
||||
return -1;
|
||||
|
||||
if (VIR_ALLOC(driverState) < 0)
|
||||
goto alloc_err_exit;
|
||||
|
||||
if (virMutexInit(&driverState->lock) < 0)
|
||||
goto alloc_err_exit;
|
||||
|
||||
nwfilterDriverLock(driverState);
|
||||
|
||||
if (privileged) {
|
||||
if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
|
||||
goto out_of_memory;
|
||||
} else {
|
||||
uid_t uid = geteuid();
|
||||
char *userdir = virGetUserDirectory(uid);
|
||||
|
||||
if (!userdir)
|
||||
goto error;
|
||||
|
||||
if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
|
||||
nwfilterLog("out of memory in virAsprintf");
|
||||
VIR_FREE(userdir);
|
||||
goto out_of_memory;
|
||||
}
|
||||
VIR_FREE(userdir);
|
||||
}
|
||||
|
||||
if (virAsprintf(&driverState->configDir,
|
||||
"%s/nwfilter", base) == -1)
|
||||
goto out_of_memory;
|
||||
|
||||
VIR_FREE(base);
|
||||
|
||||
if (virNWFilterPoolLoadAllConfigs(NULL,
|
||||
&driverState->pools,
|
||||
driverState->configDir) < 0)
|
||||
goto error;
|
||||
|
||||
nwfilterDriverUnlock(driverState);
|
||||
|
||||
return 0;
|
||||
|
||||
out_of_memory:
|
||||
nwfilterLog("virNWFilterStartup: out of memory");
|
||||
|
||||
error:
|
||||
VIR_FREE(base);
|
||||
nwfilterDriverUnlock(driverState);
|
||||
nwfilterDriverShutdown();
|
||||
|
||||
alloc_err_exit:
|
||||
virNWFilterConfLayerShutdown();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virNWFilterReload:
|
||||
*
|
||||
* Function to restart the nwfilter driver, it will recheck the configuration
|
||||
* files and update its state
|
||||
*/
|
||||
static int
|
||||
nwfilterDriverReload(void) {
|
||||
if (!driverState) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nwfilterDriverLock(driverState);
|
||||
virNWFilterPoolLoadAllConfigs(NULL,
|
||||
&driverState->pools,
|
||||
driverState->configDir);
|
||||
nwfilterDriverUnlock(driverState);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* virNWFilterActive:
|
||||
*
|
||||
* Checks if the nwfilter driver is active, i.e. has an active pool
|
||||
*
|
||||
* Returns 1 if active, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
nwfilterDriverActive(void) {
|
||||
if (!driverState->pools.count)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* virNWFilterShutdown:
|
||||
*
|
||||
* Shutdown the nwfilter driver, it will stop all active nwfilter pools
|
||||
*/
|
||||
static int
|
||||
nwfilterDriverShutdown(void) {
|
||||
if (!driverState)
|
||||
return -1;
|
||||
|
||||
nwfilterDriverLock(driverState);
|
||||
|
||||
/* free inactive pools */
|
||||
virNWFilterPoolObjListFree(&driverState->pools);
|
||||
|
||||
VIR_FREE(driverState->configDir);
|
||||
nwfilterDriverUnlock(driverState);
|
||||
virMutexDestroy(&driverState->lock);
|
||||
VIR_FREE(driverState);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static virNWFilterPtr
|
||||
nwfilterLookupByUUID(virConnectPtr conn,
|
||||
const unsigned char *uuid) {
|
||||
virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData;
|
||||
virNWFilterPoolObjPtr pool;
|
||||
virNWFilterPtr ret = NULL;
|
||||
|
||||
nwfilterDriverLock(driver);
|
||||
pool = virNWFilterPoolObjFindByUUID(&driver->pools, uuid);
|
||||
nwfilterDriverUnlock(driver);
|
||||
|
||||
if (!pool) {
|
||||
virNWFilterReportError(conn, VIR_ERR_NO_NWFILTER,
|
||||
"%s", _("no pool with matching uuid"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = virGetNWFilter(conn, pool->def->name, pool->def->uuid);
|
||||
|
||||
cleanup:
|
||||
if (pool)
|
||||
virNWFilterPoolObjUnlock(pool);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static virNWFilterPtr
|
||||
nwfilterLookupByName(virConnectPtr conn,
|
||||
const char *name) {
|
||||
virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData;
|
||||
virNWFilterPoolObjPtr pool;
|
||||
virNWFilterPtr ret = NULL;
|
||||
|
||||
nwfilterDriverLock(driver);
|
||||
pool = virNWFilterPoolObjFindByName(&driver->pools, name);
|
||||
nwfilterDriverUnlock(driver);
|
||||
|
||||
if (!pool) {
|
||||
virNWFilterReportError(conn, VIR_ERR_NO_NWFILTER,
|
||||
_("no pool with matching name '%s'"), name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = virGetNWFilter(conn, pool->def->name, pool->def->uuid);
|
||||
|
||||
cleanup:
|
||||
if (pool)
|
||||
virNWFilterPoolObjUnlock(pool);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static virDrvOpenStatus
|
||||
nwfilterOpen(virConnectPtr conn,
|
||||
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
||||
int flags ATTRIBUTE_UNUSED) {
|
||||
if (!driverState)
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
|
||||
conn->nwfilterPrivateData = driverState;
|
||||
return VIR_DRV_OPEN_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nwfilterClose(virConnectPtr conn) {
|
||||
conn->nwfilterPrivateData = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nwfilterNumNWFilters(virConnectPtr conn) {
|
||||
virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData;
|
||||
return driver->pools.count;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nwfilterListNWFilters(virConnectPtr conn,
|
||||
char **const names,
|
||||
int nnames) {
|
||||
virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData;
|
||||
int got = 0, i;
|
||||
|
||||
nwfilterDriverLock(driver);
|
||||
for (i = 0 ; i < driver->pools.count && got < nnames ; i++) {
|
||||
virNWFilterPoolObjLock(driver->pools.objs[i]);
|
||||
if (!(names[got] = strdup(driver->pools.objs[i]->def->name))) {
|
||||
virNWFilterPoolObjUnlock(driver->pools.objs[i]);
|
||||
virReportOOMError();
|
||||
goto cleanup;
|
||||
}
|
||||
got++;
|
||||
virNWFilterPoolObjUnlock(driver->pools.objs[i]);
|
||||
}
|
||||
nwfilterDriverUnlock(driver);
|
||||
return got;
|
||||
|
||||
cleanup:
|
||||
nwfilterDriverUnlock(driver);
|
||||
for (i = 0 ; i < got ; i++)
|
||||
VIR_FREE(names[i]);
|
||||
memset(names, 0, nnames * sizeof(*names));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static virNWFilterPtr
|
||||
nwfilterDefine(virConnectPtr conn,
|
||||
const char *xml,
|
||||
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||
virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData;
|
||||
virNWFilterDefPtr def;
|
||||
virNWFilterPoolObjPtr pool = NULL;
|
||||
virNWFilterPtr ret = NULL;
|
||||
|
||||
nwfilterDriverLock(driver);
|
||||
if (!(def = virNWFilterDefParseString(conn, xml)))
|
||||
goto cleanup;
|
||||
|
||||
if (!(pool = virNWFilterPoolObjAssignDef(conn, &driver->pools, def)))
|
||||
goto cleanup;
|
||||
|
||||
if (virNWFilterPoolObjSaveDef(conn, driver, pool, def) < 0) {
|
||||
virNWFilterPoolObjRemove(&driver->pools, pool);
|
||||
def = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
def = NULL;
|
||||
|
||||
ret = virGetNWFilter(conn, pool->def->name, pool->def->uuid);
|
||||
|
||||
cleanup:
|
||||
virNWFilterDefFree(def);
|
||||
if (pool)
|
||||
virNWFilterPoolObjUnlock(pool);
|
||||
nwfilterDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nwfilterUndefine(virNWFilterPtr obj) {
|
||||
virNWFilterDriverStatePtr driver = obj->conn->nwfilterPrivateData;
|
||||
virNWFilterPoolObjPtr pool;
|
||||
int ret = -1;
|
||||
|
||||
nwfilterDriverLock(driver);
|
||||
pool = virNWFilterPoolObjFindByUUID(&driver->pools, obj->uuid);
|
||||
if (!pool) {
|
||||
virNWFilterReportError(obj->conn, VIR_ERR_INVALID_NWFILTER,
|
||||
"%s", _("no nwfilter pool with matching uuid"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virNWFilterTestUnassignDef(obj->conn, pool)) {
|
||||
virNWFilterReportError(obj->conn, VIR_ERR_INVALID_NWFILTER,
|
||||
"%s",
|
||||
_("nwfilter is in use"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virNWFilterPoolObjDeleteDef(obj->conn, pool) < 0)
|
||||
goto cleanup;
|
||||
|
||||
VIR_FREE(pool->configFile);
|
||||
|
||||
virNWFilterPoolObjRemove(&driver->pools, pool);
|
||||
pool = NULL;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (pool)
|
||||
virNWFilterPoolObjUnlock(pool);
|
||||
nwfilterDriverUnlock(driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
nwfilterDumpXML(virNWFilterPtr obj,
|
||||
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||
virNWFilterDriverStatePtr driver = obj->conn->nwfilterPrivateData;
|
||||
virNWFilterPoolObjPtr pool;
|
||||
char *ret = NULL;
|
||||
|
||||
nwfilterDriverLock(driver);
|
||||
pool = virNWFilterPoolObjFindByUUID(&driver->pools, obj->uuid);
|
||||
nwfilterDriverUnlock(driver);
|
||||
|
||||
if (!pool) {
|
||||
virNWFilterReportError(obj->conn, VIR_ERR_INVALID_NWFILTER,
|
||||
"%s", _("no nwfilter pool with matching uuid"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = virNWFilterDefFormat(obj->conn, pool->def);
|
||||
|
||||
cleanup:
|
||||
if (pool)
|
||||
virNWFilterPoolObjUnlock(pool);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static virNWFilterDriver nwfilterDriver = {
|
||||
.name = "nwfilter",
|
||||
.open = nwfilterOpen,
|
||||
.close = nwfilterClose,
|
||||
.numOfNWFilters = nwfilterNumNWFilters,
|
||||
.listNWFilters = nwfilterListNWFilters,
|
||||
.nwfilterLookupByName = nwfilterLookupByName,
|
||||
.nwfilterLookupByUUID = nwfilterLookupByUUID,
|
||||
.defineXML = nwfilterDefine,
|
||||
.undefine = nwfilterUndefine,
|
||||
.getXMLDesc = nwfilterDumpXML,
|
||||
};
|
||||
|
||||
|
||||
static virStateDriver stateDriver = {
|
||||
.name = "NWFilter",
|
||||
.initialize = nwfilterDriverStartup,
|
||||
.cleanup = nwfilterDriverShutdown,
|
||||
.reload = nwfilterDriverReload,
|
||||
.active = nwfilterDriverActive,
|
||||
};
|
||||
|
||||
int nwfilterRegister(void) {
|
||||
virRegisterNWFilterDriver(&nwfilterDriver);
|
||||
virRegisterStateDriver(&stateDriver);
|
||||
return 0;
|
||||
}
|
36
src/nwfilter/nwfilter_driver.h
Normal file
36
src/nwfilter/nwfilter_driver.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* nwfilter_driver.h: core driver for nwfilter APIs
|
||||
* (based on storage driver)
|
||||
*
|
||||
* Copyright (C) 2006-2008 Red Hat, Inc.
|
||||
* Copyright (C) 2006-2008 Daniel P. Berrange
|
||||
* Copyright (C) 2010 IBM Corporation
|
||||
* Copyright (C) 2010 Stefan Berger
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||
* Stefan Berger <stefanb@us.ibm.com>
|
||||
*/
|
||||
|
||||
#ifndef __VIR_NWFILTER_DRIVER_H__
|
||||
#define __VIR_NWFILTER_DRIVER_H__
|
||||
|
||||
#include "nwfilter_params.h"
|
||||
#include "nwfilter_conf.h"
|
||||
|
||||
int nwfilterRegister(void);
|
||||
|
||||
#endif /* __VIR_NWFILTER_DRIVER_H__ */
|
1414
src/nwfilter/nwfilter_ebiptables_driver.c
Normal file
1414
src/nwfilter/nwfilter_ebiptables_driver.c
Normal file
File diff suppressed because it is too large
Load Diff
41
src/nwfilter/nwfilter_ebiptables_driver.h
Normal file
41
src/nwfilter/nwfilter_ebiptables_driver.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* nwfilter_ebiptables_driver.h: ebtables/iptables driver support
|
||||
*
|
||||
* Copyright (C) 2010 IBM Corporation
|
||||
* Copyright (C) 2010 Stefan Berger
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Stefan Berger <stefanb@us.ibm.com>
|
||||
*/
|
||||
#ifndef VIR_NWFILTER_EBTABLES_DRIVER_H__
|
||||
#define VIR_NWFILTER_EBTABLES_DRIVER_H__
|
||||
|
||||
#define MAX_CHAINNAME_LENGTH 32 /* see linux/netfilter_bridge/ebtables.h */
|
||||
|
||||
typedef struct _ebiptablesRuleInst ebiptablesRuleInst;
|
||||
typedef ebiptablesRuleInst *ebiptablesRuleInstPtr;
|
||||
struct _ebiptablesRuleInst {
|
||||
char *commandTemplate;
|
||||
enum virNWFilterChainSuffixType neededProtocolChain;
|
||||
char chainprefix; // I for incoming, O for outgoing
|
||||
unsigned int priority;
|
||||
};
|
||||
|
||||
extern virNWFilterTechDriver ebiptables_driver;
|
||||
|
||||
#define EBIPTABLES_DRIVER_ID "ebiptables"
|
||||
|
||||
#endif
|
683
src/nwfilter/nwfilter_gentech_driver.c
Normal file
683
src/nwfilter/nwfilter_gentech_driver.c
Normal file
@ -0,0 +1,683 @@
|
||||
/*
|
||||
* nwfilter_gentech_driver.c: generic technology driver
|
||||
*
|
||||
* Copyright (C) 2010 IBM Corp.
|
||||
* Copyright (C) 2010 Stefan Berger
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Stefan Berger <stefanb@us.ibm.com>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include "memory.h"
|
||||
#include "logging.h"
|
||||
#include "datatypes.h"
|
||||
#include "domain_conf.h"
|
||||
#include "virterror_internal.h"
|
||||
#include "nwfilter_gentech_driver.h"
|
||||
#include "nwfilter_ebiptables_driver.h"
|
||||
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_NWFILTER
|
||||
|
||||
|
||||
#define NWFILTER_STD_VAR_MAC "MAC"
|
||||
|
||||
|
||||
static virNWFilterTechDriverPtr filter_tech_drivers[] = {
|
||||
&ebiptables_driver,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
virNWFilterTechDriverPtr
|
||||
virNWFilterTechDriverForName(const char *name) {
|
||||
int i = 0;
|
||||
while (filter_tech_drivers[i]) {
|
||||
if (STREQ(filter_tech_drivers[i]->name, name))
|
||||
return filter_tech_drivers[i];
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNWFilterRuleInstAddData:
|
||||
* @conn : pointer to virConnect object
|
||||
* @res : pointer to virNWFilterRuleInst object collecting the instantiation
|
||||
* data of a single firewall rule.
|
||||
* @data : the opaque data that the driver wants to add
|
||||
*
|
||||
* Add instantiation data to a firewall rule. An instantiated firewall
|
||||
* rule may hold multiple data structure representing its instantiation
|
||||
* data. This may for example be the case if a rule has been defined
|
||||
* for bidirectional traffic and data needs to be added to the incoming
|
||||
* and outgoing chains.
|
||||
*
|
||||
* Returns 0 in case of success, 1 in case of an error with the error
|
||||
* message attached to the virConnect object.
|
||||
*/
|
||||
int
|
||||
virNWFilterRuleInstAddData(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virNWFilterRuleInstPtr res,
|
||||
void *data)
|
||||
{
|
||||
if (VIR_REALLOC_N(res->data, res->ndata+1) < 0) {
|
||||
virReportOOMError();
|
||||
return 1;
|
||||
}
|
||||
res->data[res->ndata++] = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst)
|
||||
{
|
||||
int i;
|
||||
if (!inst)
|
||||
return;
|
||||
|
||||
for (i = 0; i < inst->ndata; i++)
|
||||
inst->techdriver->freeRuleInstance(inst->data[i]);
|
||||
|
||||
VIR_FREE(inst->data);
|
||||
VIR_FREE(inst);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNWFilterVarHashmapAddStdValues:
|
||||
* @conn: Poijter to virConnect object
|
||||
* @tables: pointer to hash tabel to add values to
|
||||
* @macaddr: The string of the MAC address to add to the hash table,
|
||||
* may be NULL
|
||||
*
|
||||
* Returns 0 in case of success, 1 in case an error happened with
|
||||
* error having been reported.
|
||||
*
|
||||
* Adds a couple of standard keys (MAC, IP) to the hash table.
|
||||
*/
|
||||
static int
|
||||
virNWFilterVarHashmapAddStdValues(virConnectPtr conn,
|
||||
virNWFilterHashTablePtr table,
|
||||
char *macaddr)
|
||||
{
|
||||
if (macaddr) {
|
||||
if (virHashAddEntry(table->hashTable,
|
||||
NWFILTER_STD_VAR_MAC,
|
||||
macaddr) < 0) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("Could not add variable 'MAC' to hashmap"));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNWFilterCreateVarHashmap:
|
||||
* @conn: pointer to virConnect object
|
||||
* @macaddr: pointer to string containing formatted MAC address of interface
|
||||
*
|
||||
* Create a hashmap used for evaluating the firewall rules. Initializes
|
||||
* it with the standard variable 'MAC'.
|
||||
*
|
||||
* Returns pointer to hashmap, NULL if an error occcurred and error message
|
||||
* is attached to the virConnect object.
|
||||
*/
|
||||
virNWFilterHashTablePtr
|
||||
virNWFilterCreateVarHashmap(virConnectPtr conn,
|
||||
char *macaddr) {
|
||||
virNWFilterHashTablePtr table = virNWFilterHashTableCreate(0);
|
||||
if (!table) {
|
||||
virReportOOMError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (virNWFilterVarHashmapAddStdValues(conn, table, macaddr)) {
|
||||
virNWFilterHashTableFree(table);
|
||||
return NULL;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNWFilterRuleInstantiate:
|
||||
* @conn: pointer to virConnect object
|
||||
* @techdriver: the driver to use for instantiation
|
||||
* @filter: The filter the rule is part of
|
||||
* @rule : The rule that is to be instantiated
|
||||
* @ifname: The name of the interface
|
||||
* @vars: map containing variable names and value used for instantiation
|
||||
*
|
||||
* Returns virNWFilterRuleInst object on success, NULL on error with
|
||||
* error reported.
|
||||
*
|
||||
* Instantiate a single rule. Return a pointer to virNWFilterRuleInst
|
||||
* object that will hold an array of driver-specific data resulting
|
||||
* from the instantiation. Returns NULL on error with error reported.
|
||||
*/
|
||||
static virNWFilterRuleInstPtr
|
||||
virNWFilterRuleInstantiate(virConnectPtr conn,
|
||||
virNWFilterTechDriverPtr techdriver,
|
||||
enum virDomainNetType nettype,
|
||||
virNWFilterDefPtr filter,
|
||||
virNWFilterRuleDefPtr rule,
|
||||
const char *ifname,
|
||||
virNWFilterHashTablePtr vars)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
virNWFilterRuleInstPtr ret;
|
||||
|
||||
if (VIR_ALLOC(ret) < 0) {
|
||||
virReportOOMError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->techdriver = techdriver;
|
||||
|
||||
rc = techdriver->createRuleInstance(conn, nettype, filter,
|
||||
rule, ifname, vars, ret);
|
||||
|
||||
if (rc) {
|
||||
for (i = 0; i < ret->ndata; i++)
|
||||
techdriver->freeRuleInstance(ret->data[i]);
|
||||
VIR_FREE(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNWFilterCreateVarsFrom:
|
||||
* @conn: pointer to virConnect object
|
||||
* @vars1: pointer to hash table
|
||||
* @vars2: pointer to hash table
|
||||
*
|
||||
* Returns pointer to new hashtable or NULL in case of error with
|
||||
* error already reported.
|
||||
*
|
||||
* Creates a new hash table with contents of var1 and var2 added where
|
||||
* contents of var2 will overwrite those of var1.
|
||||
*/
|
||||
static virNWFilterHashTablePtr
|
||||
virNWFilterCreateVarsFrom(virConnectPtr conn,
|
||||
virNWFilterHashTablePtr vars1,
|
||||
virNWFilterHashTablePtr vars2)
|
||||
{
|
||||
virNWFilterHashTablePtr res = virNWFilterHashTableCreate(0);
|
||||
if (!res) {
|
||||
virReportOOMError();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (virNWFilterHashTablePutAll(conn, vars1, res))
|
||||
goto err_exit;
|
||||
|
||||
if (virNWFilterHashTablePutAll(conn, vars2, res))
|
||||
goto err_exit;
|
||||
|
||||
return res;
|
||||
|
||||
err_exit:
|
||||
virNWFilterHashTableFree(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _virNWFilterPoolInstantiateRec:
|
||||
* @conn: pointer to virConnect object
|
||||
* @techdriver: The driver to use for instantiation
|
||||
* @filter: The filter to instantiate
|
||||
* @ifname: The name of the interface to apply the rules to
|
||||
* @vars: A map holding variable names and values used for instantiating
|
||||
* the filter and its subfilters.
|
||||
* @nEntries: number of virNWFilterInst objects collected
|
||||
* @insts: pointer to array for virNWFilterIns object pointers
|
||||
* @useNewFilter: instruct whether to use a newDef pointer rather than a
|
||||
* def ptr which is useful during a filter update
|
||||
* @foundNewFilter: pointer to int indivating whether a newDef pointer was
|
||||
* ever used; variable expected to be initialized to 0 by caller
|
||||
*
|
||||
* Returns 0 on success, a value otherwise.
|
||||
*
|
||||
* Recursively instantiate a filter by instantiating the given filter along
|
||||
* with all its subfilters in a depth-first traversal of the tree of
|
||||
* referenced filters. The name of the interface to which the rules belong
|
||||
* must be provided. Apply the values of variables as needed. Terminate with
|
||||
* error when a referenced filter is missing or a variable could not be
|
||||
* resolved -- among other reasons.
|
||||
*/
|
||||
static int
|
||||
_virNWFilterInstantiateRec(virConnectPtr conn,
|
||||
virNWFilterTechDriverPtr techdriver,
|
||||
enum virDomainNetType nettype,
|
||||
virNWFilterDefPtr filter,
|
||||
const char *ifname,
|
||||
virNWFilterHashTablePtr vars,
|
||||
int *nEntries,
|
||||
virNWFilterRuleInstPtr **insts,
|
||||
enum instCase useNewFilter, int *foundNewFilter)
|
||||
{
|
||||
virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData;
|
||||
virNWFilterPoolObjPtr obj;
|
||||
int rc = 0;
|
||||
int i;
|
||||
virNWFilterRuleInstPtr inst;
|
||||
virNWFilterDefPtr next_filter;
|
||||
|
||||
for (i = 0; i < filter->nentries; i++) {
|
||||
virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule;
|
||||
virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include;
|
||||
if (rule) {
|
||||
inst = virNWFilterRuleInstantiate(conn,
|
||||
techdriver,
|
||||
nettype,
|
||||
filter,
|
||||
rule,
|
||||
ifname,
|
||||
vars);
|
||||
if (!inst) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (VIR_REALLOC_N(*insts, (*nEntries)+1) < 0) {
|
||||
virReportOOMError();
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
(*insts)[(*nEntries)++] = inst;
|
||||
|
||||
} else if (inc) {
|
||||
VIR_DEBUG("Instantiating filter %s\n", inc->filterref);
|
||||
obj = virNWFilterPoolObjFindByName(&driver->pools,
|
||||
inc->filterref);
|
||||
if (obj) {
|
||||
|
||||
if (obj->wantRemoved) {
|
||||
virNWFilterReportError(conn, VIR_ERR_NO_NWFILTER,
|
||||
_("Filter '%s' is in use."),
|
||||
inc->filterref);
|
||||
rc = 1;
|
||||
virNWFilterPoolObjUnlock(obj);
|
||||
break;
|
||||
}
|
||||
|
||||
// create a temporary hashmap for depth-first tree traversal
|
||||
virNWFilterHashTablePtr tmpvars =
|
||||
virNWFilterCreateVarsFrom(conn,
|
||||
inc->params,
|
||||
vars);
|
||||
if (!tmpvars) {
|
||||
virReportOOMError();
|
||||
rc = 1;
|
||||
virNWFilterPoolObjUnlock(obj);
|
||||
break;
|
||||
}
|
||||
|
||||
next_filter = obj->def;
|
||||
|
||||
switch (useNewFilter) {
|
||||
case INSTANTIATE_FOLLOW_NEWFILTER:
|
||||
if (obj->newDef) {
|
||||
next_filter = obj->newDef;
|
||||
*foundNewFilter = 1;
|
||||
}
|
||||
break;
|
||||
case INSTANTIATE_ALWAYS:
|
||||
break;
|
||||
}
|
||||
|
||||
rc = _virNWFilterInstantiateRec(conn,
|
||||
techdriver,
|
||||
nettype,
|
||||
next_filter,
|
||||
ifname,
|
||||
tmpvars,
|
||||
nEntries, insts,
|
||||
useNewFilter,
|
||||
foundNewFilter);
|
||||
|
||||
virNWFilterHashTableFree(tmpvars);
|
||||
|
||||
virNWFilterPoolObjUnlock(obj);
|
||||
if (rc)
|
||||
break;
|
||||
} else {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("referenced filter '%s' is missing"),
|
||||
inc->filterref);
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virNWFilterRuleInstancesToArray(int nEntries,
|
||||
virNWFilterRuleInstPtr *insts,
|
||||
void ***ptrs,
|
||||
int *nptrs)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
*nptrs = 0;
|
||||
|
||||
for (j = 0; j < nEntries; j++)
|
||||
(*nptrs) += insts[j]->ndata;
|
||||
|
||||
if ((*nptrs) == 0)
|
||||
return 0;
|
||||
|
||||
if (VIR_ALLOC_N((*ptrs), (*nptrs)) < 0) {
|
||||
virReportOOMError();
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*nptrs) = 0;
|
||||
|
||||
for (j = 0; j < nEntries; j++)
|
||||
for (i = 0; i < insts[j]->ndata; i++)
|
||||
(*ptrs)[(*nptrs)++] = insts[j]->data[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virNWFilterInstantiate:
|
||||
* @conn: pointer to virConnect object
|
||||
* @techdriver: The driver to use for instantiation
|
||||
* @filter: The filter to instantiate
|
||||
* @ifname: The name of the interface to apply the rules to
|
||||
* @vars: A map holding variable names and values used for instantiating
|
||||
* the filter and its subfilters.
|
||||
*
|
||||
* Returns 0 on success, a value otherwise.
|
||||
*
|
||||
* Instantiate a filter by instantiating the filter itself along with
|
||||
* all its subfilters in a depth-first traversal of the tree of referenced
|
||||
* filters. The name of the interface to which the rules belong must be
|
||||
* provided. Apply the values of variables as needed.
|
||||
*/
|
||||
static int
|
||||
virNWFilterInstantiate(virConnectPtr conn,
|
||||
virNWFilterTechDriverPtr techdriver,
|
||||
enum virDomainNetType nettype,
|
||||
virNWFilterDefPtr filter,
|
||||
const char *ifname,
|
||||
virNWFilterHashTablePtr vars,
|
||||
enum instCase useNewFilter, int *foundNewFilter,
|
||||
bool teardownOld)
|
||||
{
|
||||
int rc;
|
||||
int j, nptrs;
|
||||
int nEntries = 0;
|
||||
virNWFilterRuleInstPtr *insts = NULL;
|
||||
void **ptrs = NULL;
|
||||
int instantiate = 1;
|
||||
|
||||
rc = _virNWFilterInstantiateRec(conn,
|
||||
techdriver,
|
||||
nettype,
|
||||
filter,
|
||||
ifname,
|
||||
vars,
|
||||
&nEntries, &insts,
|
||||
useNewFilter, foundNewFilter);
|
||||
|
||||
if (rc)
|
||||
goto err_exit;
|
||||
|
||||
switch (useNewFilter) {
|
||||
case INSTANTIATE_FOLLOW_NEWFILTER:
|
||||
instantiate = *foundNewFilter;
|
||||
break;
|
||||
case INSTANTIATE_ALWAYS:
|
||||
instantiate = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (instantiate) {
|
||||
|
||||
rc = virNWFilterRuleInstancesToArray(nEntries, insts,
|
||||
&ptrs, &nptrs);
|
||||
if (rc)
|
||||
goto err_exit;
|
||||
|
||||
rc = techdriver->applyNewRules(conn, ifname, nptrs, ptrs);
|
||||
|
||||
if (teardownOld && rc == 0)
|
||||
techdriver->tearOldRules(conn, ifname);
|
||||
|
||||
VIR_FREE(ptrs);
|
||||
}
|
||||
|
||||
err_exit:
|
||||
|
||||
for (j = 0; j < nEntries; j++)
|
||||
virNWFilterRuleInstFree(insts[j]);
|
||||
|
||||
VIR_FREE(insts);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_virNWFilterInstantiateFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net,
|
||||
bool teardownOld,
|
||||
enum instCase useNewFilter)
|
||||
{
|
||||
int rc;
|
||||
const char *drvname = EBIPTABLES_DRIVER_ID;
|
||||
virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData;
|
||||
virNWFilterTechDriverPtr techdriver;
|
||||
virNWFilterPoolObjPtr obj;
|
||||
virNWFilterHashTablePtr vars, vars1;
|
||||
virNWFilterDefPtr filter;
|
||||
char vmmacaddr[VIR_MAC_STRING_BUFLEN] = {0};
|
||||
int foundNewFilter = 0;
|
||||
char *str_macaddr = NULL;
|
||||
|
||||
techdriver = virNWFilterTechDriverForName(drvname);
|
||||
|
||||
if (!techdriver) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not get access to ACL tech "
|
||||
"driver '%s'"),
|
||||
drvname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
VIR_DEBUG("filter name: %s\n", net->filter);
|
||||
|
||||
obj = virNWFilterPoolObjFindByName(&driver->pools, net->filter);
|
||||
if (!obj) {
|
||||
virNWFilterReportError(conn, VIR_ERR_NO_NWFILTER,
|
||||
_("Could not find filter '%s'"),
|
||||
net->filter);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (obj->wantRemoved) {
|
||||
virNWFilterReportError(conn, VIR_ERR_NO_NWFILTER,
|
||||
_("Filter '%s' is in use."),
|
||||
net->filter);
|
||||
rc = 1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
virFormatMacAddr(net->mac, vmmacaddr);
|
||||
str_macaddr = strdup(vmmacaddr);
|
||||
if (!str_macaddr) {
|
||||
virReportOOMError();
|
||||
rc = 1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
vars1 = virNWFilterCreateVarHashmap(conn,
|
||||
str_macaddr);
|
||||
if (!vars1) {
|
||||
rc = 1;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
str_macaddr = NULL;
|
||||
|
||||
vars = virNWFilterCreateVarsFrom(conn,
|
||||
vars1,
|
||||
net->filterparams);
|
||||
if (!vars) {
|
||||
rc = 1;
|
||||
goto err_exit_vars1;
|
||||
}
|
||||
|
||||
filter = obj->def;
|
||||
|
||||
switch (useNewFilter) {
|
||||
case INSTANTIATE_FOLLOW_NEWFILTER:
|
||||
if (obj->newDef) {
|
||||
filter = obj->newDef;
|
||||
foundNewFilter = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case INSTANTIATE_ALWAYS:
|
||||
break;
|
||||
}
|
||||
|
||||
rc = virNWFilterInstantiate(conn,
|
||||
techdriver,
|
||||
net->type,
|
||||
filter,
|
||||
net->ifname,
|
||||
vars,
|
||||
useNewFilter, &foundNewFilter,
|
||||
teardownOld);
|
||||
|
||||
virNWFilterHashTableFree(vars);
|
||||
|
||||
err_exit_vars1:
|
||||
virNWFilterHashTableFree(vars1);
|
||||
|
||||
err_exit:
|
||||
|
||||
virNWFilterPoolObjUnlock(obj);
|
||||
|
||||
VIR_FREE(str_macaddr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virNWFilterInstantiateFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net)
|
||||
{
|
||||
return _virNWFilterInstantiateFilter(conn, net,
|
||||
1,
|
||||
INSTANTIATE_ALWAYS);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virNWFilterUpdateInstantiateFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net)
|
||||
{
|
||||
return _virNWFilterInstantiateFilter(conn, net,
|
||||
0,
|
||||
INSTANTIATE_FOLLOW_NEWFILTER);
|
||||
}
|
||||
|
||||
int virNWFilterRollbackUpdateFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net)
|
||||
{
|
||||
const char *drvname = EBIPTABLES_DRIVER_ID;
|
||||
virNWFilterTechDriverPtr techdriver;
|
||||
techdriver = virNWFilterTechDriverForName(drvname);
|
||||
if (!techdriver) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not get access to ACL tech "
|
||||
"driver '%s'"),
|
||||
drvname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return techdriver->tearNewRules(conn, net->ifname);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virNWFilterTearOldFilter(virConnectPtr conn,
|
||||
virDomainNetDefPtr net)
|
||||
{
|
||||
const char *drvname = EBIPTABLES_DRIVER_ID;
|
||||
virNWFilterTechDriverPtr techdriver;
|
||||
techdriver = virNWFilterTechDriverForName(drvname);
|
||||
if (!techdriver) {
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not get access to ACL tech "
|
||||
"driver '%s'"),
|
||||
drvname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return techdriver->tearOldRules(conn, net->ifname);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
virNWFilterTeardownFilter(const virDomainNetDefPtr net)
|
||||
{
|
||||
const char *drvname = EBIPTABLES_DRIVER_ID;
|
||||
virNWFilterTechDriverPtr techdriver;
|
||||
techdriver = virNWFilterTechDriverForName(drvname);
|
||||
|
||||
if (!techdriver) {
|
||||
#if 0
|
||||
virNWFilterReportError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not get access to ACL tech "
|
||||
"driver '%s'"),
|
||||
drvname);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
techdriver->allTeardown(net->ifname);
|
||||
|
||||
return 0;
|
||||
}
|
54
src/nwfilter/nwfilter_gentech_driver.h
Normal file
54
src/nwfilter/nwfilter_gentech_driver.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* nwfilter_gentech_driver.h: generic technology driver include file
|
||||
*
|
||||
* Copyright (C) 2010 IBM Corp.
|
||||
* Copyright (C) 2010 Stefan Berger
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Stefan Berger <stefanb@us.ibm.com>
|
||||
*/
|
||||
#ifndef __NWFILTER_GENTECH_DRIVER_H
|
||||
#define __NWFILTER_GENTECH_DRIVER_H
|
||||
|
||||
virNWFilterTechDriverPtr virNWFilterTechDriverForName(const char *name);
|
||||
|
||||
int virNWFilterRuleInstAddData(virConnectPtr conn,
|
||||
virNWFilterRuleInstPtr res,
|
||||
void *data);
|
||||
|
||||
|
||||
enum instCase {
|
||||
INSTANTIATE_ALWAYS,
|
||||
INSTANTIATE_FOLLOW_NEWFILTER,
|
||||
};
|
||||
|
||||
|
||||
int virNWFilterInstantiateFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net);
|
||||
int virNWFilterUpdateInstantiateFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net);
|
||||
int virNWFilterRollbackUpdateFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net);
|
||||
|
||||
int virNWFilterTearOldFilter(virConnectPtr conn,
|
||||
const virDomainNetDefPtr net);
|
||||
|
||||
int virNWFilterTeardownFilter(const virDomainNetDefPtr net);
|
||||
|
||||
virNWFilterHashTablePtr virNWFilterCreateVarHashmap(virConnectPtr conn,
|
||||
char *macaddr);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user