/* Automatically generated from ./remote/remote_protocol.x by gendispatch.pl.
 * Do not edit this file.  Any changes you make will be lost.
 */

static char *
remoteConnectBaselineCPU(virConnectPtr conn, const char **xmlCPUs, unsigned int xmlCPUslen, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_connect_baseline_cpu_args args;
    remote_connect_baseline_cpu_ret ret;

    remoteDriverLock(priv);

    if (xmlCPUslen > REMOTE_CPU_BASELINE_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "xmlCPUs", (int)xmlCPUslen, REMOTE_CPU_BASELINE_MAX);
        goto done;
    }

    args.xmlCPUs.xmlCPUs_val = (char **)xmlCPUs;
    args.xmlCPUs.xmlCPUs_len = xmlCPUslen;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_BASELINE_CPU,
             (xdrproc_t)xdr_remote_connect_baseline_cpu_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_baseline_cpu_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.cpu;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectCompareCPU(virConnectPtr conn, const char *xml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_compare_cpu_args args;
    remote_connect_compare_cpu_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_COMPARE_CPU,
             (xdrproc_t)xdr_remote_connect_compare_cpu_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_compare_cpu_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.result;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteConnectDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat, const char *nativeConfig, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_connect_domain_xml_from_native_args args;
    remote_connect_domain_xml_from_native_ret ret;

    remoteDriverLock(priv);

    args.nativeFormat = (char *)nativeFormat;
    args.nativeConfig = (char *)nativeConfig;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_XML_FROM_NATIVE,
             (xdrproc_t)xdr_remote_connect_domain_xml_from_native_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_domain_xml_from_native_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.domainXml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteConnectDomainXMLToNative(virConnectPtr conn, const char *nativeFormat, const char *domainXml, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_connect_domain_xml_to_native_args args;
    remote_connect_domain_xml_to_native_ret ret;

    remoteDriverLock(priv);

    args.nativeFormat = (char *)nativeFormat;
    args.domainXml = (char *)domainXml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_XML_TO_NATIVE,
             (xdrproc_t)xdr_remote_connect_domain_xml_to_native_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_domain_xml_to_native_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.nativeConfig;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteConnectGetCapabilities(virConnectPtr conn)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_connect_get_capabilities_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_CAPABILITIES,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_get_capabilities_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.capabilities;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteConnectGetDomainCapabilities(virConnectPtr conn, const char *emulatorbin, const char *arch, const char *machine, const char *virttype, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_connect_get_domain_capabilities_args args;
    remote_connect_get_domain_capabilities_ret ret;

    remoteDriverLock(priv);

    args.emulatorbin = emulatorbin ? (char **)&emulatorbin : NULL;
    args.arch = arch ? (char **)&arch : NULL;
    args.machine = machine ? (char **)&machine : NULL;
    args.virttype = virttype ? (char **)&virttype : NULL;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_DOMAIN_CAPABILITIES,
             (xdrproc_t)xdr_remote_connect_get_domain_capabilities_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_get_domain_capabilities_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.capabilities;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteConnectGetHostname(virConnectPtr conn)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_connect_get_hostname_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_HOSTNAME,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_get_hostname_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.hostname;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectGetLibVersion(virConnectPtr conn, unsigned long *lib_ver)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_get_lib_version_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_LIB_VERSION,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_get_lib_version_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (lib_ver) HYPER_TO_ULONG(*lib_ver, ret.lib_ver);
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectGetMaxVcpus(virConnectPtr conn, const char *type)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_get_max_vcpus_args args;
    remote_connect_get_max_vcpus_ret ret;

    remoteDriverLock(priv);

    args.type = type ? (char **)&type : NULL;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_MAX_VCPUS,
             (xdrproc_t)xdr_remote_connect_get_max_vcpus_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_get_max_vcpus_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.max_vcpus;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_connect_get_sysinfo_args args;
    remote_connect_get_sysinfo_ret ret;

    remoteDriverLock(priv);

    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_SYSINFO,
             (xdrproc_t)xdr_remote_connect_get_sysinfo_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_get_sysinfo_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.sysinfo;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectGetVersion(virConnectPtr conn, unsigned long *hv_ver)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_get_version_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_VERSION,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_get_version_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (hv_ver) HYPER_TO_ULONG(*hv_ver, ret.hv_ver);
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListAllDomains(virConnectPtr conn, virDomainPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_all_domains_args args;
    remote_connect_list_all_domains_ret ret;
    virDomainPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_ALL_DOMAINS,
             (xdrproc_t)xdr_remote_connect_list_all_domains_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_all_domains_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.domains.domains_len > REMOTE_DOMAIN_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote domains: %d > %d"),
                       ret.domains.domains_len, REMOTE_DOMAIN_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.domains.domains_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.domains.domains_len; i++) {
            tmp_results[i] = get_nonnull_domain(conn, ret.domains.domains_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.domains.domains_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_connect_list_all_domains_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListAllInterfaces(virConnectPtr conn, virInterfacePtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_all_interfaces_args args;
    remote_connect_list_all_interfaces_ret ret;
    virInterfacePtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_ALL_INTERFACES,
             (xdrproc_t)xdr_remote_connect_list_all_interfaces_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_all_interfaces_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.ifaces.ifaces_len > REMOTE_INTERFACE_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote interfaces: %d > %d"),
                       ret.ifaces.ifaces_len, REMOTE_INTERFACE_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.ifaces.ifaces_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.ifaces.ifaces_len; i++) {
            tmp_results[i] = get_nonnull_interface(conn, ret.ifaces.ifaces_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.ifaces.ifaces_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_connect_list_all_interfaces_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListAllNetworks(virConnectPtr conn, virNetworkPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_all_networks_args args;
    remote_connect_list_all_networks_ret ret;
    virNetworkPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_ALL_NETWORKS,
             (xdrproc_t)xdr_remote_connect_list_all_networks_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_all_networks_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.nets.nets_len > REMOTE_NETWORK_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote networks: %d > %d"),
                       ret.nets.nets_len, REMOTE_NETWORK_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.nets.nets_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.nets.nets_len; i++) {
            tmp_results[i] = get_nonnull_network(conn, ret.nets.nets_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.nets.nets_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_connect_list_all_networks_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListAllNodeDevices(virConnectPtr conn, virNodeDevicePtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_all_node_devices_args args;
    remote_connect_list_all_node_devices_ret ret;
    virNodeDevicePtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_ALL_NODE_DEVICES,
             (xdrproc_t)xdr_remote_connect_list_all_node_devices_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_all_node_devices_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.devices.devices_len > REMOTE_NODE_DEVICE_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote node_devices: %d > %d"),
                       ret.devices.devices_len, REMOTE_NODE_DEVICE_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.devices.devices_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.devices.devices_len; i++) {
            tmp_results[i] = get_nonnull_node_device(conn, ret.devices.devices_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.devices.devices_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_connect_list_all_node_devices_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListAllNWFilters(virConnectPtr conn, virNWFilterPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_all_nwfilters_args args;
    remote_connect_list_all_nwfilters_ret ret;
    virNWFilterPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_ALL_NWFILTERS,
             (xdrproc_t)xdr_remote_connect_list_all_nwfilters_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_all_nwfilters_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.filters.filters_len > REMOTE_NWFILTER_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote nwfilters: %d > %d"),
                       ret.filters.filters_len, REMOTE_NWFILTER_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.filters.filters_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.filters.filters_len; i++) {
            tmp_results[i] = get_nonnull_nwfilter(conn, ret.filters.filters_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.filters.filters_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_connect_list_all_nwfilters_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListAllSecrets(virConnectPtr conn, virSecretPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_all_secrets_args args;
    remote_connect_list_all_secrets_ret ret;
    virSecretPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_ALL_SECRETS,
             (xdrproc_t)xdr_remote_connect_list_all_secrets_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_all_secrets_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.secrets.secrets_len > REMOTE_SECRET_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote secrets: %d > %d"),
                       ret.secrets.secrets_len, REMOTE_SECRET_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.secrets.secrets_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.secrets.secrets_len; i++) {
            tmp_results[i] = get_nonnull_secret(conn, ret.secrets.secrets_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.secrets.secrets_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_connect_list_all_secrets_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListAllStoragePools(virConnectPtr conn, virStoragePoolPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_all_storage_pools_args args;
    remote_connect_list_all_storage_pools_ret ret;
    virStoragePoolPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_ALL_STORAGE_POOLS,
             (xdrproc_t)xdr_remote_connect_list_all_storage_pools_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_all_storage_pools_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.pools.pools_len > REMOTE_STORAGE_POOL_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote storage_pools: %d > %d"),
                       ret.pools.pools_len, REMOTE_STORAGE_POOL_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.pools.pools_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.pools.pools_len; i++) {
            tmp_results[i] = get_nonnull_storage_pool(conn, ret.pools.pools_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.pools.pools_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_connect_list_all_storage_pools_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_defined_domains_args args;
    remote_connect_list_defined_domains_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_DOMAIN_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_DOMAIN_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_DEFINED_DOMAINS,
             (xdrproc_t)xdr_remote_connect_list_defined_domains_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_defined_domains_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_defined_domains_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_defined_interfaces_args args;
    remote_connect_list_defined_interfaces_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_INTERFACE_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_INTERFACE_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_DEFINED_INTERFACES,
             (xdrproc_t)xdr_remote_connect_list_defined_interfaces_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_defined_interfaces_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_defined_interfaces_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListDefinedNetworks(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_defined_networks_args args;
    remote_connect_list_defined_networks_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_NETWORK_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_NETWORK_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_DEFINED_NETWORKS,
             (xdrproc_t)xdr_remote_connect_list_defined_networks_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_defined_networks_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_defined_networks_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListDefinedStoragePools(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_defined_storage_pools_args args;
    remote_connect_list_defined_storage_pools_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_STORAGE_POOL_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_STORAGE_POOL_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_DEFINED_STORAGE_POOLS,
             (xdrproc_t)xdr_remote_connect_list_defined_storage_pools_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_defined_storage_pools_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_defined_storage_pools_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListInterfaces(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_interfaces_args args;
    remote_connect_list_interfaces_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_INTERFACE_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_INTERFACE_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_INTERFACES,
             (xdrproc_t)xdr_remote_connect_list_interfaces_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_interfaces_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_interfaces_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListNetworks(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_networks_args args;
    remote_connect_list_networks_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_NETWORK_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_NETWORK_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_NETWORKS,
             (xdrproc_t)xdr_remote_connect_list_networks_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_networks_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_networks_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListNWFilters(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_nwfilters_args args;
    remote_connect_list_nwfilters_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_NWFILTER_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_NWFILTER_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_NWFILTERS,
             (xdrproc_t)xdr_remote_connect_list_nwfilters_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_nwfilters_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_nwfilters_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListSecrets(virConnectPtr conn, char **const uuids, int maxuuids)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_secrets_args args;
    remote_connect_list_secrets_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxuuids > REMOTE_SECRET_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxuuids, REMOTE_SECRET_LIST_MAX);
        goto done;
    }

    args.maxuuids = maxuuids;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_SECRETS,
             (xdrproc_t)xdr_remote_connect_list_secrets_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_secrets_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.uuids.uuids_len > maxuuids) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.uuids.uuids_len, maxuuids);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.uuids.uuids_len; ++i) {
        if (VIR_STRDUP(uuids[i],
                       ret.uuids.uuids_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(uuids[j]);

            goto cleanup;
        }
    }

    rv = ret.uuids.uuids_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_secrets_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectListStoragePools(virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_list_storage_pools_args args;
    remote_connect_list_storage_pools_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_STORAGE_POOL_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_STORAGE_POOL_LIST_MAX);
        goto done;
    }

    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_STORAGE_POOLS,
             (xdrproc_t)xdr_remote_connect_list_storage_pools_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_list_storage_pools_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_connect_list_storage_pools_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfDefinedDomains(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_defined_domains_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_DEFINED_DOMAINS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_defined_domains_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfDefinedInterfaces(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_defined_interfaces_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_DEFINED_INTERFACES,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_defined_interfaces_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfDefinedNetworks(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_defined_networks_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_DEFINED_NETWORKS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_defined_networks_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_defined_storage_pools_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_DEFINED_STORAGE_POOLS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_defined_storage_pools_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfDomains(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_domains_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_DOMAINS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_domains_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfInterfaces(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_interfaces_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_INTERFACES,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_interfaces_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfNetworks(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_networks_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_NETWORKS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_networks_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfNWFilters(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_nwfilters_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_NWFILTERS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_nwfilters_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfSecrets(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_secrets_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_SECRETS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_secrets_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectNumOfStoragePools(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_num_of_storage_pools_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NUM_OF_STORAGE_POOLS,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_connect_num_of_storage_pools_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteConnectSupportsFeature(virConnectPtr conn, int feature)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_connect_supports_feature_args args;
    remote_connect_supports_feature_ret ret;

    remoteDriverLock(priv);

    args.feature = feature;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_CONNECT_SUPPORTS_FEATURE,
             (xdrproc_t)xdr_remote_connect_supports_feature_args, (char *)&args,
             (xdrproc_t)xdr_remote_connect_supports_feature_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.supported;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainAbortJob(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_abort_job_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_ABORT_JOB,
             (xdrproc_t)xdr_remote_domain_abort_job_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainAddIOThread(virDomainPtr dom, unsigned int iothread_id, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_add_iothread_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.iothread_id = iothread_id;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_ADD_IOTHREAD,
             (xdrproc_t)xdr_remote_domain_add_iothread_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainAttachDevice(virDomainPtr dom, const char *xml)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_attach_device_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.xml = (char *)xml;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE,
             (xdrproc_t)xdr_remote_domain_attach_device_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_attach_device_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.xml = (char *)xml;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE_FLAGS,
             (xdrproc_t)xdr_remote_domain_attach_device_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockCommit(virDomainPtr dom, const char *disk, const char *base, const char *top, unsigned long bandwidth, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_commit_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.disk = (char *)disk;
    args.base = base ? (char **)&base : NULL;
    args.top = top ? (char **)&top : NULL;
    args.bandwidth = bandwidth;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_COMMIT,
             (xdrproc_t)xdr_remote_domain_block_commit_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockCopy(virDomainPtr dom, const char *path, const char *destxml, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_copy_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;
    args.destxml = (char *)destxml;
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_block_copy_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_COPY,
             (xdrproc_t)xdr_remote_domain_block_copy_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_job_abort_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_JOB_ABORT,
             (xdrproc_t)xdr_remote_domain_block_job_abort_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockJobSetSpeed(virDomainPtr dom, const char *path, unsigned long bandwidth, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_job_set_speed_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;
    args.bandwidth = bandwidth;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_JOB_SET_SPEED,
             (xdrproc_t)xdr_remote_domain_block_job_set_speed_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_pull_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;
    args.bandwidth = bandwidth;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_PULL,
             (xdrproc_t)xdr_remote_domain_block_pull_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockRebase(virDomainPtr dom, const char *path, const char *base, unsigned long bandwidth, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_rebase_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;
    args.base = base ? (char **)&base : NULL;
    args.bandwidth = bandwidth;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_REBASE,
             (xdrproc_t)xdr_remote_domain_block_rebase_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockResize(virDomainPtr dom, const char *disk, unsigned long long size, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_resize_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.disk = (char *)disk;
    args.size = size;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_RESIZE,
             (xdrproc_t)xdr_remote_domain_block_resize_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainBlockStats(virDomainPtr dom, const char *path, virDomainBlockStatsPtr result)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_block_stats_args args;
    remote_domain_block_stats_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS,
             (xdrproc_t)xdr_remote_domain_block_stats_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_block_stats_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->rd_req = ret.rd_req;
    result->rd_bytes = ret.rd_bytes;
    result->wr_req = ret.wr_req;
    result->wr_bytes = ret.wr_bytes;
    result->errs = ret.errs;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_core_dump_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.to = (char *)to;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_CORE_DUMP,
             (xdrproc_t)xdr_remote_domain_core_dump_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainCoreDumpWithFormat(virDomainPtr dom, const char *to, unsigned int dumpformat, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_core_dump_with_format_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.to = (char *)to;
    args.dumpformat = dumpformat;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_CORE_DUMP_WITH_FORMAT,
             (xdrproc_t)xdr_remote_domain_core_dump_with_format_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_create_with_flags_args args;
    remote_domain_create_with_flags_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS,
             (xdrproc_t)xdr_remote_domain_create_with_flags_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_create_with_flags_ret, (char *)&ret) == -1) {
        goto done;
    }

    dom->id = ret.dom.id;
    xdr_free((xdrproc_t)xdr_remote_domain_create_with_flags_ret, (char *)&ret);
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainCreateXML(virConnectPtr conn, const char *xml_desc, unsigned int flags)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_create_xml_args args;
    remote_domain_create_xml_ret ret;

    remoteDriverLock(priv);

    args.xml_desc = (char *)xml_desc;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_XML,
             (xdrproc_t)xdr_remote_domain_create_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_create_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.dom);
    xdr_free((xdrproc_t)xdr_remote_domain_create_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainDefineXML(virConnectPtr conn, const char *xml)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_define_xml_args args;
    remote_domain_define_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_DEFINE_XML,
             (xdrproc_t)xdr_remote_domain_define_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_define_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.dom);
    xdr_free((xdrproc_t)xdr_remote_domain_define_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_define_xml_flags_args args;
    remote_domain_define_xml_flags_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_DEFINE_XML_FLAGS,
             (xdrproc_t)xdr_remote_domain_define_xml_flags_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_define_xml_flags_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.dom);
    xdr_free((xdrproc_t)xdr_remote_domain_define_xml_flags_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainDelIOThread(virDomainPtr dom, unsigned int iothread_id, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_del_iothread_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.iothread_id = iothread_id;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DEL_IOTHREAD,
             (xdrproc_t)xdr_remote_domain_del_iothread_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainDestroy(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_destroy_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DESTROY,
             (xdrproc_t)xdr_remote_domain_destroy_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    dom->id = -1;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainDestroyFlags(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_destroy_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DESTROY_FLAGS,
             (xdrproc_t)xdr_remote_domain_destroy_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainDetachDevice(virDomainPtr dom, const char *xml)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_detach_device_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.xml = (char *)xml;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE,
             (xdrproc_t)xdr_remote_domain_detach_device_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_detach_device_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.xml = (char *)xml;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE_FLAGS,
             (xdrproc_t)xdr_remote_domain_detach_device_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainFSFreeze(virDomainPtr dom, const char **mountpoints, unsigned int mountpointslen, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_fsfreeze_args args;
    remote_domain_fsfreeze_ret ret;

    remoteDriverLock(priv);

    if (mountpointslen > REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "mountpoints", (int)mountpointslen, REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.mountpoints.mountpoints_val = (char **)mountpoints;
    args.mountpoints.mountpoints_len = mountpointslen;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_FSFREEZE,
             (xdrproc_t)xdr_remote_domain_fsfreeze_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_fsfreeze_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.filesystems;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainFSThaw(virDomainPtr dom, const char **mountpoints, unsigned int mountpointslen, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_fsthaw_args args;
    remote_domain_fsthaw_ret ret;

    remoteDriverLock(priv);

    if (mountpointslen > REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "mountpoints", (int)mountpointslen, REMOTE_DOMAIN_FSFREEZE_MOUNTPOINTS_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.mountpoints.mountpoints_val = (char **)mountpoints;
    args.mountpoints.mountpoints_len = mountpointslen;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_FSTHAW,
             (xdrproc_t)xdr_remote_domain_fsthaw_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_fsthaw_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.filesystems;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainFSTrim(virDomainPtr dom, const char *mountPoint, unsigned long long minimum, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_fstrim_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.mountPoint = mountPoint ? (char **)&mountPoint : NULL;
    args.minimum = minimum;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_FSTRIM,
             (xdrproc_t)xdr_remote_domain_fstrim_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_autostart_args args;
    remote_domain_get_autostart_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_AUTOSTART,
             (xdrproc_t)xdr_remote_domain_get_autostart_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_autostart_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (autostart) *autostart = ret.autostart;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetBlockInfo(virDomainPtr dom, const char *path, virDomainBlockInfoPtr result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_block_info_args args;
    remote_domain_get_block_info_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_INFO,
             (xdrproc_t)xdr_remote_domain_get_block_info_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_block_info_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->allocation = ret.allocation;
    result->capacity = ret.capacity;
    result->physical = ret.physical;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetControlInfo(virDomainPtr dom, virDomainControlInfoPtr result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_control_info_args args;
    remote_domain_get_control_info_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_CONTROL_INFO,
             (xdrproc_t)xdr_remote_domain_get_control_info_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_control_info_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->state = ret.state;
    result->details = ret.details;
    result->stateTime = ret.stateTime;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetGuestVcpus(virDomainPtr dom, virTypedParameterPtr *params, unsigned int *nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_guest_vcpus_args args;
    remote_domain_get_guest_vcpus_ret ret;
    virTypedParameterPtr ret_params = NULL;
    int ret_nparams = 0;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_GUEST_VCPUS,
             (xdrproc_t)xdr_remote_domain_get_guest_vcpus_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_guest_vcpus_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
                                  ret.params.params_len,
                                  REMOTE_DOMAIN_GUEST_VCPU_PARAMS_MAX,
                                  &ret_params,
                                  &ret_nparams) < 0)
        goto cleanup;

    *params = ret_params;
    *nparams = ret_nparams;
    rv = 0;

cleanup:
    if (rv != 0) {
        virTypedParamsFree(ret_params, ret_nparams);
    }
    xdr_free((xdrproc_t)xdr_remote_domain_get_guest_vcpus_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainGetHostname(virDomainPtr dom, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_hostname_args args;
    remote_domain_get_hostname_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_HOSTNAME,
             (xdrproc_t)xdr_remote_domain_get_hostname_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_hostname_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.hostname;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetInfo(virDomainPtr dom, virDomainInfoPtr result)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_info_args args;
    remote_domain_get_info_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_INFO,
             (xdrproc_t)xdr_remote_domain_get_info_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_info_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->state = ret.state;
    HYPER_TO_ULONG(result->maxMem, ret.maxMem);
    HYPER_TO_ULONG(result->memory, ret.memory);
    result->nrVirtCpu = ret.nrVirtCpu;
    result->cpuTime = ret.cpuTime;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetJobInfo(virDomainPtr dom, virDomainJobInfoPtr result)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_job_info_args args;
    remote_domain_get_job_info_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_JOB_INFO,
             (xdrproc_t)xdr_remote_domain_get_job_info_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_job_info_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->type = ret.type;
    result->timeElapsed = ret.timeElapsed;
    result->timeRemaining = ret.timeRemaining;
    result->dataTotal = ret.dataTotal;
    result->dataProcessed = ret.dataProcessed;
    result->dataRemaining = ret.dataRemaining;
    result->memTotal = ret.memTotal;
    result->memProcessed = ret.memProcessed;
    result->memRemaining = ret.memRemaining;
    result->fileTotal = ret.fileTotal;
    result->fileProcessed = ret.fileProcessed;
    result->fileRemaining = ret.fileRemaining;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static unsigned long long
remoteDomainGetMaxMemory(virDomainPtr dom)
{
    unsigned long long rv = 0;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_max_memory_args args;
    remote_domain_get_max_memory_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_MEMORY,
             (xdrproc_t)xdr_remote_domain_get_max_memory_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_max_memory_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.memory;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetMaxVcpus(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_max_vcpus_args args;
    remote_domain_get_max_vcpus_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_VCPUS,
             (xdrproc_t)xdr_remote_domain_get_max_vcpus_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_max_vcpus_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainGetMetadata(virDomainPtr dom, int type, const char *uri, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_metadata_args args;
    remote_domain_get_metadata_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.type = type;
    args.uri = uri ? (char **)&uri : NULL;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_METADATA,
             (xdrproc_t)xdr_remote_domain_get_metadata_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_metadata_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.metadata;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainGetOSType(virDomainPtr dom)
{
    char *rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_os_type_args args;
    remote_domain_get_os_type_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_OS_TYPE,
             (xdrproc_t)xdr_remote_domain_get_os_type_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_os_type_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.type;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int * nparams)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_scheduler_parameters_args args;
    remote_domain_get_scheduler_parameters_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.nparams = *nparams;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS,
             (xdrproc_t)xdr_remote_domain_get_scheduler_parameters_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_scheduler_parameters_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
                                  ret.params.params_len,
                                  REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX,
                                  &params,
                                  nparams) < 0)
        goto cleanup;

    rv = 0;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_domain_get_scheduler_parameters_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetSchedulerParametersFlags(virDomainPtr dom, virTypedParameterPtr params, int * nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_scheduler_parameters_flags_args args;
    remote_domain_get_scheduler_parameters_flags_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.nparams = *nparams;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS_FLAGS,
             (xdrproc_t)xdr_remote_domain_get_scheduler_parameters_flags_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_scheduler_parameters_flags_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (virTypedParamsDeserialize((virTypedParameterRemotePtr) ret.params.params_val,
                                  ret.params.params_len,
                                  REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX,
                                  &params,
                                  nparams) < 0)
        goto cleanup;

    rv = 0;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_domain_get_scheduler_parameters_flags_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_vcpus_flags_args args;
    remote_domain_get_vcpus_flags_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS,
             (xdrproc_t)xdr_remote_domain_get_vcpus_flags_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_vcpus_flags_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_get_xml_desc_args args;
    remote_domain_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_XML_DESC,
             (xdrproc_t)xdr_remote_domain_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainHasCurrentSnapshot(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_has_current_snapshot_args args;
    remote_domain_has_current_snapshot_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT,
             (xdrproc_t)xdr_remote_domain_has_current_snapshot_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_has_current_snapshot_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.result;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_has_managed_save_image_args args;
    remote_domain_has_managed_save_image_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_MANAGED_SAVE_IMAGE,
             (xdrproc_t)xdr_remote_domain_has_managed_save_image_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_has_managed_save_image_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.result;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainInjectNMI(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_inject_nmi_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_INJECT_NMI,
             (xdrproc_t)xdr_remote_domain_inject_nmi_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainInterfaceStats(virDomainPtr dom, const char *path, virDomainInterfaceStatsPtr result)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_interface_stats_args args;
    remote_domain_interface_stats_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.path = (char *)path;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACE_STATS,
             (xdrproc_t)xdr_remote_domain_interface_stats_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_interface_stats_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->rx_bytes = ret.rx_bytes;
    result->rx_packets = ret.rx_packets;
    result->rx_errs = ret.rx_errs;
    result->rx_drop = ret.rx_drop;
    result->tx_bytes = ret.tx_bytes;
    result->tx_packets = ret.tx_packets;
    result->tx_errs = ret.tx_errs;
    result->tx_drop = ret.tx_drop;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainIsActive(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_is_active_args args;
    remote_domain_is_active_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_ACTIVE,
             (xdrproc_t)xdr_remote_domain_is_active_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_is_active_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainIsPersistent(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_is_persistent_args args;
    remote_domain_is_persistent_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_PERSISTENT,
             (xdrproc_t)xdr_remote_domain_is_persistent_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_is_persistent_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.persistent;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainIsUpdated(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_is_updated_args args;
    remote_domain_is_updated_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_UPDATED,
             (xdrproc_t)xdr_remote_domain_is_updated_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_is_updated_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.updated;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainListAllSnapshots(virDomainPtr dom, virDomainSnapshotPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_list_all_snapshots_args args;
    remote_domain_list_all_snapshots_ret ret;
    virDomainSnapshotPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS,
             (xdrproc_t)xdr_remote_domain_list_all_snapshots_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_list_all_snapshots_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.snapshots.snapshots_len > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote domain_snapshots: %d > %d"),
                       ret.snapshots.snapshots_len, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.snapshots.snapshots_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.snapshots.snapshots_len; i++) {
            tmp_results[i] = get_nonnull_domain_snapshot(dom, ret.snapshots.snapshots_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.snapshots.snapshots_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_domain_list_all_snapshots_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainLookupByID(virConnectPtr conn, int id)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_lookup_by_id_args args;
    remote_domain_lookup_by_id_ret ret;

    remoteDriverLock(priv);

    args.id = id;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_ID,
             (xdrproc_t)xdr_remote_domain_lookup_by_id_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_lookup_by_id_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.dom);
    xdr_free((xdrproc_t)xdr_remote_domain_lookup_by_id_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainLookupByName(virConnectPtr conn, const char *name)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_lookup_by_name_args args;
    remote_domain_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    args.name = (char *)name;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_domain_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.dom);
    xdr_free((xdrproc_t)xdr_remote_domain_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_lookup_by_uuid_args args;
    remote_domain_lookup_by_uuid_ret ret;

    remoteDriverLock(priv);

    memcpy(args.uuid, uuid, VIR_UUID_BUFLEN);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID,
             (xdrproc_t)xdr_remote_domain_lookup_by_uuid_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_lookup_by_uuid_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.dom);
    xdr_free((xdrproc_t)xdr_remote_domain_lookup_by_uuid_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_managed_save_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE,
             (xdrproc_t)xdr_remote_domain_managed_save_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    dom->id = -1;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_managed_save_remove_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE_REMOVE,
             (xdrproc_t)xdr_remote_domain_managed_save_remove_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainMigrateFinish(virConnectPtr conn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_migrate_finish_args args;
    remote_domain_migrate_finish_ret ret;

    remoteDriverLock(priv);

    if (cookielen > REMOTE_MIGRATE_COOKIE_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "cookie", (int)cookielen, REMOTE_MIGRATE_COOKIE_MAX);
        goto done;
    }

    args.dname = (char *)dname;
    args.cookie.cookie_val = (char *)cookie;
    args.cookie.cookie_len = cookielen;
    args.uri = (char *)uri;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH,
             (xdrproc_t)xdr_remote_domain_migrate_finish_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_migrate_finish_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.ddom);
    xdr_free((xdrproc_t)xdr_remote_domain_migrate_finish_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainPtr
remoteDomainMigrateFinish2(virConnectPtr conn, const char *dname, const char *cookie, int cookielen, const char *uri, unsigned long flags, int retcode)
{
    virDomainPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_migrate_finish2_args args;
    remote_domain_migrate_finish2_ret ret;

    remoteDriverLock(priv);

    if (cookielen > REMOTE_MIGRATE_COOKIE_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "cookie", (int)cookielen, REMOTE_MIGRATE_COOKIE_MAX);
        goto done;
    }

    args.dname = (char *)dname;
    args.cookie.cookie_val = (char *)cookie;
    args.cookie.cookie_len = cookielen;
    args.uri = (char *)uri;
    args.flags = flags;
    args.retcode = retcode;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH2,
             (xdrproc_t)xdr_remote_domain_migrate_finish2_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_migrate_finish2_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain(conn, ret.ddom);
    xdr_free((xdrproc_t)xdr_remote_domain_migrate_finish2_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigrateGetCompressionCache(virDomainPtr dom, unsigned long long *cacheSize, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_migrate_get_compression_cache_args args;
    remote_domain_migrate_get_compression_cache_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_GET_COMPRESSION_CACHE,
             (xdrproc_t)xdr_remote_domain_migrate_get_compression_cache_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_migrate_get_compression_cache_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (cacheSize) *cacheSize = ret.cacheSize;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigrateGetMaxSpeed(virDomainPtr dom, unsigned long *bandwidth, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_migrate_get_max_speed_args args;
    remote_domain_migrate_get_max_speed_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_GET_MAX_SPEED,
             (xdrproc_t)xdr_remote_domain_migrate_get_max_speed_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_migrate_get_max_speed_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (bandwidth) HYPER_TO_ULONG(*bandwidth, ret.bandwidth);
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigratePerform(virDomainPtr dom, const char *cookie, int cookielen, const char *uri, unsigned long flags, const char *dname, unsigned long resource)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_migrate_perform_args args;

    remoteDriverLock(priv);

    if (cookielen > REMOTE_MIGRATE_COOKIE_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "cookie", (int)cookielen, REMOTE_MIGRATE_COOKIE_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.cookie.cookie_val = (char *)cookie;
    args.cookie.cookie_len = cookielen;
    args.uri = (char *)uri;
    args.flags = flags;
    args.dname = dname ? (char **)&dname : NULL;
    args.resource = resource;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM,
             (xdrproc_t)xdr_remote_domain_migrate_perform_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigratePrepareTunnel(virConnectPtr conn, virStreamPtr st, unsigned long flags, const char *dname, unsigned long resource, const char *dom_xml)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_domain_migrate_prepare_tunnel_args args;
    virNetClientStreamPtr netst = NULL;

    remoteDriverLock(priv);

    if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL, priv->counter)))
        goto done;

    if (virNetClientAddStream(priv->client, netst) < 0) {
        virObjectUnref(netst);
        goto done;
    }
    st->driver = &remoteStreamDrv;
    st->privateData = netst;

    args.flags = flags;
    args.dname = dname ? (char **)&dname : NULL;
    args.resource = resource;
    args.dom_xml = (char *)dom_xml;

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL,
             (xdrproc_t)xdr_remote_domain_migrate_prepare_tunnel_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        virNetClientRemoveStream(priv->client, netst);
        virObjectUnref(netst);
        st->driver = NULL;
        st->privateData = NULL;
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigrateSetCompressionCache(virDomainPtr dom, unsigned long long cacheSize, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_migrate_set_compression_cache_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.cacheSize = cacheSize;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_COMPRESSION_CACHE,
             (xdrproc_t)xdr_remote_domain_migrate_set_compression_cache_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigrateSetMaxDowntime(virDomainPtr dom, unsigned long long downtime, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_migrate_set_max_downtime_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.downtime = downtime;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME,
             (xdrproc_t)xdr_remote_domain_migrate_set_max_downtime_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigrateSetMaxSpeed(virDomainPtr dom, unsigned long bandwidth, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_migrate_set_max_speed_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.bandwidth = bandwidth;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED,
             (xdrproc_t)xdr_remote_domain_migrate_set_max_speed_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainMigrateStartPostCopy(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_migrate_start_post_copy_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_START_POST_COPY,
             (xdrproc_t)xdr_remote_domain_migrate_start_post_copy_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainOpenChannel(virDomainPtr dom, const char *name, virStreamPtr st, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_open_channel_args args;
    virNetClientStreamPtr netst = NULL;

    remoteDriverLock(priv);

    if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_DOMAIN_OPEN_CHANNEL, priv->counter)))
        goto done;

    if (virNetClientAddStream(priv->client, netst) < 0) {
        virObjectUnref(netst);
        goto done;
    }
    st->driver = &remoteStreamDrv;
    st->privateData = netst;

    make_nonnull_domain(&args.dom, dom);
    args.name = name ? (char **)&name : NULL;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_OPEN_CHANNEL,
             (xdrproc_t)xdr_remote_domain_open_channel_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        virNetClientRemoveStream(priv->client, netst);
        virObjectUnref(netst);
        st->driver = NULL;
        st->privateData = NULL;
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainOpenConsole(virDomainPtr dom, const char *dev_name, virStreamPtr st, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_open_console_args args;
    virNetClientStreamPtr netst = NULL;

    remoteDriverLock(priv);

    if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_DOMAIN_OPEN_CONSOLE, priv->counter)))
        goto done;

    if (virNetClientAddStream(priv->client, netst) < 0) {
        virObjectUnref(netst);
        goto done;
    }
    st->driver = &remoteStreamDrv;
    st->privateData = netst;

    make_nonnull_domain(&args.dom, dom);
    args.dev_name = dev_name ? (char **)&dev_name : NULL;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_OPEN_CONSOLE,
             (xdrproc_t)xdr_remote_domain_open_console_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        virNetClientRemoveStream(priv->client, netst);
        virObjectUnref(netst);
        st->driver = NULL;
        st->privateData = NULL;
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainPinIOThread(virDomainPtr dom, unsigned int iothreads_id, unsigned char *cpumap, int cpumaplen, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_pin_iothread_args args;

    remoteDriverLock(priv);

    if (cpumaplen > REMOTE_CPUMAP_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "cpumap", (int)cpumaplen, REMOTE_CPUMAP_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.iothreads_id = iothreads_id;
    args.cpumap.cpumap_val = (char *)cpumap;
    args.cpumap.cpumap_len = cpumaplen;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_IOTHREAD,
             (xdrproc_t)xdr_remote_domain_pin_iothread_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, int cpumaplen)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_pin_vcpu_args args;

    remoteDriverLock(priv);

    if (cpumaplen > REMOTE_CPUMAP_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "cpumap", (int)cpumaplen, REMOTE_CPUMAP_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.vcpu = vcpu;
    args.cpumap.cpumap_val = (char *)cpumap;
    args.cpumap.cpumap_len = cpumaplen;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU,
             (xdrproc_t)xdr_remote_domain_pin_vcpu_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainPinVcpuFlags(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, int cpumaplen, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_pin_vcpu_flags_args args;

    remoteDriverLock(priv);

    if (cpumaplen > REMOTE_CPUMAP_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "cpumap", (int)cpumaplen, REMOTE_CPUMAP_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.vcpu = vcpu;
    args.cpumap.cpumap_val = (char *)cpumap;
    args.cpumap.cpumap_len = cpumaplen;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS,
             (xdrproc_t)xdr_remote_domain_pin_vcpu_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainPMSuspendForDuration(virDomainPtr dom, unsigned int target, unsigned long long duration, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_pm_suspend_for_duration_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.target = target;
    args.duration = duration;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_PM_SUSPEND_FOR_DURATION,
             (xdrproc_t)xdr_remote_domain_pm_suspend_for_duration_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainPMWakeup(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_pm_wakeup_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_PM_WAKEUP,
             (xdrproc_t)xdr_remote_domain_pm_wakeup_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainReboot(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_reboot_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_REBOOT,
             (xdrproc_t)xdr_remote_domain_reboot_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainReset(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_reset_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_RESET,
             (xdrproc_t)xdr_remote_domain_reset_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainRestore(virConnectPtr conn, const char *from)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_domain_restore_args args;

    remoteDriverLock(priv);

    args.from = (char *)from;

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_RESTORE,
             (xdrproc_t)xdr_remote_domain_restore_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainRestoreFlags(virConnectPtr conn, const char *from, const char *dxml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_domain_restore_flags_args args;

    remoteDriverLock(priv);

    args.from = (char *)from;
    args.dxml = dxml ? (char **)&dxml : NULL;
    args.flags = flags;

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_RESTORE_FLAGS,
             (xdrproc_t)xdr_remote_domain_restore_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainResume(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_resume_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_RESUME,
             (xdrproc_t)xdr_remote_domain_resume_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainRevertToSnapshot(virDomainSnapshotPtr snap, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_revert_to_snapshot_args args;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.flags = flags;

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT,
             (xdrproc_t)xdr_remote_domain_revert_to_snapshot_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSave(virDomainPtr dom, const char *to)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_save_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.to = (char *)to;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE,
             (xdrproc_t)xdr_remote_domain_save_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    dom->id = -1;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_save_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.to = (char *)to;
    args.dxml = dxml ? (char **)&dxml : NULL;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE_FLAGS,
             (xdrproc_t)xdr_remote_domain_save_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSaveImageDefineXML(virConnectPtr conn, const char *file, const char *dxml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_domain_save_image_define_xml_args args;

    remoteDriverLock(priv);

    args.file = (char *)file;
    args.dxml = (char *)dxml;
    args.flags = flags;

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE_IMAGE_DEFINE_XML,
             (xdrproc_t)xdr_remote_domain_save_image_define_xml_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *file, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_domain_save_image_get_xml_desc_args args;
    remote_domain_save_image_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    args.file = (char *)file;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE_IMAGE_GET_XML_DESC,
             (xdrproc_t)xdr_remote_domain_save_image_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_save_image_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainScreenshot(virDomainPtr dom, virStreamPtr st, unsigned int screen, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_screenshot_args args;
    remote_domain_screenshot_ret ret;
    virNetClientStreamPtr netst = NULL;

    remoteDriverLock(priv);

    if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_DOMAIN_SCREENSHOT, priv->counter)))
        goto done;

    if (virNetClientAddStream(priv->client, netst) < 0) {
        virObjectUnref(netst);
        goto done;
    }
    st->driver = &remoteStreamDrv;
    st->privateData = netst;

    make_nonnull_domain(&args.dom, dom);
    args.screen = screen;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SCREENSHOT,
             (xdrproc_t)xdr_remote_domain_screenshot_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_screenshot_ret, (char *)&ret) == -1) {
        virNetClientRemoveStream(priv->client, netst);
        virObjectUnref(netst);
        st->driver = NULL;
        st->privateData = NULL;
        goto done;
    }

    rv = ret.mime ? *ret.mime : NULL;
    VIR_FREE(ret.mime);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSendKey(virDomainPtr dom, unsigned int codeset, unsigned int holdtime, unsigned int *keycodes, int keycodeslen, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_send_key_args args;

    remoteDriverLock(priv);

    if (keycodeslen > REMOTE_DOMAIN_SEND_KEY_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "keycodes", (int)keycodeslen, REMOTE_DOMAIN_SEND_KEY_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.codeset = codeset;
    args.holdtime = holdtime;
    args.keycodes.keycodes_val = keycodes;
    args.keycodes.keycodes_len = keycodeslen;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SEND_KEY,
             (xdrproc_t)xdr_remote_domain_send_key_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSendProcessSignal(virDomainPtr dom, long long pid_value, unsigned int signum, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_send_process_signal_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.pid_value = pid_value;
    args.signum = signum;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL,
             (xdrproc_t)xdr_remote_domain_send_process_signal_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetAutostart(virDomainPtr dom, int autostart)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_autostart_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.autostart = autostart;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_AUTOSTART,
             (xdrproc_t)xdr_remote_domain_set_autostart_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetBlkioParameters(virDomainPtr dom, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_blkio_parameters_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_blkio_parameters_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_BLKIO_PARAMETERS,
             (xdrproc_t)xdr_remote_domain_set_blkio_parameters_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetBlockIoTune(virDomainPtr dom, const char *disk, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_block_io_tune_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.disk = (char *)disk;
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_block_io_tune_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_BLOCK_IO_TUNE,
             (xdrproc_t)xdr_remote_domain_set_block_io_tune_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetBlockThreshold(virDomainPtr dom, const char *dev, unsigned long long threshold, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_block_threshold_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.dev = (char *)dev;
    args.threshold = threshold;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_BLOCK_THRESHOLD,
             (xdrproc_t)xdr_remote_domain_set_block_threshold_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetGuestVcpus(virDomainPtr dom, const char *cpumap, int state, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_guest_vcpus_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.cpumap = (char *)cpumap;
    args.state = state;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_GUEST_VCPUS,
             (xdrproc_t)xdr_remote_domain_set_guest_vcpus_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetInterfaceParameters(virDomainPtr dom, const char *device, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_interface_parameters_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.device = (char *)device;
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_interface_parameters_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS,
             (xdrproc_t)xdr_remote_domain_set_interface_parameters_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_max_memory_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.memory = memory;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MAX_MEMORY,
             (xdrproc_t)xdr_remote_domain_set_max_memory_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetMemory(virDomainPtr dom, unsigned long memory)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_memory_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.memory = memory;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY,
             (xdrproc_t)xdr_remote_domain_set_memory_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetMemoryFlags(virDomainPtr dom, unsigned long memory, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_memory_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.memory = memory;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS,
             (xdrproc_t)xdr_remote_domain_set_memory_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetMemoryParameters(virDomainPtr dom, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_memory_parameters_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_memory_parameters_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS,
             (xdrproc_t)xdr_remote_domain_set_memory_parameters_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetMemoryStatsPeriod(virDomainPtr dom, int period, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_memory_stats_period_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.period = period;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY_STATS_PERIOD,
             (xdrproc_t)xdr_remote_domain_set_memory_stats_period_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetMetadata(virDomainPtr dom, int type, const char *metadata, const char *key, const char *uri, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_metadata_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.type = type;
    args.metadata = metadata ? (char **)&metadata : NULL;
    args.key = key ? (char **)&key : NULL;
    args.uri = uri ? (char **)&uri : NULL;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_METADATA,
             (xdrproc_t)xdr_remote_domain_set_metadata_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetNumaParameters(virDomainPtr dom, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_numa_parameters_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_numa_parameters_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_NUMA_PARAMETERS,
             (xdrproc_t)xdr_remote_domain_set_numa_parameters_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetPerfEvents(virDomainPtr dom, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_perf_events_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_perf_events_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_PERF_EVENTS,
             (xdrproc_t)xdr_remote_domain_set_perf_events_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params, int nparams)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_scheduler_parameters_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_scheduler_parameters_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS,
             (xdrproc_t)xdr_remote_domain_set_scheduler_parameters_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetSchedulerParametersFlags(virDomainPtr dom, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_scheduler_parameters_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_domain_set_scheduler_parameters_flags_args, (char *)&args);
        goto done;
    }

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS,
             (xdrproc_t)xdr_remote_domain_set_scheduler_parameters_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetTime(virDomainPtr dom, long long seconds, unsigned int nseconds, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_time_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.seconds = seconds;
    args.nseconds = nseconds;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_TIME,
             (xdrproc_t)xdr_remote_domain_set_time_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetUserPassword(virDomainPtr dom, const char *user, const char *password, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_user_password_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.user = user ? (char **)&user : NULL;
    args.password = password ? (char **)&password : NULL;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_USER_PASSWORD,
             (xdrproc_t)xdr_remote_domain_set_user_password_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetVcpu(virDomainPtr dom, const char *cpumap, int state, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_vcpu_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.cpumap = (char *)cpumap;
    args.state = state;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPU,
             (xdrproc_t)xdr_remote_domain_set_vcpu_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_vcpus_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.nvcpus = nvcpus;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS,
             (xdrproc_t)xdr_remote_domain_set_vcpus_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_set_vcpus_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.nvcpus = nvcpus;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS,
             (xdrproc_t)xdr_remote_domain_set_vcpus_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainShutdown(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_shutdown_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SHUTDOWN,
             (xdrproc_t)xdr_remote_domain_shutdown_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_shutdown_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS,
             (xdrproc_t)xdr_remote_domain_shutdown_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainSnapshotPtr
remoteDomainSnapshotCreateXML(virDomainPtr dom, const char *xml_desc, unsigned int flags)
{
    virDomainSnapshotPtr rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_snapshot_create_xml_args args;
    remote_domain_snapshot_create_xml_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.xml_desc = (char *)xml_desc;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML,
             (xdrproc_t)xdr_remote_domain_snapshot_create_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_create_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain_snapshot(dom, ret.snap);
    xdr_free((xdrproc_t)xdr_remote_domain_snapshot_create_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainSnapshotPtr
remoteDomainSnapshotCurrent(virDomainPtr dom, unsigned int flags)
{
    virDomainSnapshotPtr rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_snapshot_current_args args;
    remote_domain_snapshot_current_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT,
             (xdrproc_t)xdr_remote_domain_snapshot_current_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_current_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain_snapshot(dom, ret.snap);
    xdr_free((xdrproc_t)xdr_remote_domain_snapshot_current_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotDelete(virDomainSnapshotPtr snap, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_snapshot_delete_args args;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.flags = flags;

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE,
             (xdrproc_t)xdr_remote_domain_snapshot_delete_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainSnapshotPtr
remoteDomainSnapshotGetParent(virDomainSnapshotPtr snap, unsigned int flags)
{
    virDomainSnapshotPtr rv = NULL;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_snapshot_get_parent_args args;
    remote_domain_snapshot_get_parent_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT,
             (xdrproc_t)xdr_remote_domain_snapshot_get_parent_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_get_parent_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain_snapshot(snap->domain, ret.snap);
    xdr_free((xdrproc_t)xdr_remote_domain_snapshot_get_parent_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snap, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_snapshot_get_xml_desc_args args;
    remote_domain_snapshot_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_GET_XML_DESC,
             (xdrproc_t)xdr_remote_domain_snapshot_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotHasMetadata(virDomainSnapshotPtr snap, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_snapshot_has_metadata_args args;
    remote_domain_snapshot_has_metadata_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_HAS_METADATA,
             (xdrproc_t)xdr_remote_domain_snapshot_has_metadata_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_has_metadata_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.metadata;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotIsCurrent(virDomainSnapshotPtr snap, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_snapshot_is_current_args args;
    remote_domain_snapshot_is_current_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_IS_CURRENT,
             (xdrproc_t)xdr_remote_domain_snapshot_is_current_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_is_current_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.current;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot, virDomainSnapshotPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = snapshot->domain->conn->privateData;
    remote_domain_snapshot_list_all_children_args args;
    remote_domain_snapshot_list_all_children_ret ret;
    virDomainSnapshotPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snapshot, snapshot);
    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN,
             (xdrproc_t)xdr_remote_domain_snapshot_list_all_children_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_list_all_children_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.snapshots.snapshots_len > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote domain_snapshots: %d > %d"),
                       ret.snapshots.snapshots_len, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.snapshots.snapshots_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.snapshots.snapshots_len; i++) {
            tmp_results[i] = get_nonnull_domain_snapshot(snapshot->domain, ret.snapshots.snapshots_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.snapshots.snapshots_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_domain_snapshot_list_all_children_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotListChildrenNames(virDomainSnapshotPtr snap, char **const names, int maxnames, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_snapshot_list_children_names_args args;
    remote_domain_snapshot_list_children_names_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
        goto done;
    }

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.maxnames = maxnames;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_CHILDREN_NAMES,
             (xdrproc_t)xdr_remote_domain_snapshot_list_children_names_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_list_children_names_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_domain_snapshot_list_children_names_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotListNames(virDomainPtr dom, char **const names, int maxnames, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_snapshot_list_names_args args;
    remote_domain_snapshot_list_names_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_DOMAIN_SNAPSHOT_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_DOMAIN_SNAPSHOT_LIST_MAX);
        goto done;
    }

    make_nonnull_domain(&args.dom, dom);
    args.maxnames = maxnames;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES,
             (xdrproc_t)xdr_remote_domain_snapshot_list_names_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_list_names_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_domain_snapshot_list_names_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virDomainSnapshotPtr
remoteDomainSnapshotLookupByName(virDomainPtr dom, const char *name, unsigned int flags)
{
    virDomainSnapshotPtr rv = NULL;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_snapshot_lookup_by_name_args args;
    remote_domain_snapshot_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.name = (char *)name;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_domain_snapshot_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_domain_snapshot(dom, ret.snap);
    xdr_free((xdrproc_t)xdr_remote_domain_snapshot_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotNum(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_snapshot_num_args args;
    remote_domain_snapshot_num_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_NUM,
             (xdrproc_t)xdr_remote_domain_snapshot_num_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_num_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSnapshotNumChildren(virDomainSnapshotPtr snap, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = snap->domain->conn->privateData;
    remote_domain_snapshot_num_children_args args;
    remote_domain_snapshot_num_children_ret ret;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snap);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(snap->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_NUM_CHILDREN,
             (xdrproc_t)xdr_remote_domain_snapshot_num_children_args, (char *)&args,
             (xdrproc_t)xdr_remote_domain_snapshot_num_children_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainSuspend(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_suspend_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SUSPEND,
             (xdrproc_t)xdr_remote_domain_suspend_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainUndefine(virDomainPtr dom)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_undefine_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_UNDEFINE,
             (xdrproc_t)xdr_remote_domain_undefine_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_undefine_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS,
             (xdrproc_t)xdr_remote_domain_undefine_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = dom->conn->privateData;
    remote_domain_update_device_flags_args args;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, dom);
    args.xml = (char *)xml;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_UPDATE_DEVICE_FLAGS,
             (xdrproc_t)xdr_remote_domain_update_device_flags_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteInterfaceChangeBegin(virConnectPtr conn, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_interface_change_begin_args args;

    remoteDriverLock(priv);

    args.flags = flags;

    if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_CHANGE_BEGIN,
             (xdrproc_t)xdr_remote_interface_change_begin_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteInterfaceChangeCommit(virConnectPtr conn, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_interface_change_commit_args args;

    remoteDriverLock(priv);

    args.flags = flags;

    if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_CHANGE_COMMIT,
             (xdrproc_t)xdr_remote_interface_change_commit_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteInterfaceChangeRollback(virConnectPtr conn, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_interface_change_rollback_args args;

    remoteDriverLock(priv);

    args.flags = flags;

    if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_CHANGE_ROLLBACK,
             (xdrproc_t)xdr_remote_interface_change_rollback_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteInterfaceCreate(virInterfacePtr iface, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = iface->conn->privateData;
    remote_interface_create_args args;

    remoteDriverLock(priv);

    make_nonnull_interface(&args.iface, iface);
    args.flags = flags;

    if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_CREATE,
             (xdrproc_t)xdr_remote_interface_create_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virInterfacePtr
remoteInterfaceDefineXML(virConnectPtr conn, const char *xml, unsigned int flags)
{
    virInterfacePtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_interface_define_xml_args args;
    remote_interface_define_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_DEFINE_XML,
             (xdrproc_t)xdr_remote_interface_define_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_interface_define_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_interface(conn, ret.iface);
    xdr_free((xdrproc_t)xdr_remote_interface_define_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteInterfaceDestroy(virInterfacePtr iface, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = iface->conn->privateData;
    remote_interface_destroy_args args;

    remoteDriverLock(priv);

    make_nonnull_interface(&args.iface, iface);
    args.flags = flags;

    if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_DESTROY,
             (xdrproc_t)xdr_remote_interface_destroy_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = iface->conn->privateData;
    remote_interface_get_xml_desc_args args;
    remote_interface_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_interface(&args.iface, iface);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_GET_XML_DESC,
             (xdrproc_t)xdr_remote_interface_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_interface_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteInterfaceIsActive(virInterfacePtr iface)
{
    int rv = -1;
    struct private_data *priv = iface->conn->privateData;
    remote_interface_is_active_args args;
    remote_interface_is_active_ret ret;

    remoteDriverLock(priv);

    make_nonnull_interface(&args.iface, iface);

    memset(&ret, 0, sizeof(ret));

    if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_IS_ACTIVE,
             (xdrproc_t)xdr_remote_interface_is_active_args, (char *)&args,
             (xdrproc_t)xdr_remote_interface_is_active_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virInterfacePtr
remoteInterfaceLookupByMACString(virConnectPtr conn, const char *mac)
{
    virInterfacePtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_interface_lookup_by_mac_string_args args;
    remote_interface_lookup_by_mac_string_ret ret;

    remoteDriverLock(priv);

    args.mac = (char *)mac;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING,
             (xdrproc_t)xdr_remote_interface_lookup_by_mac_string_args, (char *)&args,
             (xdrproc_t)xdr_remote_interface_lookup_by_mac_string_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_interface(conn, ret.iface);
    xdr_free((xdrproc_t)xdr_remote_interface_lookup_by_mac_string_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virInterfacePtr
remoteInterfaceLookupByName(virConnectPtr conn, const char *name)
{
    virInterfacePtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_interface_lookup_by_name_args args;
    remote_interface_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    args.name = (char *)name;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_interface_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_interface_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_interface(conn, ret.iface);
    xdr_free((xdrproc_t)xdr_remote_interface_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteInterfaceUndefine(virInterfacePtr iface)
{
    int rv = -1;
    struct private_data *priv = iface->conn->privateData;
    remote_interface_undefine_args args;

    remoteDriverLock(priv);

    make_nonnull_interface(&args.iface, iface);

    if (call(iface->conn, priv, 0, REMOTE_PROC_INTERFACE_UNDEFINE,
             (xdrproc_t)xdr_remote_interface_undefine_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkCreate(virNetworkPtr net)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_create_args args;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_CREATE,
             (xdrproc_t)xdr_remote_network_create_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNetworkPtr
remoteNetworkCreateXML(virConnectPtr conn, const char *xml)
{
    virNetworkPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_network_create_xml_args args;
    remote_network_create_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NETWORK_CREATE_XML,
             (xdrproc_t)xdr_remote_network_create_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_create_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_network(conn, ret.net);
    xdr_free((xdrproc_t)xdr_remote_network_create_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNetworkPtr
remoteNetworkDefineXML(virConnectPtr conn, const char *xml)
{
    virNetworkPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_network_define_xml_args args;
    remote_network_define_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NETWORK_DEFINE_XML,
             (xdrproc_t)xdr_remote_network_define_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_define_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_network(conn, ret.net);
    xdr_free((xdrproc_t)xdr_remote_network_define_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkDestroy(virNetworkPtr net)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_destroy_args args;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_DESTROY,
             (xdrproc_t)xdr_remote_network_destroy_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkGetAutostart(virNetworkPtr net, int *autostart)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_get_autostart_args args;
    remote_network_get_autostart_ret ret;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);

    memset(&ret, 0, sizeof(ret));

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_AUTOSTART,
             (xdrproc_t)xdr_remote_network_get_autostart_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_get_autostart_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (autostart) *autostart = ret.autostart;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteNetworkGetBridgeName(virNetworkPtr net)
{
    char *rv = NULL;
    struct private_data *priv = net->conn->privateData;
    remote_network_get_bridge_name_args args;
    remote_network_get_bridge_name_ret ret;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);

    memset(&ret, 0, sizeof(ret));

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_BRIDGE_NAME,
             (xdrproc_t)xdr_remote_network_get_bridge_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_get_bridge_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.name;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteNetworkGetXMLDesc(virNetworkPtr net, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = net->conn->privateData;
    remote_network_get_xml_desc_args args;
    remote_network_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_XML_DESC,
             (xdrproc_t)xdr_remote_network_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkIsActive(virNetworkPtr net)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_is_active_args args;
    remote_network_is_active_ret ret;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);

    memset(&ret, 0, sizeof(ret));

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_IS_ACTIVE,
             (xdrproc_t)xdr_remote_network_is_active_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_is_active_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkIsPersistent(virNetworkPtr net)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_is_persistent_args args;
    remote_network_is_persistent_ret ret;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);

    memset(&ret, 0, sizeof(ret));

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_IS_PERSISTENT,
             (xdrproc_t)xdr_remote_network_is_persistent_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_is_persistent_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.persistent;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNetworkPtr
remoteNetworkLookupByName(virConnectPtr conn, const char *name)
{
    virNetworkPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_network_lookup_by_name_args args;
    remote_network_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    args.name = (char *)name;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_network_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_network(conn, ret.net);
    xdr_free((xdrproc_t)xdr_remote_network_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNetworkPtr
remoteNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
    virNetworkPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_network_lookup_by_uuid_args args;
    remote_network_lookup_by_uuid_ret ret;

    remoteDriverLock(priv);

    memcpy(args.uuid, uuid, VIR_UUID_BUFLEN);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_UUID,
             (xdrproc_t)xdr_remote_network_lookup_by_uuid_args, (char *)&args,
             (xdrproc_t)xdr_remote_network_lookup_by_uuid_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_network(conn, ret.net);
    xdr_free((xdrproc_t)xdr_remote_network_lookup_by_uuid_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkSetAutostart(virNetworkPtr net, int autostart)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_set_autostart_args args;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);
    args.autostart = autostart;

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_SET_AUTOSTART,
             (xdrproc_t)xdr_remote_network_set_autostart_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkUndefine(virNetworkPtr net)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_undefine_args args;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_UNDEFINE,
             (xdrproc_t)xdr_remote_network_undefine_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkUpdate(virNetworkPtr net, unsigned int command, unsigned int section, int parentIndex, const char *xml, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = net->conn->privateData;
    remote_network_update_args args;

    remoteDriverLock(priv);

    make_nonnull_network(&args.net, net);
    args.command = command;
    args.section = section;
    args.parentIndex = parentIndex;
    args.xml = (char *)xml;
    args.flags = flags;

    if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_UPDATE,
             (xdrproc_t)xdr_remote_network_update_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNodeDevicePtr
remoteNodeDeviceCreateXML(virConnectPtr conn, const char *xml_desc, unsigned int flags)
{
    virNodeDevicePtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_node_device_create_xml_args args;
    remote_node_device_create_xml_ret ret;

    remoteDriverLock(priv);

    args.xml_desc = (char *)xml_desc;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_CREATE_XML,
             (xdrproc_t)xdr_remote_node_device_create_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_device_create_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_node_device(conn, ret.dev);
    xdr_free((xdrproc_t)xdr_remote_node_device_create_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int rv = -1;
    struct private_data *priv = dev->conn->privateData;
    remote_node_device_destroy_args args;

    remoteDriverLock(priv);

    args.name = dev->name;

    if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DESTROY,
             (xdrproc_t)xdr_remote_node_device_destroy_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteNodeDeviceGetParent(virNodeDevicePtr dev)
{
    char *rv = NULL;
    struct private_data *priv = dev->conn->privateData;
    remote_node_device_get_parent_args args;
    remote_node_device_get_parent_ret ret;

    remoteDriverLock(priv);

    args.name = dev->name;

    memset(&ret, 0, sizeof(ret));

    if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_GET_PARENT,
             (xdrproc_t)xdr_remote_node_device_get_parent_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_device_get_parent_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.parent ? *ret.parent : NULL;
    VIR_FREE(ret.parent);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteNodeDeviceGetXMLDesc(virNodeDevicePtr dev, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = dev->conn->privateData;
    remote_node_device_get_xml_desc_args args;
    remote_node_device_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    args.name = dev->name;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_GET_XML_DESC,
             (xdrproc_t)xdr_remote_node_device_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_device_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = dev->conn->privateData;
    remote_node_device_list_caps_args args;
    remote_node_device_list_caps_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_NODE_DEVICE_CAPS_LIST_MAX);
        goto done;
    }

    args.name = dev->name;
    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LIST_CAPS,
             (xdrproc_t)xdr_remote_node_device_list_caps_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_device_list_caps_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_node_device_list_caps_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNodeDevicePtr
remoteNodeDeviceLookupByName(virConnectPtr conn, const char *name)
{
    virNodeDevicePtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_node_device_lookup_by_name_args args;
    remote_node_device_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    args.name = (char *)name;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_node_device_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_device_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_node_device(conn, ret.dev);
    xdr_free((xdrproc_t)xdr_remote_node_device_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNodeDevicePtr
remoteNodeDeviceLookupSCSIHostByWWN(virConnectPtr conn, const char *wwnn, const char *wwpn, unsigned int flags)
{
    virNodeDevicePtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_node_device_lookup_scsi_host_by_wwn_args args;
    remote_node_device_lookup_scsi_host_by_wwn_ret ret;

    remoteDriverLock(priv);

    args.wwnn = (char *)wwnn;
    args.wwpn = (char *)wwpn;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LOOKUP_SCSI_HOST_BY_WWN,
             (xdrproc_t)xdr_remote_node_device_lookup_scsi_host_by_wwn_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_device_lookup_scsi_host_by_wwn_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_node_device(conn, ret.dev);
    xdr_free((xdrproc_t)xdr_remote_node_device_lookup_scsi_host_by_wwn_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
    int rv = -1;
    struct private_data *priv = dev->conn->privateData;
    remote_node_device_num_of_caps_args args;
    remote_node_device_num_of_caps_ret ret;

    remoteDriverLock(priv);

    args.name = dev->name;

    memset(&ret, 0, sizeof(ret));

    if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS,
             (xdrproc_t)xdr_remote_node_device_num_of_caps_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_device_num_of_caps_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static unsigned long long
remoteNodeGetFreeMemory(virConnectPtr conn)
{
    unsigned long long rv = 0;
    struct private_data *priv = conn->privateData;
    remote_node_get_free_memory_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_MEMORY,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_node_get_free_memory_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.freeMem;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeGetInfo(virConnectPtr conn, virNodeInfoPtr result)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_node_get_info_ret ret;

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_INFO,
             (xdrproc_t)xdr_void, (char *)NULL,
             (xdrproc_t)xdr_remote_node_get_info_ret, (char *)&ret) == -1) {
        goto done;
    }

    memcpy(result->model, ret.model, sizeof(result->model));
    HYPER_TO_ULONG(result->memory, ret.memory);
    result->cpus = ret.cpus;
    result->mhz = ret.mhz;
    result->nodes = ret.nodes;
    result->sockets = ret.sockets;
    result->cores = ret.cores;
    result->threads = ret.threads;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeListDevices(virConnectPtr conn, const char *cap, char **const names, int maxnames, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_node_list_devices_args args;
    remote_node_list_devices_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_NODE_DEVICE_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_NODE_DEVICE_LIST_MAX);
        goto done;
    }

    args.cap = cap ? (char **)&cap : NULL;
    args.maxnames = maxnames;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NODE_LIST_DEVICES,
             (xdrproc_t)xdr_remote_node_list_devices_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_list_devices_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_node_list_devices_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeNumOfDevices(virConnectPtr conn, const char *cap, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_node_num_of_devices_args args;
    remote_node_num_of_devices_ret ret;

    remoteDriverLock(priv);

    args.cap = cap ? (char **)&cap : NULL;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NODE_NUM_OF_DEVICES,
             (xdrproc_t)xdr_remote_node_num_of_devices_args, (char *)&args,
             (xdrproc_t)xdr_remote_node_num_of_devices_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeSetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int nparams, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_node_set_memory_parameters_args args;

    remoteDriverLock(priv);

    args.flags = flags;

    if (virTypedParamsSerialize(params, nparams,
                                (virTypedParameterRemotePtr *) &args.params.params_val,
                                &args.params.params_len,
                                VIR_TYPED_PARAM_STRING_OKAY) < 0) {
        xdr_free((xdrproc_t)xdr_remote_node_set_memory_parameters_args, (char *)&args);
        goto done;
    }

    if (call(conn, priv, 0, REMOTE_PROC_NODE_SET_MEMORY_PARAMETERS,
             (xdrproc_t)xdr_remote_node_set_memory_parameters_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    virTypedParamsRemoteFree((virTypedParameterRemotePtr) args.params.params_val,
                             args.params.params_len);
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeSuspendForDuration(virConnectPtr conn, unsigned int target, unsigned long long duration, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_node_suspend_for_duration_args args;

    remoteDriverLock(priv);

    args.target = target;
    args.duration = duration;
    args.flags = flags;

    if (call(conn, priv, 0, REMOTE_PROC_NODE_SUSPEND_FOR_DURATION,
             (xdrproc_t)xdr_remote_node_suspend_for_duration_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNWFilterPtr
remoteNWFilterDefineXML(virConnectPtr conn, const char *xml)
{
    virNWFilterPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_nwfilter_define_xml_args args;
    remote_nwfilter_define_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NWFILTER_DEFINE_XML,
             (xdrproc_t)xdr_remote_nwfilter_define_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_nwfilter_define_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_nwfilter(conn, ret.nwfilter);
    xdr_free((xdrproc_t)xdr_remote_nwfilter_define_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteNWFilterGetXMLDesc(virNWFilterPtr nwfilter, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = nwfilter->conn->privateData;
    remote_nwfilter_get_xml_desc_args args;
    remote_nwfilter_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_nwfilter(&args.nwfilter, nwfilter);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_GET_XML_DESC,
             (xdrproc_t)xdr_remote_nwfilter_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_nwfilter_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNWFilterPtr
remoteNWFilterLookupByName(virConnectPtr conn, const char *name)
{
    virNWFilterPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_nwfilter_lookup_by_name_args args;
    remote_nwfilter_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    args.name = (char *)name;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_nwfilter_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_nwfilter_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_nwfilter(conn, ret.nwfilter);
    xdr_free((xdrproc_t)xdr_remote_nwfilter_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virNWFilterPtr
remoteNWFilterLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
    virNWFilterPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_nwfilter_lookup_by_uuid_args args;
    remote_nwfilter_lookup_by_uuid_ret ret;

    remoteDriverLock(priv);

    memcpy(args.uuid, uuid, VIR_UUID_BUFLEN);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID,
             (xdrproc_t)xdr_remote_nwfilter_lookup_by_uuid_args, (char *)&args,
             (xdrproc_t)xdr_remote_nwfilter_lookup_by_uuid_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_nwfilter(conn, ret.nwfilter);
    xdr_free((xdrproc_t)xdr_remote_nwfilter_lookup_by_uuid_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNWFilterUndefine(virNWFilterPtr nwfilter)
{
    int rv = -1;
    struct private_data *priv = nwfilter->conn->privateData;
    remote_nwfilter_undefine_args args;

    remoteDriverLock(priv);

    make_nonnull_nwfilter(&args.nwfilter, nwfilter);

    if (call(nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_UNDEFINE,
             (xdrproc_t)xdr_remote_nwfilter_undefine_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virSecretPtr
remoteSecretDefineXML(virConnectPtr conn, const char *xml, unsigned int flags)
{
    virSecretPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_secret_define_xml_args args;
    remote_secret_define_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_SECRET_DEFINE_XML,
             (xdrproc_t)xdr_remote_secret_define_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_secret_define_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_secret(conn, ret.secret);
    xdr_free((xdrproc_t)xdr_remote_secret_define_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteSecretGetXMLDesc(virSecretPtr secret, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = secret->conn->privateData;
    remote_secret_get_xml_desc_args args;
    remote_secret_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_secret(&args.secret, secret);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(secret->conn, priv, 0, REMOTE_PROC_SECRET_GET_XML_DESC,
             (xdrproc_t)xdr_remote_secret_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_secret_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virSecretPtr
remoteSecretLookupByUsage(virConnectPtr conn, int usageType, const char *usageID)
{
    virSecretPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_secret_lookup_by_usage_args args;
    remote_secret_lookup_by_usage_ret ret;

    remoteDriverLock(priv);

    args.usageType = usageType;
    args.usageID = (char *)usageID;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_USAGE,
             (xdrproc_t)xdr_remote_secret_lookup_by_usage_args, (char *)&args,
             (xdrproc_t)xdr_remote_secret_lookup_by_usage_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_secret(conn, ret.secret);
    xdr_free((xdrproc_t)xdr_remote_secret_lookup_by_usage_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virSecretPtr
remoteSecretLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
    virSecretPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_secret_lookup_by_uuid_args args;
    remote_secret_lookup_by_uuid_ret ret;

    remoteDriverLock(priv);

    memcpy(args.uuid, uuid, VIR_UUID_BUFLEN);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_UUID,
             (xdrproc_t)xdr_remote_secret_lookup_by_uuid_args, (char *)&args,
             (xdrproc_t)xdr_remote_secret_lookup_by_uuid_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_secret(conn, ret.secret);
    xdr_free((xdrproc_t)xdr_remote_secret_lookup_by_uuid_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteSecretSetValue(virSecretPtr secret, const unsigned char *value, size_t valuelen, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = secret->conn->privateData;
    remote_secret_set_value_args args;

    remoteDriverLock(priv);

    if (valuelen > REMOTE_SECRET_VALUE_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("%s length greater than maximum: %d > %d"),
                       "value", (int)valuelen, REMOTE_SECRET_VALUE_MAX);
        goto done;
    }

    make_nonnull_secret(&args.secret, secret);
    args.value.value_val = (char *)value;
    args.value.value_len = valuelen;
    args.flags = flags;

    if (call(secret->conn, priv, 0, REMOTE_PROC_SECRET_SET_VALUE,
             (xdrproc_t)xdr_remote_secret_set_value_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteSecretUndefine(virSecretPtr secret)
{
    int rv = -1;
    struct private_data *priv = secret->conn->privateData;
    remote_secret_undefine_args args;

    remoteDriverLock(priv);

    make_nonnull_secret(&args.secret, secret);

    if (call(secret->conn, priv, 0, REMOTE_PROC_SECRET_UNDEFINE,
             (xdrproc_t)xdr_remote_secret_undefine_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolBuild(virStoragePoolPtr pool, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_build_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.flags = flags;

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_BUILD,
             (xdrproc_t)xdr_remote_storage_pool_build_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolCreate(virStoragePoolPtr pool, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_create_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.flags = flags;

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE,
             (xdrproc_t)xdr_remote_storage_pool_create_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStoragePoolPtr
remoteStoragePoolCreateXML(virConnectPtr conn, const char *xml, unsigned int flags)
{
    virStoragePoolPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_storage_pool_create_xml_args args;
    remote_storage_pool_create_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE_XML,
             (xdrproc_t)xdr_remote_storage_pool_create_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_create_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_pool(conn, ret.pool);
    xdr_free((xdrproc_t)xdr_remote_storage_pool_create_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStoragePoolPtr
remoteStoragePoolDefineXML(virConnectPtr conn, const char *xml, unsigned int flags)
{
    virStoragePoolPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_storage_pool_define_xml_args args;
    remote_storage_pool_define_xml_ret ret;

    remoteDriverLock(priv);

    args.xml = (char *)xml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DEFINE_XML,
             (xdrproc_t)xdr_remote_storage_pool_define_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_define_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_pool(conn, ret.pool);
    xdr_free((xdrproc_t)xdr_remote_storage_pool_define_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolDelete(virStoragePoolPtr pool, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_delete_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.flags = flags;

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DELETE,
             (xdrproc_t)xdr_remote_storage_pool_delete_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolDestroy(virStoragePoolPtr pool)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_destroy_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DESTROY,
             (xdrproc_t)xdr_remote_storage_pool_destroy_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolGetAutostart(virStoragePoolPtr pool, int *autostart)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_get_autostart_args args;
    remote_storage_pool_get_autostart_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART,
             (xdrproc_t)xdr_remote_storage_pool_get_autostart_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_get_autostart_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (autostart) *autostart = ret.autostart;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolGetInfo(virStoragePoolPtr pool, virStoragePoolInfoPtr result)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_get_info_args args;
    remote_storage_pool_get_info_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_INFO,
             (xdrproc_t)xdr_remote_storage_pool_get_info_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_get_info_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->state = ret.state;
    result->capacity = ret.capacity;
    result->allocation = ret.allocation;
    result->available = ret.available;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteStoragePoolGetXMLDesc(virStoragePoolPtr pool, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_get_xml_desc_args args;
    remote_storage_pool_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_XML_DESC,
             (xdrproc_t)xdr_remote_storage_pool_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolIsActive(virStoragePoolPtr pool)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_is_active_args args;
    remote_storage_pool_is_active_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_ACTIVE,
             (xdrproc_t)xdr_remote_storage_pool_is_active_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_is_active_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolIsPersistent(virStoragePoolPtr pool)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_is_persistent_args args;
    remote_storage_pool_is_persistent_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT,
             (xdrproc_t)xdr_remote_storage_pool_is_persistent_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_is_persistent_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.persistent;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolListAllVolumes(virStoragePoolPtr pool, virStorageVolPtr **result, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_list_all_volumes_args args;
    remote_storage_pool_list_all_volumes_ret ret;
    virStorageVolPtr *tmp_results = NULL;
    size_t i;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.flags = flags;
    args.need_results = !!result;

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LIST_ALL_VOLUMES,
             (xdrproc_t)xdr_remote_storage_pool_list_all_volumes_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_list_all_volumes_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.vols.vols_len > REMOTE_STORAGE_VOL_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote storage_vols: %d > %d"),
                       ret.vols.vols_len, REMOTE_STORAGE_VOL_LIST_MAX);
        goto cleanup;
    }

    if (result) {
        if (VIR_ALLOC_N(tmp_results, ret.vols.vols_len + 1) < 0)
            goto cleanup;

        for (i = 0; i < ret.vols.vols_len; i++) {
            tmp_results[i] = get_nonnull_storage_vol(pool->conn, ret.vols.vols_val[i]);
            if (!tmp_results[i])
                goto cleanup;
        }
        *result = tmp_results;
        tmp_results = NULL;
    }

    rv = ret.ret;

cleanup:
    if (tmp_results) {
        for (i = 0; i < ret.vols.vols_len; i++)
            virObjectUnref(tmp_results[i]);
        VIR_FREE(tmp_results);
    }

    xdr_free((xdrproc_t)xdr_remote_storage_pool_list_all_volumes_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolListVolumes(virStoragePoolPtr pool, char **const names, int maxnames)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_list_volumes_args args;
    remote_storage_pool_list_volumes_ret ret;
    size_t i;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_STORAGE_VOL_LIST_MAX) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       maxnames, REMOTE_STORAGE_VOL_LIST_MAX);
        goto done;
    }

    make_nonnull_storage_pool(&args.pool, pool);
    args.maxnames = maxnames;

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES,
             (xdrproc_t)xdr_remote_storage_pool_list_volumes_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_list_volumes_ret, (char *)&ret) == -1) {
        goto done;
    }

    if (ret.names.names_len > maxnames) {
        virReportError(VIR_ERR_RPC,
                       _("too many remote undefineds: %d > %d"),
                       ret.names.names_len, maxnames);
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to VIR_STRDUP the
     * names here. */
    for (i = 0; i < ret.names.names_len; ++i) {
        if (VIR_STRDUP(names[i],
                       ret.names.names_val[i]) < 0) {
            size_t j;
            for (j = 0; j < i; j++)
                VIR_FREE(names[j]);

            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free((xdrproc_t)xdr_remote_storage_pool_list_volumes_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStoragePoolPtr
remoteStoragePoolLookupByName(virConnectPtr conn, const char *name)
{
    virStoragePoolPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_storage_pool_lookup_by_name_args args;
    remote_storage_pool_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    args.name = (char *)name;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_storage_pool_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_pool(conn, ret.pool);
    xdr_free((xdrproc_t)xdr_remote_storage_pool_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStoragePoolPtr
remoteStoragePoolLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
    virStoragePoolPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_storage_pool_lookup_by_uuid_args args;
    remote_storage_pool_lookup_by_uuid_ret ret;

    remoteDriverLock(priv);

    memcpy(args.uuid, uuid, VIR_UUID_BUFLEN);

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID,
             (xdrproc_t)xdr_remote_storage_pool_lookup_by_uuid_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_lookup_by_uuid_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_pool(conn, ret.pool);
    xdr_free((xdrproc_t)xdr_remote_storage_pool_lookup_by_uuid_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStoragePoolPtr
remoteStoragePoolLookupByVolume(virStorageVolPtr vol)
{
    virStoragePoolPtr rv = NULL;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_pool_lookup_by_volume_args args;
    remote_storage_pool_lookup_by_volume_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);

    memset(&ret, 0, sizeof(ret));

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME,
             (xdrproc_t)xdr_remote_storage_pool_lookup_by_volume_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_lookup_by_volume_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_pool(vol->conn, ret.pool);
    xdr_free((xdrproc_t)xdr_remote_storage_pool_lookup_by_volume_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolNumOfVolumes(virStoragePoolPtr pool)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_num_of_volumes_args args;
    remote_storage_pool_num_of_volumes_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES,
             (xdrproc_t)xdr_remote_storage_pool_num_of_volumes_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_pool_num_of_volumes_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolRefresh(virStoragePoolPtr pool, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_refresh_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.flags = flags;

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_REFRESH,
             (xdrproc_t)xdr_remote_storage_pool_refresh_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolSetAutostart(virStoragePoolPtr pool, int autostart)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_set_autostart_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.autostart = autostart;

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART,
             (xdrproc_t)xdr_remote_storage_pool_set_autostart_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolUndefine(virStoragePoolPtr pool)
{
    int rv = -1;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_pool_undefine_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_UNDEFINE,
             (xdrproc_t)xdr_remote_storage_pool_undefine_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStorageVolPtr
remoteStorageVolCreateXML(virStoragePoolPtr pool, const char *xml, unsigned int flags)
{
    virStorageVolPtr rv = NULL;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_vol_create_xml_args args;
    remote_storage_vol_create_xml_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.xml = (char *)xml;
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML,
             (xdrproc_t)xdr_remote_storage_vol_create_xml_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_create_xml_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_vol(pool->conn, ret.vol);
    xdr_free((xdrproc_t)xdr_remote_storage_vol_create_xml_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStorageVolPtr
remoteStorageVolCreateXMLFrom(virStoragePoolPtr pool, const char *xml, virStorageVolPtr clonevol, unsigned int flags)
{
    virStorageVolPtr rv = NULL;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_vol_create_xml_from_args args;
    remote_storage_vol_create_xml_from_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.xml = (char *)xml;
    make_nonnull_storage_vol(&args.clonevol, clonevol);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM,
             (xdrproc_t)xdr_remote_storage_vol_create_xml_from_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_create_xml_from_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_vol(pool->conn, ret.vol);
    xdr_free((xdrproc_t)xdr_remote_storage_vol_create_xml_from_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStorageVolDelete(virStorageVolPtr vol, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_delete_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);
    args.flags = flags;

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DELETE,
             (xdrproc_t)xdr_remote_storage_vol_delete_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStorageVolDownload(virStorageVolPtr vol, virStreamPtr st, unsigned long long offset, unsigned long long length, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_download_args args;
    virNetClientStreamPtr netst = NULL;

    remoteDriverLock(priv);

    if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_STORAGE_VOL_DOWNLOAD, priv->counter)))
        goto done;

    if (virNetClientAddStream(priv->client, netst) < 0) {
        virObjectUnref(netst);
        goto done;
    }
    st->driver = &remoteStreamDrv;
    st->privateData = netst;

    make_nonnull_storage_vol(&args.vol, vol);
    args.offset = offset;
    args.length = length;
    args.flags = flags;

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DOWNLOAD,
             (xdrproc_t)xdr_remote_storage_vol_download_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        virNetClientRemoveStream(priv->client, netst);
        virObjectUnref(netst);
        st->driver = NULL;
        st->privateData = NULL;
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStorageVolGetInfo(virStorageVolPtr vol, virStorageVolInfoPtr result)
{
    int rv = -1;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_get_info_args args;
    remote_storage_vol_get_info_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);

    memset(&ret, 0, sizeof(ret));

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_INFO,
             (xdrproc_t)xdr_remote_storage_vol_get_info_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_get_info_ret, (char *)&ret) == -1) {
        goto done;
    }

    result->type = ret.type;
    result->capacity = ret.capacity;
    result->allocation = ret.allocation;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteStorageVolGetPath(virStorageVolPtr vol)
{
    char *rv = NULL;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_get_path_args args;
    remote_storage_vol_get_path_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);

    memset(&ret, 0, sizeof(ret));

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_PATH,
             (xdrproc_t)xdr_remote_storage_vol_get_path_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_get_path_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.name;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteStorageVolGetXMLDesc(virStorageVolPtr vol, unsigned int flags)
{
    char *rv = NULL;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_get_xml_desc_args args;
    remote_storage_vol_get_xml_desc_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);
    args.flags = flags;

    memset(&ret, 0, sizeof(ret));

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_XML_DESC,
             (xdrproc_t)xdr_remote_storage_vol_get_xml_desc_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_get_xml_desc_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStorageVolPtr
remoteStorageVolLookupByKey(virConnectPtr conn, const char *key)
{
    virStorageVolPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_storage_vol_lookup_by_key_args args;
    remote_storage_vol_lookup_by_key_ret ret;

    remoteDriverLock(priv);

    args.key = (char *)key;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY,
             (xdrproc_t)xdr_remote_storage_vol_lookup_by_key_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_lookup_by_key_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_vol(conn, ret.vol);
    xdr_free((xdrproc_t)xdr_remote_storage_vol_lookup_by_key_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStorageVolPtr
remoteStorageVolLookupByName(virStoragePoolPtr pool, const char *name)
{
    virStorageVolPtr rv = NULL;
    struct private_data *priv = pool->conn->privateData;
    remote_storage_vol_lookup_by_name_args args;
    remote_storage_vol_lookup_by_name_ret ret;

    remoteDriverLock(priv);

    make_nonnull_storage_pool(&args.pool, pool);
    args.name = (char *)name;

    memset(&ret, 0, sizeof(ret));

    if (call(pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME,
             (xdrproc_t)xdr_remote_storage_vol_lookup_by_name_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_lookup_by_name_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_vol(pool->conn, ret.vol);
    xdr_free((xdrproc_t)xdr_remote_storage_vol_lookup_by_name_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virStorageVolPtr
remoteStorageVolLookupByPath(virConnectPtr conn, const char *path)
{
    virStorageVolPtr rv = NULL;
    struct private_data *priv = conn->privateData;
    remote_storage_vol_lookup_by_path_args args;
    remote_storage_vol_lookup_by_path_ret ret;

    remoteDriverLock(priv);

    args.path = (char *)path;

    memset(&ret, 0, sizeof(ret));

    if (call(conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH,
             (xdrproc_t)xdr_remote_storage_vol_lookup_by_path_args, (char *)&args,
             (xdrproc_t)xdr_remote_storage_vol_lookup_by_path_ret, (char *)&ret) == -1) {
        goto done;
    }

    rv = get_nonnull_storage_vol(conn, ret.vol);
    xdr_free((xdrproc_t)xdr_remote_storage_vol_lookup_by_path_ret, (char *)&ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStorageVolResize(virStorageVolPtr vol, unsigned long long capacity, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_resize_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);
    args.capacity = capacity;
    args.flags = flags;

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_RESIZE,
             (xdrproc_t)xdr_remote_storage_vol_resize_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStorageVolUpload(virStorageVolPtr vol, virStreamPtr st, unsigned long long offset, unsigned long long length, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_upload_args args;
    virNetClientStreamPtr netst = NULL;

    remoteDriverLock(priv);

    if (!(netst = virNetClientStreamNew(priv->remoteProgram, REMOTE_PROC_STORAGE_VOL_UPLOAD, priv->counter)))
        goto done;

    if (virNetClientAddStream(priv->client, netst) < 0) {
        virObjectUnref(netst);
        goto done;
    }
    st->driver = &remoteStreamDrv;
    st->privateData = netst;

    make_nonnull_storage_vol(&args.vol, vol);
    args.offset = offset;
    args.length = length;
    args.flags = flags;

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_UPLOAD,
             (xdrproc_t)xdr_remote_storage_vol_upload_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        virNetClientRemoveStream(priv->client, netst);
        virObjectUnref(netst);
        st->driver = NULL;
        st->privateData = NULL;
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStorageVolWipe(virStorageVolPtr vol, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_wipe_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);
    args.flags = flags;

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_WIPE,
             (xdrproc_t)xdr_remote_storage_vol_wipe_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStorageVolWipePattern(virStorageVolPtr vol, unsigned int algorithm, unsigned int flags)
{
    int rv = -1;
    struct private_data *priv = vol->conn->privateData;
    remote_storage_vol_wipe_pattern_args args;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);
    args.algorithm = algorithm;
    args.flags = flags;

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN,
             (xdrproc_t)xdr_remote_storage_vol_wipe_pattern_args, (char *)&args,
             (xdrproc_t)xdr_void, (char *)NULL) == -1) {
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}
