From 46e9b0fb4eefd5f47877356eefbe7ffcbb2c85ff Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Thu, 25 Mar 2010 13:46:02 -0400 Subject: [PATCH] Implementation of the public API This patch adds the implementation of the public API for the network filtering (ACL) extensions to libvirt.c . Signed-off-by: Stefan Berger --- include/libvirt/virterror.h | 7 +- src/datatypes.c | 142 +++++++++ src/datatypes.h | 32 ++ src/libvirt.c | 586 ++++++++++++++++++++++++++++++++++++ src/libvirt_private.syms | 3 + src/libvirt_public.syms | 13 + src/util/virterror.c | 27 ++ 7 files changed, 809 insertions(+), 1 deletion(-) diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index d298447382..8cf30be373 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -69,7 +69,8 @@ typedef enum { VIR_FROM_PHYP, /* Error from IBM power hypervisor */ VIR_FROM_SECRET, /* Error from secret storage */ VIR_FROM_CPU, /* Error from CPU driver */ - VIR_FROM_XENAPI /* Error from XenAPI */ + VIR_FROM_XENAPI, /* Error from XenAPI */ + VIR_FROM_NWFILTER /* Error from network filter driver */ } virErrorDomain; @@ -169,6 +170,10 @@ typedef enum { VIR_ERR_NO_INTERFACE, /* interface driver not running */ VIR_ERR_INVALID_INTERFACE, /* invalid interface object */ VIR_ERR_MULTIPLE_INTERFACES, /* more than one matching interface found */ + VIR_WAR_NO_NWFILTER, /* failed to start nwfilter driver */ + VIR_ERR_INVALID_NWFILTER, /* invalid nwfilter object */ + VIR_ERR_NO_NWFILTER, /* nw filter pool not found */ + VIR_ERR_BUILD_FIREWALL, /* nw filter pool not found */ VIR_WAR_NO_SECRET, /* failed to start secret storage */ VIR_ERR_INVALID_SECRET, /* invalid secret */ VIR_ERR_NO_SECRET, /* secret not found */ diff --git a/src/datatypes.c b/src/datatypes.c index 01601d8caf..a361da6cd4 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -175,6 +175,9 @@ virGetConnect(void) { ret->secrets = virHashCreate(20); if (ret->secrets == NULL) goto failed; + ret->nwfilterPools = virHashCreate(20); + if (ret->nwfilterPools == NULL) + goto failed; ret->refs = 1; return(ret); @@ -1362,3 +1365,142 @@ int virUnrefStream(virStreamPtr st) { virMutexUnlock(&st->conn->lock); return (refs); } + + +/** + * virGetNWFilter: + * @conn: the hypervisor connection + * @name: pointer to the network filter pool name + * @uuid: pointer to the uuid + * + * Lookup if the network filter is already registered for that connection, + * if yes return a new pointer to it, if no allocate a new structure, + * and register it in the table. In any case a corresponding call to + * virFreeNWFilterPool() is needed to not leak data. + * + * Returns a pointer to the network, or NULL in case of failure + */ +virNWFilterPtr +virGetNWFilter(virConnectPtr conn, const char *name, const unsigned char *uuid) { + virNWFilterPtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (uuid == NULL)) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + virMutexLock(&conn->lock); + + /* TODO search by UUID first as they are better differenciators */ + + ret = (virNWFilterPtr) virHashLookup(conn->nwfilterPools, name); + /* TODO check the UUID */ + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virMutexUnlock(&conn->lock); + virReportOOMError(); + goto error; + } + ret->name = strdup(name); + if (ret->name == NULL) { + virMutexUnlock(&conn->lock); + virReportOOMError(); + goto error; + } + ret->magic = VIR_NWFILTER_MAGIC; + ret->conn = conn; + if (uuid != NULL) + memcpy(&(ret->uuid[0]), uuid, VIR_UUID_BUFLEN); + + if (virHashAddEntry(conn->nwfilterPools, name, ret) < 0) { + virMutexUnlock(&conn->lock); + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("failed to add network filter pool to connection hash table")); + goto error; + } + conn->refs++; + } + ret->refs++; + virMutexUnlock(&conn->lock); + return(ret); + +error: + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret); + } + return(NULL); +} + + +/** + * virReleaseNWFilterPool: + * @pool: the pool to release + * + * Unconditionally release all memory associated with a pool. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The pool obj must not + * be used once this method returns. + * + * It will also unreference the associated connection object, + * which may also be released if its ref count hits zero. + */ +static void +virReleaseNWFilterPool(virNWFilterPtr pool) { + virConnectPtr conn = pool->conn; + DEBUG("release pool %p %s", pool, pool->name); + + /* TODO search by UUID first as they are better differenciators */ + if (virHashRemoveEntry(conn->nwfilterPools, pool->name, NULL) < 0) { + virMutexUnlock(&conn->lock); + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + "%s", _("pool missing from connection hash table")); + conn = NULL; + } + + pool->magic = -1; + VIR_FREE(pool->name); + VIR_FREE(pool); + + if (conn) { + DEBUG("unref connection %p %d", conn, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + virMutexUnlock(&conn->lock); + } +} + + +/** + * virUnrefNWFilter: + * @pool: the nwfilter to unreference + * + * Unreference the networkf itler. If the use count drops to zero, the + * structure is actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefNWFilter(virNWFilterPtr pool) { + int refs; + + if (!VIR_IS_CONNECTED_NWFILTER(pool)) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + virMutexLock(&pool->conn->lock); + DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs); + pool->refs--; + refs = pool->refs; + if (refs == 0) { + virReleaseNWFilterPool(pool); + /* Already unlocked mutex */ + return (0); + } + + virMutexUnlock(&pool->conn->lock); + return (refs); +} diff --git a/src/datatypes.h b/src/datatypes.h index e19c99ab23..c221119971 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -120,6 +120,17 @@ # define VIR_IS_CONNECTED_STREAM(obj) (VIR_IS_STREAM(obj) && VIR_IS_CONNECT((obj)->conn)) +/** + * VIR_NWFILTER_MAGIC: + * + * magic value used to protect the API when pointers to network filter + * pool structures are passed down by the users. + */ +#define VIR_NWFILTER_MAGIC 0xDEAD7777 +#define VIR_IS_NWFILTER(obj) ((obj) && (obj)->magic==VIR_NWFILTER_MAGIC) +#define VIR_IS_CONNECTED_NWFILTER(obj) (VIR_IS_NWFILTER(obj) && VIR_IS_CONNECT((obj)->conn)) + + /** * _virConnect: * @@ -141,6 +152,7 @@ struct _virConnect { virStorageDriverPtr storageDriver; virDeviceMonitorPtr deviceMonitor; virSecretDriverPtr secretDriver; + virNWFilterDriverPtr nwfilterDriver; /* Private data pointer which can be used by driver and * network driver as they wish. @@ -152,6 +164,7 @@ struct _virConnect { void * storagePrivateData; void * devMonPrivateData; void * secretPrivateData; + void * nwfilterPrivateData; /* * The lock mutex must be acquired before accessing/changing @@ -173,6 +186,7 @@ struct _virConnect { virHashTablePtr storageVols;/* hash table for known storage vols */ virHashTablePtr nodeDevices; /* hash table for known node devices */ virHashTablePtr secrets; /* hash taboe for known secrets */ + virHashTablePtr nwfilterPools; /* hash tables ofr known nw filter pools */ int refs; /* reference count */ }; @@ -336,4 +350,22 @@ int virUnrefSecret(virSecretPtr secret); virStreamPtr virGetStream(virConnectPtr conn); int virUnrefStream(virStreamPtr st); +/** +* _virNWFilter: +* +* Internal structure associated to a network filter +*/ +struct _virNWFilter { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *name; /* the network filter external name */ + unsigned char uuid[VIR_UUID_BUFLEN]; /* the network filter unique identifier */ +}; + +virNWFilterPtr virGetNWFilter(virConnectPtr conn, + const char *name, + const unsigned char *uuid); +int virUnrefNWFilter(virNWFilterPtr pool); + #endif diff --git a/src/libvirt.c b/src/libvirt.c index 8424eaf381..1ee299ab74 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -91,6 +91,8 @@ static virDeviceMonitorPtr virDeviceMonitorTab[MAX_DRIVERS]; static int virDeviceMonitorTabCount = 0; static virSecretDriverPtr virSecretDriverTab[MAX_DRIVERS]; static int virSecretDriverTabCount = 0; +static virNWFilterDriverPtr virNWFilterDriverTab[MAX_DRIVERS]; +static int virNWFilterDriverTabCount = 0; #ifdef WITH_LIBVIRTD static virStateDriverPtr virStateDriverTab[MAX_DRIVERS]; static int virStateDriverTabCount = 0; @@ -654,6 +656,32 @@ virLibSecretError(virSecretPtr secret, virErrorNumber error, const char *info) errmsg, info, NULL, 0, 0, errmsg, info); } +/** + * virLibNWFilterError: + * @conn: the connection if available + * @error: the error number + * @info: extra information string + * + * Handle an error at the connection level + */ +static void +virLibNWFilterError(virNWFilterPtr pool, virErrorNumber error, + const char *info) +{ + virConnectPtr conn = NULL; + const char *errmsg; + + if (error == VIR_ERR_OK) + return; + + errmsg = virErrorMsg(error, info); + if (error != VIR_ERR_INVALID_NWFILTER) + conn = pool->conn; + + virRaiseError(conn, NULL, NULL, VIR_FROM_NWFILTER, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); +} + /** * virRegisterNetworkDriver: * @driver: pointer to a network driver block @@ -809,6 +837,38 @@ virRegisterSecretDriver(virSecretDriverPtr driver) return virSecretDriverTabCount++; } +/** + * virRegisterNWFilterDriver: + * @driver: pointer to a network filter driver block + * + * Register a network filter virtualization driver + * + * Returns the driver priority or -1 in case of error. + */ +int +virRegisterNWFilterDriver(virNWFilterDriverPtr driver) +{ + if (virInitialize() < 0) + return -1; + + if (driver == NULL) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + if (virNWFilterDriverTabCount >= MAX_DRIVERS) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + DEBUG ("registering %s as network filter driver %d", + driver->name, virNWFilterDriverTabCount); + + virNWFilterDriverTab[virNWFilterDriverTabCount] = driver; + return virNWFilterDriverTabCount++; +} + + /** * virRegisterDriver: * @driver: pointer to a driver block @@ -1253,6 +1313,26 @@ do_open (const char *name, } } + /* Network filter driver. Optional */ + for (i = 0; i < virNWFilterDriverTabCount; i++) { + res = virNWFilterDriverTab[i]->open (ret, auth, flags); + DEBUG("nwfilter driver %d %s returned %s", + i, virNWFilterDriverTab[i]->name, + res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" : + (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" : + (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status"))); + if (res == VIR_DRV_OPEN_ERROR) { + if (STREQ(virNWFilterDriverTab[i]->name, "remote")) { + virLibConnWarning (NULL, VIR_WAR_NO_NWFILTER, + _("Is the daemon running ?")); + } + break; + } else if (res == VIR_DRV_OPEN_SUCCESS) { + ret->nwfilterDriver = virNWFilterDriverTab[i]; + break; + } + } + return ret; failed: @@ -11084,6 +11164,512 @@ error: } + +/** + * virConnectNumOfNWFilters: + * @conn: pointer to the hypervisor connection + * + * Provides the number of nwfilters. + * + * Returns the number of nwfilters found or -1 in case of error + */ +int +virConnectNumOfNWFilters(virConnectPtr conn) +{ + DEBUG("conn=%p", conn); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if (conn->nwfilterDriver && conn->nwfilterDriver->numOfNWFilters) { + int ret; + ret = conn->nwfilterDriver->numOfNWFilters (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + + +/** + * virConnectListNWFilters: + * @conn: pointer to the hypervisor connection + * @names: array to collect the list of names of network filters + * @maxnames: size of @names + * + * Collect the list of network filters, and store their names in @names + * + * Returns the number of network filters found or -1 in case of error + */ +int +virConnectListNWFilters(virConnectPtr conn, char **const names, int maxnames) +{ + DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + if ((names == NULL) || (maxnames < 0)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->nwfilterDriver && conn->nwfilterDriver->listNWFilters) { + int ret; + ret = conn->nwfilterDriver->listNWFilters (conn, names, maxnames); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return -1; +} + + +/** + * virNWFilterLookupByName: + * @conn: pointer to the hypervisor connection + * @name: name for the network filter + * + * Try to lookup a network filter on the given hypervisor based on its name. + * + * Returns a new nwfilter object or NULL in case of failure. If the + * network filter cannot be found, then VIR_ERR_NO_NWFILTER error is raised. + */ +virNWFilterPtr +virNWFilterLookupByName(virConnectPtr conn, const char *name) +{ + DEBUG("conn=%p, name=%s", conn, name); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return (NULL); + } + if (name == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->nwfilterDriver && conn->nwfilterDriver->nwfilterLookupByName) { + virNWFilterPtr ret; + ret = conn->nwfilterDriver->nwfilterLookupByName (conn, name); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return NULL; +} + +/** + * virNWFilterLookupByUUID: + * @conn: pointer to the hypervisor connection + * @uuid: the raw UUID for the network filter + * + * Try to lookup a network filter on the given hypervisor based on its UUID. + * + * Returns a new nwfilter object or NULL in case of failure. If the + * nwfdilter cannot be found, then VIR_ERR_NO_NWFILTER error is raised. + */ +virNWFilterPtr +virNWFilterLookupByUUID(virConnectPtr conn, const unsigned char *uuid) +{ + DEBUG("conn=%p, uuid=%s", conn, uuid); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return (NULL); + } + if (uuid == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->nwfilterDriver && conn->nwfilterDriver->nwfilterLookupByUUID){ + virNWFilterPtr ret; + ret = conn->nwfilterDriver->nwfilterLookupByUUID (conn, uuid); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return NULL; +} + +/** + * virNWFIlterLookupByUUIDString: + * @conn: pointer to the hypervisor connection + * @uuidstr: the string UUID for the nwfilter + * + * Try to lookup an nwfilter on the given hypervisor based on its UUID. + * + * Returns a new nwfilter object or NULL in case of failure. If the + * nwfilter cannot be found, then VIR_ERR_NO_NWFILTER error is raised. + */ +virNWFilterPtr +virNWFilterLookupByUUIDString(virConnectPtr conn, const char *uuidstr) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + DEBUG("conn=%p, uuidstr=%s", conn, uuidstr); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return (NULL); + } + if (uuidstr == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (virUUIDParse(uuidstr, uuid) < 0) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + return virNWFilterLookupByUUID(conn, &uuid[0]); + +error: + virDispatchError(conn); + return NULL; +} + +/** + * virNWFilterFree: + * @nwfilter: a nwfilter object + * + * Free the nwfilter object. The running instance is kept alive. + * The data structure is freed and should not be used thereafter. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virNWFilterFree(virNWFilterPtr nwfilter) +{ + DEBUG("nwfilter=%p", nwfilter); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_NWFILTER(nwfilter)) { + virLibNWFilterError(NULL, VIR_ERR_INVALID_NWFILTER, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (virUnrefNWFilter(nwfilter) < 0) { + virDispatchError(NULL); + return -1; + } + return 0; +} + +/** + * virNWFilterGetName: + * @nwfilter: a nwfilter object + * + * Get the public name for the network filter + * + * Returns a pointer to the name or NULL, the string need not be deallocated + * its lifetime will be the same as the nwfilter object. + */ +const char * +virNWFilterGetName(virNWFilterPtr nwfilter) +{ + DEBUG("nwfilter=%p", nwfilter); + + virResetLastError(); + + if (!VIR_IS_NWFILTER(nwfilter)) { + virLibNWFilterError(NULL, VIR_ERR_INVALID_NWFILTER, __FUNCTION__); + virDispatchError(NULL); + return (NULL); + } + return (nwfilter->name); +} + +/** + * virNWFilterGetUUID: + * @nwfilter: a nwfilter object + * @uuid: pointer to a VIR_UUID_BUFLEN bytes array + * + * Get the UUID for a network filter + * + * Returns -1 in case of error, 0 in case of success + */ +int +virNWFilterGetUUID(virNWFilterPtr nwfilter, unsigned char *uuid) +{ + DEBUG("nwfilter=%p, uuid=%p", nwfilter, uuid); + + virResetLastError(); + + if (!VIR_IS_NWFILTER(nwfilter)) { + virLibNWFilterError(NULL, VIR_ERR_INVALID_NWFILTER, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (uuid == NULL) { + virLibNWFilterError(nwfilter, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + memcpy(uuid, &nwfilter->uuid[0], VIR_UUID_BUFLEN); + + return 0; + +error: + virDispatchError(nwfilter->conn); + return -1; +} + +/** + * virNWFilterGetUUIDString: + * @nwfilter: a nwfilter object + * @buf: pointer to a VIR_UUID_STRING_BUFLEN bytes array + * + * Get the UUID for a network filter as string. For more information about + * UUID see RFC4122. + * + * Returns -1 in case of error, 0 in case of success + */ +int +virNWFilterGetUUIDString(virNWFilterPtr nwfilter, char *buf) +{ + unsigned char uuid[VIR_UUID_BUFLEN]; + DEBUG("nwfilter=%p, buf=%p", nwfilter, buf); + + virResetLastError(); + + if (!VIR_IS_NWFILTER(nwfilter)) { + virLibNWFilterError(NULL, VIR_ERR_INVALID_NWFILTER, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + if (buf == NULL) { + virLibNWFilterError(nwfilter, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (virNWFilterGetUUID(nwfilter, &uuid[0])) + goto error; + + virUUIDFormat(uuid, buf); + return 0; + +error: + virDispatchError(nwfilter->conn); + return -1; +} + + +/** + * virNWFilterDefineXML: + * @conn: pointer to the hypervisor connection + * @xmlDesc: an XML description of the nwfilter + * + * Define a new network filter, based on an XML description + * similar to the one returned by virNWFilterGetXMLDesc() + * + * Returns a new nwfilter object or NULL in case of failure + */ +virNWFilterPtr +virNWFilterDefineXML(virConnectPtr conn, const char *xmlDesc) +{ + DEBUG("conn=%p, xmlDesc=%s", conn, xmlDesc); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + virDispatchError(NULL); + return (NULL); + } + if (xmlDesc == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->nwfilterDriver && conn->nwfilterDriver->defineXML) { + virNWFilterPtr ret; + ret = conn->nwfilterDriver->defineXML (conn, xmlDesc, 0); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(conn); + return NULL; +} + + +/** + * virNWFilterUndefine: + * @nwfilter: a nwfilter object + * + * Undefine the nwfilter object. This call will not succeed if + * a running VM is referencing the filter. This does not free the + * associated virNWFilterPtr object. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virNWFilterUndefine(virNWFilterPtr nwfilter) +{ + virConnectPtr conn; + DEBUG("nwfilter=%p", nwfilter); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_NWFILTER(nwfilter)) { + virLibNWFilterError(NULL, VIR_ERR_INVALID_NWFILTER, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + + conn = nwfilter->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibNWFilterError(nwfilter, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->nwfilterDriver && conn->nwfilterDriver->undefine) { + int ret; + ret = conn->nwfilterDriver->undefine (nwfilter); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(nwfilter->conn); + return -1; +} + + +/** + * virNWFilterGetXMLDesc: + * @nwfilter: a nwfilter object + * @flags: an OR'ed set of extraction flags, not used yet + * + * Provide an XML description of the network filter. The description may be + * reused later to redefine the network filter with virNWFilterCreateXML(). + * + * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. + * the caller must free() the returned value. + */ +char * +virNWFilterGetXMLDesc(virNWFilterPtr nwfilter, int flags) +{ + virConnectPtr conn; + DEBUG("nwfilter=%p, flags=%d", nwfilter, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_NWFILTER(nwfilter)) { + virLibNWFilterError(NULL, VIR_ERR_INVALID_NWFILTER, __FUNCTION__); + virDispatchError(NULL); + return (NULL); + } + if (flags != 0) { + virLibNWFilterError(nwfilter, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = nwfilter->conn; + + if (conn->nwfilterDriver && conn->nwfilterDriver->getXMLDesc) { + char *ret; + ret = conn->nwfilterDriver->getXMLDesc (nwfilter, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + virDispatchError(nwfilter->conn); + return NULL; +} + + +/** + * virNWFilterRef: + * @nwfilter: the nwfilter to hold a reference on + * + * Increment the reference count on the nwfilter. For each + * additional call to this method, there shall be a corresponding + * call to virNWFilterFree to release the reference count, once + * the caller no longer needs the reference to this object. + * + * This method is typically useful for applications where multiple + * threads are using a connection, and it is required that the + * connection remain open until all threads have finished using + * it. ie, each new thread using an nwfilter would increment + * the reference count. + * + * Returns 0 in case of success, -1 in case of failure. + */ +int +virNWFilterRef(virNWFilterPtr nwfilter) +{ + if ((!VIR_IS_CONNECTED_NWFILTER(nwfilter))) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + virDispatchError(NULL); + return -1; + } + virMutexLock(&nwfilter->conn->lock); + DEBUG("nwfilter=%p refs=%d", nwfilter, nwfilter->refs); + nwfilter->refs++; + virMutexUnlock(&nwfilter->conn->lock); + return 0; +} + + /** * virInterfaceIsActive: * @iface: pointer to the interface object diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 0033d2a373..4fe5427045 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -105,6 +105,8 @@ virUnrefConnect; virUnrefSecret; virGetStream; virUnrefStream; +virGetNWFilter; +virUnrefNWFilter; # domain_conf.h @@ -311,6 +313,7 @@ virRegisterNetworkDriver; virRegisterStorageDriver; virRegisterDeviceMonitor; virRegisterSecretDriver; +virRegisterNWFilterDriver; # json.h diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index f1491e9afa..ad7577cd30 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -365,6 +365,19 @@ LIBVIRT_0.7.8 { virConnectDomainEventRegisterAny; virConnectDomainEventDeregisterAny; virDomainUpdateDeviceFlags; + virConnectListNWFilters; + virConnectNumOfNWFilters; + virNWFilterLookupByName; + virNWFilterLookupByUUID; + virNWFilterLookupByUUIDString; + virNWFilterFree; + virNWFilterGetName; + virNWFilterGetUUID; + virNWFilterGetUUIDString; + virNWFilterGetXMLDesc; + virNWFilterRef; + virNWFilterDefineXML; + virNWFilterUndefine; } LIBVIRT_0.7.7; # .... define new API here using predicted next version number .... diff --git a/src/util/virterror.c b/src/util/virterror.c index 0e8bdb3194..d82c2c6dfe 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -178,6 +178,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_CPU: dom = "CPU "; break; + case VIR_FROM_NWFILTER: + dom = "Network Filter"; + break; } return(dom); } @@ -1100,6 +1103,30 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("Secret not found: %s"); break; + case VIR_WAR_NO_NWFILTER: + if (info == NULL) + errmsg = _("Failed to start the nwfilter driver"); + else + errmsg = _("Failed to start the nwfilter driver: %s"); + break; + case VIR_ERR_INVALID_NWFILTER: + if (info == NULL) + errmsg = _("Invalid network filter"); + else + errmsg = _("Invalid network filter: %s"); + break; + case VIR_ERR_NO_NWFILTER: + if (info == NULL) + errmsg = _("Network filter not found"); + else + errmsg = _("Network filter not found: %s"); + break; + case VIR_ERR_BUILD_FIREWALL: + if (info == NULL) + errmsg = _("Error while building firewall"); + else + errmsg = _("Error while building firewall: %s"); + break; case VIR_ERR_CONFIG_UNSUPPORTED: if (info == NULL) errmsg = _("unsupported configuration");