This patch adds the implementation of the public API for the network
filtering (ACL) extensions to libvirt.c .
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
src/libvirt.c | 586 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 586 insertions(+)
Index: libvirt-acl/src/libvirt.c
===================================================================
--- libvirt-acl.orig/src/libvirt.c
+++ libvirt-acl/src/libvirt.c
@@ -91,6 +91,8 @@ static virDeviceMonitorPtr virDeviceMoni
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;
@@ -655,6 +657,32 @@ virLibSecretError(virSecretPtr secret, v
}
/**
+ * 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
*
@@ -810,6 +838,38 @@ virRegisterSecretDriver(virSecretDriverP
}
/**
+ * 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:
@@ -11011,6 +11091,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