[libvirt] [PATCHv6 2/5] domifaddr: Implement the remote protocol

Nehal J Wani nehaljw.kkd1 at gmail.com
Fri Sep 6 15:18:50 UTC 2013


daemon/remote.c
   * Define remoteSerializeDomainInterface, remoteDispatchDomainInterfaceAddresses

src/remote/remote_driver.c
   * Define remoteDomainInterfaceAddresses

src/remote/remote_protocol.x
   * New RPC procedure: REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES
   * Define structs remote_domain_ip_addr, remote_domain_interface,
     remote_domain_interfaces_addresse_args, remote_domain_interface_addresses_ret
   * Introduce upper bounds (to handle DDoS attacks):
     REMOTE_DOMAIN_INTERFACE_MAX = 2048
     REMOTE_DOMAIN_IP_ADDR_MAX = 2048
     Restrictions on the maximum number of aliases per interface were
     removed after kernel v2.0, and theoretically, at present, there
     are no upper limits on number of interfaces per virtual machine
     and on the number of IP addresses per interface.

src/remote_protocol-structs
   * New structs added

---
 daemon/remote.c              | 130 +++++++++++++++++++++++++++++++++++++++++++
 src/remote/remote_driver.c   |  99 ++++++++++++++++++++++++++++++++
 src/remote/remote_protocol.x |  40 ++++++++++++-
 src/remote_protocol-structs  |  24 ++++++++
 4 files changed, 292 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 2aff7c1..4dff602 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -5137,7 +5137,137 @@ cleanup:
     return rv;
 }
 
+static int
+remoteSerializeDomainInterface(virDomainInterfacePtr *ifaces,
+                               unsigned int ifaces_count,
+                               remote_domain_interface_addresses_ret *ret)
+{
+    size_t i, j;
+
+    if (ifaces_count > REMOTE_DOMAIN_INTERFACE_MAX) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Number of interfaces, %d exceeds the max limit: %d"),
+                       ifaces_count, REMOTE_DOMAIN_INTERFACE_MAX);
+        return -1;
+    }
+
+    if (VIR_ALLOC_N(ret->ifaces.ifaces_val, ifaces_count) < 0)
+        return -1;
+
+    ret->ifaces.ifaces_len = ifaces_count;
+
+    for (i = 0; i < ifaces_count; i++) {
+        virDomainInterfacePtr iface = ifaces[i];
+        remote_domain_interface *iface_ret = &(ret->ifaces.ifaces_val[i]);
+
+        if ((VIR_STRDUP(iface_ret->name, iface->name)) < 0)
+            goto cleanup;
+
+        if (iface->hwaddr) {
+            char **hwaddr_p = NULL;
+            if (VIR_ALLOC(hwaddr_p) < 0)
+                goto cleanup;
+            if (VIR_STRDUP(*hwaddr_p, iface->hwaddr) < 0) {
+                VIR_FREE(hwaddr_p);
+                goto cleanup;
+            }
+
+            iface_ret->hwaddr = hwaddr_p;
+        }
+
+        if (iface->naddrs > REMOTE_DOMAIN_IP_ADDR_MAX) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Number of interfaces, %d exceeds the max limit: %d"),
+                           iface->naddrs, REMOTE_DOMAIN_IP_ADDR_MAX);
+            goto cleanup;
+        }
+
+        if (VIR_ALLOC_N(iface_ret->addrs.addrs_val,
+                        iface->naddrs) < 0)
+            goto cleanup;
+
+        iface_ret->addrs.addrs_len = iface->naddrs;
+
+        for (j = 0; j < iface->naddrs; j++) {
+            virDomainIPAddressPtr ip_addr = &(iface->addrs[j]);
+            remote_domain_ip_addr *ip_addr_ret =
+                &(iface_ret->addrs.addrs_val[j]);
+
+            if (VIR_STRDUP(ip_addr_ret->addr, ip_addr->addr) < 0)
+                goto cleanup;
+
+            ip_addr_ret->prefix = ip_addr->prefix;
+            ip_addr_ret->type = ip_addr->type;
+        }
+    }
+
+    return 0;
+
+cleanup:
+    if (ret->ifaces.ifaces_val) {
+        for (i = 0; i < ifaces_count; i++) {
+            remote_domain_interface *iface_ret = &(ret->ifaces.ifaces_val[i]);
+            VIR_FREE(iface_ret->name);
+            VIR_FREE(iface_ret->hwaddr);
+            for (j = 0; j < iface_ret->addrs.addrs_len; j++) {
+                remote_domain_ip_addr *ip_addr =
+                    &(iface_ret->addrs.addrs_val[j]);
+                VIR_FREE(ip_addr->addr);
+            }
+            VIR_FREE(iface_ret);
+        }
+        VIR_FREE(ret->ifaces.ifaces_val);
+    }
+
+    return -1;
+}
+
+static int
+remoteDispatchDomainInterfaceAddresses(virNetServerPtr server ATTRIBUTE_UNUSED,
+                                       virNetServerClientPtr client,
+                                       virNetMessagePtr msg ATTRIBUTE_UNUSED,
+                                       virNetMessageErrorPtr rerr,
+                                       remote_domain_interface_addresses_args *args,
+                                       remote_domain_interface_addresses_ret *ret)
+{
+    size_t i;
+    int rv = -1;
+    virDomainPtr dom = NULL;
+    virDomainInterfacePtr *ifaces = NULL;
+    int ifaces_count = 0;
+    struct daemonClientPrivate *priv =
+        virNetServerClientGetPrivateData(client);
+
+    if (!priv->conn) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+        goto cleanup;
+    }
 
+    if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+        goto cleanup;
+
+    if ((ifaces_count = virDomainInterfaceAddresses(dom, &ifaces, args->flags)) < 0)
+        goto cleanup;
+
+    if (remoteSerializeDomainInterface(ifaces, ifaces_count, ret) < 0)
+        goto cleanup;
+
+    rv = 0;
+
+cleanup:
+    if (rv < 0)
+        virNetMessageSaveError(rerr);
+
+    virDomainFree(dom);
+
+    if (ifaces) {
+        for (i = 0; i < ifaces_count; i++)
+            virDomainInterfaceFree(ifaces[i]);
+        VIR_FREE(ifaces);
+    }
+
+    return rv;
+}
 
 /*----- Helpers. -----*/
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 62e77a5..db94c07 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6599,6 +6599,104 @@ done:
     return rv;
 }
 
+static int
+remoteDomainInterfaceAddresses(virDomainPtr dom,
+                               virDomainInterfacePtr **ifaces,
+                               unsigned int flags)
+{
+    int rv = -1;
+    size_t i, j;
+
+    virDomainInterfacePtr *ifaces_ret = NULL;
+    remote_domain_interface_addresses_args args;
+    remote_domain_interface_addresses_ret ret;
+
+    struct private_data *priv = dom->conn->privateData;
+
+    args.flags = flags;
+    make_nonnull_domain(&args.dom, dom);
+
+    remoteDriverLock(priv);
+
+    memset(&ret, 0, sizeof(ret));
+
+    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES,
+             (xdrproc_t)xdr_remote_domain_interface_addresses_args,
+             (char *)&args,
+             (xdrproc_t)xdr_remote_domain_interface_addresses_ret,
+             (char *)&ret) == -1) {
+        goto done;
+    }
+
+    if (ret.ifaces.ifaces_len > REMOTE_DOMAIN_INTERFACE_MAX) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Number of interfaces, %d exceeds the max limit: %d"),
+                       ret.ifaces.ifaces_len, REMOTE_DOMAIN_INTERFACE_MAX);
+        goto cleanup;
+    }
+
+    if (ret.ifaces.ifaces_len &&
+        VIR_ALLOC_N(ifaces_ret, ret.ifaces.ifaces_len) < 0)
+        goto cleanup;
+
+    for (i = 0; i < ret.ifaces.ifaces_len; i++) {
+        if (VIR_ALLOC(ifaces_ret[i]) < 0)
+            goto cleanup;
+
+        virDomainInterfacePtr iface = ifaces_ret[i];
+        remote_domain_interface *iface_ret = &(ret.ifaces.ifaces_val[i]);
+
+        if (VIR_STRDUP(iface->name, iface_ret->name) < 0)
+            goto cleanup;
+
+        if (iface_ret->hwaddr &&
+            VIR_STRDUP(iface->hwaddr, *iface_ret->hwaddr) < 0)
+            goto cleanup;
+
+        if (iface_ret->addrs.addrs_len > REMOTE_DOMAIN_IP_ADDR_MAX) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Number of interfaces, %d exceeds the max limit: %d"),
+                           iface_ret->addrs.addrs_len, REMOTE_DOMAIN_IP_ADDR_MAX);
+            goto cleanup;
+        }
+
+        iface->naddrs = iface_ret->addrs.addrs_len;
+
+        if (iface->naddrs) {
+            if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0)
+                goto cleanup;
+
+           for (j = 0; j < iface->naddrs; j++) {
+                virDomainIPAddressPtr ip_addr = &(iface->addrs[j]);
+                remote_domain_ip_addr *ip_addr_ret =
+                    &(iface_ret->addrs.addrs_val[j]);
+
+                if (VIR_STRDUP(ip_addr->addr, ip_addr_ret->addr) < 0)
+                    goto cleanup;
+
+                ip_addr->prefix = ip_addr_ret->prefix;
+                ip_addr->type = ip_addr_ret->type;
+            }
+        }
+    }
+    *ifaces = ifaces_ret;
+    ifaces_ret = NULL;
+
+    rv = ret.ifaces.ifaces_len;
+
+cleanup:
+    if (ifaces_ret) {
+        for (i = 0; i < ret.ifaces.ifaces_len; i++)
+            virDomainInterfaceFree(ifaces_ret[i]);
+        VIR_FREE(ifaces_ret);
+    }
+    xdr_free((xdrproc_t)xdr_remote_domain_interface_addresses_ret,
+             (char *) &ret);
+done:
+    remoteDriverUnlock(priv);
+    return rv;
+}
+
 static void
 remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event)
 {
@@ -6933,6 +7031,7 @@ static virDriver remote_driver = {
     .domainMigratePerform3Params = remoteDomainMigratePerform3Params, /* 1.1.0 */
     .domainMigrateFinish3Params = remoteDomainMigrateFinish3Params, /* 1.1.0 */
     .domainMigrateConfirm3Params = remoteDomainMigrateConfirm3Params, /* 1.1.0 */
+    .domainInterfaceAddresses = remoteDomainInterfaceAddresses, /* 1.1.3 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index a1c23da..cc074b2 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -235,6 +235,16 @@ const REMOTE_DOMAIN_JOB_STATS_MAX = 16;
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
+/*
+ * Upper limit on number of interfaces per domain
+ */
+const REMOTE_DOMAIN_INTERFACE_MAX = 2048;
+
+/*
+ * Upper limit on number of IP addresses per interface
+ */
+const REMOTE_DOMAIN_IP_ADDR_MAX = 2048;
+
 /* A domain which may not be NULL. */
 struct remote_nonnull_domain {
     remote_nonnull_string name;
@@ -2835,6 +2845,27 @@ struct remote_domain_event_device_removed_msg {
     remote_nonnull_string devAlias;
 };
 
+struct remote_domain_ip_addr {
+    int type;
+    remote_nonnull_string addr;
+    unsigned int prefix;
+};
+
+struct remote_domain_interface {
+    remote_nonnull_string name;
+    remote_string hwaddr;
+    remote_domain_ip_addr addrs<REMOTE_DOMAIN_IP_ADDR_MAX>;
+};
+
+struct remote_domain_interface_addresses_args {
+    remote_nonnull_domain dom;
+    unsigned int flags;
+};
+
+struct remote_domain_interface_addresses_ret {
+    remote_domain_interface ifaces<REMOTE_DOMAIN_INTERFACE_MAX>;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -4998,5 +5029,12 @@ enum remote_procedure {
      * @generate: both
      * @acl: none
      */
-    REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311
+    REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311,
+
+    /**
+     * @generate: none
+     * @acl: domain:read
+     */
+    REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES = 312
+
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 4e27aae..bde73fd 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2316,6 +2316,29 @@ struct remote_domain_event_device_removed_msg {
         remote_nonnull_domain      dom;
         remote_nonnull_string      devAlias;
 };
+struct remote_domain_ip_addr {
+        int                        type;
+        remote_nonnull_string      addr;
+        u_int                      prefix;
+};
+struct remote_domain_interface {
+        remote_nonnull_string      name;
+        remote_string              hwaddr;
+        struct {
+                u_int              addrs_len;
+                remote_domain_ip_addr * addrs_val;
+        } addrs;
+};
+struct remote_domain_interface_addresses_args {
+        remote_nonnull_domain      dom;
+        u_int                      flags;
+};
+struct remote_domain_interface_addresses_ret {
+        struct {
+                u_int              ifaces_len;
+                remote_domain_interface * ifaces_val;
+        } ifaces;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -2628,4 +2651,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_CREATE_XML_WITH_FILES = 309,
         REMOTE_PROC_DOMAIN_CREATE_WITH_FILES = 310,
         REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED = 311,
+        REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES = 312,
 };
-- 
1.7.11.7




More information about the libvir-list mailing list