remote.c 221.0 KB
Newer Older
1
/*
2
 * remote.c: handlers for RPC method calls
3
 *
4
 * Copyright (C) 2007-2010 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Richard W.M. Jones <rjones@redhat.com>
 */

#include <config.h>

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <pwd.h>
#include <stdio.h>
#include <stdarg.h>
#include <syslog.h>
#include <string.h>
#include <errno.h>
43
#include <fnmatch.h>
44
#include <arpa/inet.h>
45
#include "virterror_internal.h"
46

47
#if HAVE_POLKIT0
48 49
# include <polkit/polkit.h>
# include <polkit-dbus/polkit-dbus.h>
50 51
#endif

52 53 54
#include "remote.h"
#include "dispatch.h"

55 56
#include "libvirt_internal.h"
#include "datatypes.h"
57
#include "memory.h"
58
#include "util.h"
C
Chris Lalancette 已提交
59
#include "stream.h"
C
Chris Lalancette 已提交
60
#include "libvirt/libvirt-qemu.h"
61

62
#define VIR_FROM_THIS VIR_FROM_REMOTE
63
#define REMOTE_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
64

65 66
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
67
static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface);
68 69
static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool);
static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol);
70
static virSecretPtr get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret);
71
static virNWFilterPtr get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter);
72
static virDomainSnapshotPtr get_nonnull_domain_snapshot (virDomainPtr domain, remote_nonnull_domain_snapshot snapshot);
73 74
static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
D
Daniel Veillard 已提交
75
static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
76 77
static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src);
static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
78
static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src);
79
static void make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
80
static void make_nonnull_nwfilter (remote_nonnull_nwfilter *net_dst, virNWFilterPtr nwfilter_src);
C
Chris Lalancette 已提交
81
static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
82

83

84
#include "remote_dispatch_prototypes.h"
C
Chris Lalancette 已提交
85
#include "qemu_dispatch_prototypes.h"
86 87 88 89

static const dispatch_data const dispatch_table[] = {
#include "remote_dispatch_table.h"
};
90

C
Chris Lalancette 已提交
91 92 93 94
static const dispatch_data const qemu_dispatch_table[] = {
#include "qemu_dispatch_table.h"
};

95 96 97 98 99 100 101 102 103 104
const dispatch_data const *remoteGetDispatchData(int proc)
{
    if (proc >= ARRAY_CARDINALITY(dispatch_table) ||
        dispatch_table[proc].fn == NULL) {
        return NULL;
    }

    return &(dispatch_table[proc]);
}

C
Chris Lalancette 已提交
105 106 107 108 109 110 111 112 113 114
const dispatch_data const *qemuGetDispatchData(int proc)
{
    if (proc >= ARRAY_CARDINALITY(qemu_dispatch_table) ||
        qemu_dispatch_table[proc].fn == NULL) {
        return NULL;
    }

    return &(qemu_dispatch_table[proc]);
}

115 116 117
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
118 119 120
                               int procnr,
                               xdrproc_t proc,
                               void *data);
121

122 123 124 125 126
static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           int event,
                                           int detail,
                                           void *opaque)
127 128
{
    struct qemud_client *client = opaque;
129
    remote_domain_event_lifecycle_msg data;
130

131 132 133 134
    if (!client)
        return -1;

    REMOTE_DEBUG("Relaying domain lifecycle event %d %d", event, detail);
135

136
    virMutexLock(&client->lock);
137

138 139 140 141 142
    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);
    data.event = event;
    data.detail = detail;
143

144
    remoteDispatchDomainEventSend (client,
145 146
                                   REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
                                   (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, &data);
147 148

    virMutexUnlock(&client->lock);
149

150 151
    return 0;
}
152

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED,
                                        virDomainPtr dom,
                                        void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_reboot_msg data;

    if (!client)
        return -1;

    REMOTE_DEBUG("Relaying domain reboot event %s %d", dom->name, dom->id);

    virMutexLock(&client->lock);

    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);

    remoteDispatchDomainEventSend (client,
                                   REMOTE_PROC_DOMAIN_EVENT_REBOOT,
                                   (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data);

    virMutexUnlock(&client->lock);

    return 0;
}

180

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           long long offset,
                                           void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_rtc_change_msg data;

    if (!client)
        return -1;

    REMOTE_DEBUG("Relaying domain rtc change event %s %d %lld", dom->name, dom->id, offset);

    virMutexLock(&client->lock);

    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);
    data.offset = offset;

    remoteDispatchDomainEventSend (client,
                                   REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
                                   (xdrproc_t)xdr_remote_domain_event_rtc_change_msg, &data);

    virMutexUnlock(&client->lock);

    return 0;
}


211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          int action,
                                          void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_watchdog_msg data;

    if (!client)
        return -1;

    REMOTE_DEBUG("Relaying domain watchdog event %s %d %d", dom->name, dom->id, action);

    virMutexLock(&client->lock);

    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);
    data.action = action;

    remoteDispatchDomainEventSend (client,
                                   REMOTE_PROC_DOMAIN_EVENT_WATCHDOG,
                                   (xdrproc_t)xdr_remote_domain_event_watchdog_msg, &data);

    virMutexUnlock(&client->lock);

    return 0;
}


241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         const char *srcPath,
                                         const char *devAlias,
                                         int action,
                                         void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_io_error_msg data;

    if (!client)
        return -1;

    REMOTE_DEBUG("Relaying domain io error %s %d %s %s %d", dom->name, dom->id, srcPath, devAlias, action);

    virMutexLock(&client->lock);

    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);
    data.srcPath = (char*)srcPath;
    data.devAlias = (char*)devAlias;
    data.action = action;

    remoteDispatchDomainEventSend (client,
                                   REMOTE_PROC_DOMAIN_EVENT_IO_ERROR,
                                   (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data);

    virMutexUnlock(&client->lock);

    return 0;
}


275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED,
                                               virDomainPtr dom,
                                               const char *srcPath,
                                               const char *devAlias,
                                               int action,
                                               const char *reason,
                                               void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_io_error_reason_msg data;

    if (!client)
        return -1;

    REMOTE_DEBUG("Relaying domain io error %s %d %s %s %d %s",
                 dom->name, dom->id, srcPath, devAlias, action, reason);

    virMutexLock(&client->lock);

    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);
    data.srcPath = (char*)srcPath;
    data.devAlias = (char*)devAlias;
    data.action = action;
    data.reason = (char*)reason;

    remoteDispatchDomainEventSend (client,
                                   REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON,
                                   (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data);

    virMutexUnlock(&client->lock);

    return 0;
}


312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          int phase,
                                          virDomainEventGraphicsAddressPtr local,
                                          virDomainEventGraphicsAddressPtr remote,
                                          const char *authScheme,
                                          virDomainEventGraphicsSubjectPtr subject,
                                          void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_graphics_msg data;
    int i;

    if (!client)
        return -1;

    REMOTE_DEBUG("Relaying domain graphics event %s %d %d - %d %s %s  - %d %s %s - %s", dom->name, dom->id, phase,
                 local->family, local->service, local->node,
                 remote->family, remote->service, remote->node,
                 authScheme);

    REMOTE_DEBUG("Subject %d", subject->nidentity);
    for (i = 0 ; i < subject->nidentity ; i++) {
        REMOTE_DEBUG("  %s=%s", subject->identities[i].type, subject->identities[i].name);
    }

    virMutexLock(&client->lock);

    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);
    data.phase = phase;
    data.authScheme = (char*)authScheme;

    data.local.family = local->family;
    data.local.node = (char *)local->node;
    data.local.service = (char *)local->service;

    data.remote.family = remote->family;
    data.remote.node = (char*)remote->node;
    data.remote.service = (char*)remote->service;

    data.subject.subject_len = subject->nidentity;
    if (VIR_ALLOC_N(data.subject.subject_val, data.subject.subject_len) < 0) {
        VIR_WARN0("cannot allocate memory for graphics event subject");
        return -1;
    }
    for (i = 0 ; i < data.subject.subject_len ; i++) {
        data.subject.subject_val[i].type = (char*)subject->identities[i].type;
        data.subject.subject_val[i].name = (char*)subject->identities[i].name;
    }

    remoteDispatchDomainEventSend (client,
                                   REMOTE_PROC_DOMAIN_EVENT_GRAPHICS,
                                   (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data);

    VIR_FREE(data.subject.subject_val);

    virMutexUnlock(&client->lock);

    return 0;
}


376
static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
377
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
378
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
379
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventRTCChange),
380
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog),
381
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
382
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
383
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOErrorReason),
384 385 386 387
};

verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);

388 389 390
/*----- Functions. -----*/

static int
391
remoteDispatchOpen (struct qemud_server *server,
392
                    struct qemud_client *client,
393
                    virConnectPtr conn,
394
                    remote_message_header *hdr ATTRIBUTE_UNUSED,
395
                    remote_error *rerr,
396 397 398
                    struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED)
{
    const char *name;
399
    int flags, rc;
400 401

    /* Already opened? */
402
    if (conn) {
403 404
        remoteDispatchFormatError (rerr, "%s", _("connection already open"));
        return -1;
405 406
    }

407 408 409
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
410

411 412 413 414 415 416 417 418 419 420 421 422 423
    name = args->name ? *args->name : NULL;

    /* If this connection arrived on a readonly socket, force
     * the connection to be readonly.
     */
    flags = args->flags;
    if (client->readonly) flags |= VIR_CONNECT_RO;

    client->conn =
        flags & VIR_CONNECT_RO
        ? virConnectOpenReadOnly (name)
        : virConnectOpen (name);

424
    if (client->conn == NULL)
425 426
        remoteDispatchConnError(rerr, NULL);

427
    rc = client->conn ? 0 : -1;
428
    virMutexUnlock(&client->lock);
429
    return rc;
430 431
}

432 433 434 435
#define CHECK_CONN(client)                                              \
    if (!client->conn) {                                                \
        remoteDispatchFormatError (rerr, "%s", _("connection not open")); \
        return -1;                                                      \
436 437 438
    }

static int
439
remoteDispatchClose (struct qemud_server *server ATTRIBUTE_UNUSED,
440 441
                     struct qemud_client *client ATTRIBUTE_UNUSED,
                     virConnectPtr conn ATTRIBUTE_UNUSED,
442
                     remote_message_header *hdr ATTRIBUTE_UNUSED,
443
                     remote_error *rerr ATTRIBUTE_UNUSED,
444 445
                     void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
{
446 447 448
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
449

450
    client->closing = 1;
451

452
    virMutexUnlock(&client->lock);
453
    return 0;
454 455
}

456
static int
457
remoteDispatchSupportsFeature (struct qemud_server *server ATTRIBUTE_UNUSED,
458 459
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
460
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
461
                               remote_error *rerr,
462 463
                               remote_supports_feature_args *args, remote_supports_feature_ret *ret)
{
464
    ret->supported = virDrvSupportsFeature (conn, args->feature);
465 466

    if (ret->supported == -1) {
467
        remoteDispatchConnError(rerr, conn);
468 469
        return -1;
    }
470 471 472 473

    return 0;
}

474
static int
475
remoteDispatchGetType (struct qemud_server *server ATTRIBUTE_UNUSED,
476 477
                       struct qemud_client *client ATTRIBUTE_UNUSED,
                       virConnectPtr conn,
478
                       remote_message_header *hdr ATTRIBUTE_UNUSED,
479
                       remote_error *rerr,
480 481 482 483
                       void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret)
{
    const char *type;

484
    type = virConnectGetType (conn);
485
    if (type == NULL) {
486
        remoteDispatchConnError(rerr, conn);
487 488
        return -1;
    }
489 490 491 492 493 494

    /* We have to strdup because remoteDispatchClientRequest will
     * free this string after it's been serialised.
     */
    ret->type = strdup (type);
    if (!ret->type) {
495
        remoteDispatchOOMError(rerr);
496
        return -1;
497 498 499 500 501 502
    }

    return 0;
}

static int
503
remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
504 505
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
506
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
507
                          remote_error *rerr,
508 509 510 511 512
                          void *args ATTRIBUTE_UNUSED,
                          remote_get_version_ret *ret)
{
    unsigned long hvVer;

513 514
    if (virConnectGetVersion (conn, &hvVer) == -1) {
        remoteDispatchConnError(rerr, conn);
515
        return -1;
516
    }
517 518 519 520 521

    ret->hv_ver = hvVer;
    return 0;
}

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
static int
remoteDispatchGetLibVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *rerr,
                             void *args ATTRIBUTE_UNUSED,
                             remote_get_lib_version_ret *ret)
{
    unsigned long libVer;

    if (virConnectGetLibVersion (conn, &libVer) == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    ret->lib_ver = libVer;
    return 0;
}

542
static int
543
remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED,
544 545
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
546
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
547
                           remote_error *rerr,
548 549 550 551 552
                           void *args ATTRIBUTE_UNUSED,
                           remote_get_hostname_ret *ret)
{
    char *hostname;

553
    hostname = virConnectGetHostname (conn);
554
    if (hostname == NULL) {
555
        remoteDispatchConnError(rerr, conn);
556 557
        return -1;
    }
558 559 560 561 562

    ret->hostname = hostname;
    return 0;
}

563 564
static int
remoteDispatchGetUri (struct qemud_server *server ATTRIBUTE_UNUSED,
565 566
                      struct qemud_client *client ATTRIBUTE_UNUSED,
                      virConnectPtr conn,
567
                      remote_message_header *hdr ATTRIBUTE_UNUSED,
568
                      remote_error *rerr,
569 570 571 572 573 574
                      void *args ATTRIBUTE_UNUSED,
                      remote_get_uri_ret *ret)
{
    char *uri;
    CHECK_CONN(client);

575
    uri = virConnectGetURI (conn);
576
    if (uri == NULL) {
577
        remoteDispatchConnError(rerr, conn);
578 579
        return -1;
    }
580 581 582 583 584

    ret->uri = uri;
    return 0;
}

585
static int
586
remoteDispatchGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
587 588
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
589
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
590
                           remote_error *rerr,
591 592 593 594 595 596
                           remote_get_max_vcpus_args *args,
                           remote_get_max_vcpus_ret *ret)
{
    char *type;

    type = args->type ? *args->type : NULL;
597
    ret->max_vcpus = virConnectGetMaxVcpus (conn, type);
598
    if (ret->max_vcpus == -1) {
599
        remoteDispatchConnError(rerr, conn);
600 601
        return -1;
    }
602 603 604 605 606

    return 0;
}

static int
607
remoteDispatchNodeGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
608 609
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
610
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
611
                           remote_error *rerr,
612 613 614 615 616
                           void *args ATTRIBUTE_UNUSED,
                           remote_node_get_info_ret *ret)
{
    virNodeInfo info;

617 618
    if (virNodeGetInfo (conn, &info) == -1) {
        remoteDispatchConnError(rerr, conn);
619
        return -1;
620
    }
621 622 623 624 625 626 627 628 629 630 631 632 633 634

    memcpy (ret->model, info.model, sizeof ret->model);
    ret->memory = info.memory;
    ret->cpus = info.cpus;
    ret->mhz = info.mhz;
    ret->nodes = info.nodes;
    ret->sockets = info.sockets;
    ret->cores = info.cores;
    ret->threads = info.threads;

    return 0;
}

static int
635
remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED,
636 637
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
638
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
639
                               remote_error *rerr,
640 641 642 643 644
                               void *args ATTRIBUTE_UNUSED,
                               remote_get_capabilities_ret *ret)
{
    char *caps;

645
    caps = virConnectGetCapabilities (conn);
646
    if (caps == NULL) {
647
        remoteDispatchConnError(rerr, conn);
648 649
        return -1;
    }
650 651 652 653 654

    ret->capabilities = caps;
    return 0;
}

655 656
static int
remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
657 658
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
659
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
660
                                      remote_error *rerr,
661 662 663
                                      remote_node_get_cells_free_memory_args *args,
                                      remote_node_get_cells_free_memory_ret *ret)
{
D
Daniel P. Berrange 已提交
664
    int err;
665 666

    if (args->maxCells > REMOTE_NODE_MAX_CELLS) {
667 668 669
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxCells > REMOTE_NODE_MAX_CELLS"));
        return -1;
670 671 672
    }

    /* Allocate return buffer. */
673
    if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) {
674 675
        remoteDispatchOOMError(rerr);
        return -1;
676
    }
677

D
Daniel P. Berrange 已提交
678 679 680 681 682
    err = virNodeGetCellsFreeMemory(conn,
                                    (unsigned long long *)ret->freeMems.freeMems_val,
                                    args->startCell,
                                    args->maxCells);
    if (err <= 0) {
683
        VIR_FREE(ret->freeMems.freeMems_val);
684
        remoteDispatchConnError(rerr, conn);
685
        return -1;
686
    }
D
Daniel P. Berrange 已提交
687
    ret->freeMems.freeMems_len = err;
688 689 690 691 692 693 694

    return 0;
}


static int
remoteDispatchNodeGetFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
695 696
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
697
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
698
                                 remote_error *rerr,
699 700 701 702 703
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_node_get_free_memory_ret *ret)
{
    unsigned long long freeMem;

704
    freeMem = virNodeGetFreeMemory(conn);
705
    if (freeMem == 0) {
706
        remoteDispatchConnError(rerr, conn);
707 708
        return -1;
    }
709 710 711 712 713
    ret->freeMem = freeMem;
    return 0;
}


714
static int
715
remoteDispatchDomainGetSchedulerType (struct qemud_server *server ATTRIBUTE_UNUSED,
716 717
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
718
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
719
                                      remote_error *rerr,
720 721 722 723 724 725 726
                                      remote_domain_get_scheduler_type_args *args,
                                      remote_domain_get_scheduler_type_ret *ret)
{
    virDomainPtr dom;
    char *type;
    int nparams;

727
    dom = get_nonnull_domain (conn, args->dom);
728
    if (dom == NULL) {
729
        remoteDispatchConnError(rerr, conn);
730
        return -1;
731 732 733
    }

    type = virDomainGetSchedulerType (dom, &nparams);
734 735
    if (type == NULL) {
        virDomainFree(dom);
736
        remoteDispatchConnError(rerr, conn);
737 738
        return -1;
    }
739 740 741

    ret->type = type;
    ret->nparams = nparams;
742
    virDomainFree(dom);
743 744 745 746
    return 0;
}

static int
747
remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
748 749
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
750
                                            remote_message_header *hdr ATTRIBUTE_UNUSED,
751
                                            remote_error *rerr,
752 753 754 755 756 757 758 759 760 761
                                            remote_domain_get_scheduler_parameters_args *args,
                                            remote_domain_get_scheduler_parameters_ret *ret)
{
    virDomainPtr dom;
    virSchedParameterPtr params;
    int i, r, nparams;

    nparams = args->nparams;

    if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) {
762 763
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
764
    }
765
    if (VIR_ALLOC_N(params, nparams) < 0) {
766 767
        remoteDispatchOOMError(rerr);
        return -1;
768 769
    }

770
    dom = get_nonnull_domain (conn, args->dom);
771
    if (dom == NULL) {
772
        VIR_FREE(params);
773
        remoteDispatchConnError(rerr, conn);
774
        return -1;
775 776 777 778
    }

    r = virDomainGetSchedulerParameters (dom, params, &nparams);
    if (r == -1) {
779
        virDomainFree(dom);
780
        VIR_FREE(params);
781
        remoteDispatchConnError(rerr, conn);
782 783 784 785 786
        return -1;
    }

    /* Serialise the scheduler parameters. */
    ret->params.params_len = nparams;
787 788
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;
789 790 791 792

    for (i = 0; i < nparams; ++i) {
        // remoteDispatchClientRequest will free this:
        ret->params.params_val[i].field = strdup (params[i].field);
793 794 795
        if (ret->params.params_val[i].field == NULL)
            goto oom;

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
        ret->params.params_val[i].value.type = params[i].type;
        switch (params[i].type) {
        case VIR_DOMAIN_SCHED_FIELD_INT:
            ret->params.params_val[i].value.remote_sched_param_value_u.i = params[i].value.i; break;
        case VIR_DOMAIN_SCHED_FIELD_UINT:
            ret->params.params_val[i].value.remote_sched_param_value_u.ui = params[i].value.ui; break;
        case VIR_DOMAIN_SCHED_FIELD_LLONG:
            ret->params.params_val[i].value.remote_sched_param_value_u.l = params[i].value.l; break;
        case VIR_DOMAIN_SCHED_FIELD_ULLONG:
            ret->params.params_val[i].value.remote_sched_param_value_u.ul = params[i].value.ul; break;
        case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
            ret->params.params_val[i].value.remote_sched_param_value_u.d = params[i].value.d; break;
        case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
            ret->params.params_val[i].value.remote_sched_param_value_u.b = params[i].value.b; break;
        default:
811
            remoteDispatchFormatError (rerr, "%s", _("unknown type"));
812
            goto cleanup;
813 814
        }
    }
815
    virDomainFree(dom);
816
    VIR_FREE(params);
817 818

    return 0;
819 820

oom:
821
    remoteDispatchOOMError(rerr);
822 823 824 825 826
cleanup:
    virDomainFree(dom);
    for (i = 0 ; i < nparams ; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
827
    return -1;
828 829 830
}

static int
831
remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
832 833
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
834
                                            remote_message_header *hdr ATTRIBUTE_UNUSED,
835
                                            remote_error *rerr,
836 837 838 839 840 841 842 843 844 845
                                            remote_domain_set_scheduler_parameters_args *args,
                                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int i, r, nparams;
    virSchedParameterPtr params;

    nparams = args->params.params_len;

    if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) {
846 847
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
848
    }
849
    if (VIR_ALLOC_N(params, nparams) < 0) {
850 851
        remoteDispatchOOMError(rerr);
        return -1;
852 853 854 855
    }

    /* Deserialise parameters. */
    for (i = 0; i < nparams; ++i) {
C
Chris Lalancette 已提交
856 857 858 859 860
        if (virStrcpyStatic(params[i].field, args->params.params_val[i].field) == NULL) {
            remoteDispatchFormatError(rerr, _("Field %s too big for destination"),
                                      args->params.params_val[i].field);
            return -1;
        }
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
        params[i].type = args->params.params_val[i].value.type;
        switch (params[i].type) {
        case VIR_DOMAIN_SCHED_FIELD_INT:
            params[i].value.i = args->params.params_val[i].value.remote_sched_param_value_u.i; break;
        case VIR_DOMAIN_SCHED_FIELD_UINT:
            params[i].value.ui = args->params.params_val[i].value.remote_sched_param_value_u.ui; break;
        case VIR_DOMAIN_SCHED_FIELD_LLONG:
            params[i].value.l = args->params.params_val[i].value.remote_sched_param_value_u.l; break;
        case VIR_DOMAIN_SCHED_FIELD_ULLONG:
            params[i].value.ul = args->params.params_val[i].value.remote_sched_param_value_u.ul; break;
        case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
            params[i].value.d = args->params.params_val[i].value.remote_sched_param_value_u.d; break;
        case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
            params[i].value.b = args->params.params_val[i].value.remote_sched_param_value_u.b; break;
        }
    }

878
    dom = get_nonnull_domain (conn, args->dom);
879
    if (dom == NULL) {
880
        VIR_FREE(params);
881
        remoteDispatchConnError(rerr, conn);
882
        return -1;
883 884 885
    }

    r = virDomainSetSchedulerParameters (dom, params, nparams);
886
    virDomainFree(dom);
887
    VIR_FREE(params);
888
    if (r == -1) {
889
        remoteDispatchConnError(rerr, conn);
890 891
        return -1;
    }
892 893 894 895

    return 0;
}

896
static int
897
remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED,
898 899
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
900
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
901
                                remote_error *rerr,
902 903 904 905 906 907 908
                                remote_domain_block_stats_args *args,
                                remote_domain_block_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainBlockStats stats;

909
    dom = get_nonnull_domain (conn, args->dom);
910
    if (dom == NULL) {
911
        remoteDispatchConnError(rerr, conn);
912
        return -1;
913 914 915
    }
    path = args->path;

D
Daniel P. Berrange 已提交
916 917
    if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
918
        remoteDispatchConnError(rerr, conn);
919
        return -1;
D
Daniel P. Berrange 已提交
920 921
    }
    virDomainFree (dom);
922 923 924 925 926 927 928 929 930 931 932

    ret->rd_req = stats.rd_req;
    ret->rd_bytes = stats.rd_bytes;
    ret->wr_req = stats.wr_req;
    ret->wr_bytes = stats.wr_bytes;
    ret->errs = stats.errs;

    return 0;
}

static int
933
remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED,
934 935
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
936
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
937
                                    remote_error *rerr,
938 939 940 941 942 943 944
                                    remote_domain_interface_stats_args *args,
                                    remote_domain_interface_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainInterfaceStats stats;

945
    dom = get_nonnull_domain (conn, args->dom);
946
    if (dom == NULL) {
947
        remoteDispatchConnError(rerr, conn);
948
        return -1;
949 950 951
    }
    path = args->path;

D
Daniel P. Berrange 已提交
952 953
    if (virDomainInterfaceStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
954
        remoteDispatchConnError(rerr, conn);
955
        return -1;
D
Daniel P. Berrange 已提交
956 957
    }
    virDomainFree (dom);
958 959 960 961 962 963 964 965 966 967 968 969 970

    ret->rx_bytes = stats.rx_bytes;
    ret->rx_packets = stats.rx_packets;
    ret->rx_errs = stats.rx_errs;
    ret->rx_drop = stats.rx_drop;
    ret->tx_bytes = stats.tx_bytes;
    ret->tx_packets = stats.tx_packets;
    ret->tx_errs = stats.tx_errs;
    ret->tx_drop = stats.tx_drop;

    return 0;
}

971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
static int
remoteDispatchDomainMemoryStats (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_domain_memory_stats_args *args,
                                 remote_domain_memory_stats_ret *ret)
{
    virDomainPtr dom;
    struct _virDomainMemoryStat *stats;
    unsigned int nr_stats, i;

    if (args->maxStats > REMOTE_DOMAIN_MEMORY_STATS_MAX) {
        remoteDispatchFormatError (rerr, "%s",
                               _("maxStats > REMOTE_DOMAIN_MEMORY_STATS_MAX"));
        return -1;
    }

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* Allocate stats array for making dispatch call */
    if (VIR_ALLOC_N(stats, args->maxStats) < 0) {
998
        virDomainFree (dom);
999 1000
        remoteDispatchOOMError(rerr);
        return -1;
1001
    }
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027

    nr_stats = virDomainMemoryStats (dom, stats, args->maxStats, 0);
    virDomainFree (dom);
    if (nr_stats == -1) {
        VIR_FREE(stats);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* Allocate return buffer */
    if (VIR_ALLOC_N(ret->stats.stats_val, args->maxStats) < 0) {
        VIR_FREE(stats);
        remoteDispatchOOMError(rerr);
        return -1;
    }

    /* Copy the stats into the xdr return structure */
    for (i = 0; i < nr_stats; i++) {
        ret->stats.stats_val[i].tag = stats[i].tag;
        ret->stats.stats_val[i].val = stats[i].val;
    }
    ret->stats.stats_len = nr_stats;
    VIR_FREE(stats);
    return 0;
}

1028 1029
static int
remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
1030 1031
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1032
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1033
                               remote_error *rerr,
1034 1035 1036 1037 1038 1039 1040 1041 1042
                               remote_domain_block_peek_args *args,
                               remote_domain_block_peek_ret *ret)
{
    virDomainPtr dom;
    char *path;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

1043
    dom = get_nonnull_domain (conn, args->dom);
1044
    if (dom == NULL) {
1045
        remoteDispatchConnError(rerr, conn);
1046
        return -1;
1047 1048 1049 1050 1051 1052 1053
    }
    path = args->path;
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
1054
        virDomainFree (dom);
1055 1056 1057
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
1058 1059 1060
    }

    ret->buffer.buffer_len = size;
1061
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
1062
        virDomainFree (dom);
1063
        remoteDispatchOOMError(rerr);
1064
        return -1;
1065 1066 1067 1068 1069 1070
    }

    if (virDomainBlockPeek (dom, path, offset, size,
                            ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
1071
        remoteDispatchConnError(rerr, conn);
1072 1073 1074 1075 1076 1077 1078
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

R
Richard W.M. Jones 已提交
1079 1080
static int
remoteDispatchDomainMemoryPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
1081 1082
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
1083
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
1084
                                remote_error *rerr,
R
Richard W.M. Jones 已提交
1085 1086 1087 1088 1089 1090 1091 1092
                                remote_domain_memory_peek_args *args,
                                remote_domain_memory_peek_ret *ret)
{
    virDomainPtr dom;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

1093
    dom = get_nonnull_domain (conn, args->dom);
R
Richard W.M. Jones 已提交
1094
    if (dom == NULL) {
1095
        remoteDispatchConnError(rerr, conn);
1096
        return -1;
R
Richard W.M. Jones 已提交
1097 1098 1099 1100 1101 1102
    }
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
1103
        virDomainFree (dom);
1104 1105 1106
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
R
Richard W.M. Jones 已提交
1107 1108 1109 1110 1111
    }

    ret->buffer.buffer_len = size;
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
        virDomainFree (dom);
1112
        remoteDispatchOOMError(rerr);
1113
        return -1;
R
Richard W.M. Jones 已提交
1114 1115 1116 1117 1118 1119
    }

    if (virDomainMemoryPeek (dom, offset, size,
                             ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
1120
        remoteDispatchConnError(rerr, conn);
R
Richard W.M. Jones 已提交
1121 1122 1123 1124 1125 1126 1127
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

1128
static int
1129
remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1130 1131
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1132
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1133
                                  remote_error *rerr,
1134 1135 1136 1137 1138
                                  remote_domain_attach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1139
    dom = get_nonnull_domain (conn, args->dom);
1140
    if (dom == NULL) {
1141
        remoteDispatchConnError(rerr, conn);
1142
        return -1;
1143 1144
    }

1145 1146
    if (virDomainAttachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
1147
        remoteDispatchConnError(rerr, conn);
1148
        return -1;
1149 1150
    }
    virDomainFree(dom);
1151 1152 1153
    return 0;
}

J
Jim Fehlig 已提交
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
static int
remoteDispatchDomainAttachDeviceFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_attach_device_flags_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainAttachDeviceFlags (dom, args->xml, args->flags) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
static int
remoteDispatchDomainUpdateDeviceFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_update_device_flags_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainUpdateDeviceFlags (dom, args->xml, args->flags) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

1206
static int
1207
remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
1208 1209
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1210
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
1211
                            remote_error *rerr,
1212 1213 1214 1215 1216
                            remote_domain_create_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1217
    dom = get_nonnull_domain (conn, args->dom);
1218
    if (dom == NULL) {
1219
        remoteDispatchConnError(rerr, conn);
1220
        return -1;
1221 1222
    }

1223 1224
    if (virDomainCreate (dom) == -1) {
        virDomainFree(dom);
1225
        remoteDispatchConnError(rerr, conn);
1226
        return -1;
1227 1228
    }
    virDomainFree(dom);
1229 1230 1231
    return 0;
}

1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
static int
remoteDispatchDomainCreateWithFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
                                     remote_error *rerr,
                                     remote_domain_create_with_flags_args *args,
                                     remote_domain_create_with_flags_ret *ret)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainCreateWithFlags (dom, args->flags) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_domain (&ret->dom, dom);
    virDomainFree(dom);
    return 0;
}

1260
static int
1261
remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1262 1263
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1264
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1265 1266 1267
                               remote_error *rerr,
                               remote_domain_create_xml_args *args,
                               remote_domain_create_xml_ret *ret)
1268 1269 1270
{
    virDomainPtr dom;

1271
    dom = virDomainCreateXML (conn, args->xml_desc, args->flags);
1272
    if (dom == NULL) {
1273
        remoteDispatchConnError(rerr, conn);
1274 1275
        return -1;
    }
1276 1277

    make_nonnull_domain (&ret->dom, dom);
1278
    virDomainFree(dom);
1279 1280 1281 1282 1283

    return 0;
}

static int
1284
remoteDispatchDomainDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1285 1286
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1287
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1288
                               remote_error *rerr,
1289 1290 1291 1292 1293
                               remote_domain_define_xml_args *args,
                               remote_domain_define_xml_ret *ret)
{
    virDomainPtr dom;

1294
    dom = virDomainDefineXML (conn, args->xml);
1295
    if (dom == NULL) {
1296
        remoteDispatchConnError(rerr, conn);
1297 1298
        return -1;
    }
1299 1300

    make_nonnull_domain (&ret->dom, dom);
1301
    virDomainFree(dom);
1302 1303 1304 1305 1306

    return 0;
}

static int
1307
remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
1308 1309
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1310
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1311
                             remote_error *rerr,
1312 1313 1314 1315 1316
                             remote_domain_destroy_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1317
    dom = get_nonnull_domain (conn, args->dom);
1318
    if (dom == NULL) {
1319
        remoteDispatchConnError(rerr, conn);
1320
        return -1;
1321 1322
    }

1323 1324
    if (virDomainDestroy (dom) == -1) {
        virDomainFree(dom);
1325
        remoteDispatchConnError(rerr, conn);
1326
        return -1;
1327 1328
    }
    virDomainFree(dom);
1329 1330 1331 1332
    return 0;
}

static int
1333
remoteDispatchDomainDetachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1334 1335
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1336
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1337
                                  remote_error *rerr,
1338 1339 1340 1341 1342
                                  remote_domain_detach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1343
    dom = get_nonnull_domain (conn, args->dom);
1344
    if (dom == NULL) {
1345
        remoteDispatchConnError(rerr, conn);
1346
        return -1;
1347 1348
    }

1349 1350
    if (virDomainDetachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
J
Jim Fehlig 已提交
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    virDomainFree(dom);
    return 0;
}

static int
remoteDispatchDomainDetachDeviceFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_detach_device_flags_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainDetachDeviceFlags (dom, args->xml, args->flags) == -1) {
        virDomainFree(dom);
1378
        remoteDispatchConnError(rerr, conn);
1379
        return -1;
1380
    }
1381

1382
    virDomainFree(dom);
1383 1384 1385 1386
    return 0;
}

static int
1387
remoteDispatchDomainDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1388 1389
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1390
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1391
                             remote_error *rerr,
1392 1393 1394 1395 1396
                             remote_domain_dump_xml_args *args,
                             remote_domain_dump_xml_ret *ret)
{
    virDomainPtr dom;

1397
    dom = get_nonnull_domain (conn, args->dom);
1398
    if (dom == NULL) {
1399
        remoteDispatchConnError(rerr, conn);
1400
        return -1;
1401 1402 1403 1404
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virDomainGetXMLDesc (dom, args->flags);
1405
    if (!ret->xml) {
1406
        virDomainFree(dom);
1407
        remoteDispatchConnError(rerr, conn);
1408
        return -1;
1409 1410
    }
    virDomainFree(dom);
1411 1412 1413
    return 0;
}

1414 1415 1416 1417
static int
remoteDispatchDomainXmlFromNative (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1418
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438
                                   remote_error *rerr,
                                   remote_domain_xml_from_native_args *args,
                                   remote_domain_xml_from_native_ret *ret)
{
    /* remoteDispatchClientRequest will free this. */
    ret->domainXml = virConnectDomainXMLFromNative (conn,
                                                    args->nativeFormat,
                                                    args->nativeConfig,
                                                    args->flags);
    if (!ret->domainXml) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}

static int
remoteDispatchDomainXmlToNative (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1439
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456
                                 remote_error *rerr,
                                 remote_domain_xml_to_native_args *args,
                                 remote_domain_xml_to_native_ret *ret)
{
    /* remoteDispatchClientRequest will free this. */
    ret->nativeConfig = virConnectDomainXMLToNative (conn,
                                                     args->nativeFormat,
                                                     args->domainXml,
                                                     args->flags);
    if (!ret->nativeConfig) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}


1457
static int
1458
remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1459 1460
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1461
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1462
                                  remote_error *rerr,
1463 1464 1465 1466 1467
                                  remote_domain_get_autostart_args *args,
                                  remote_domain_get_autostart_ret *ret)
{
    virDomainPtr dom;

1468
    dom = get_nonnull_domain (conn, args->dom);
1469
    if (dom == NULL) {
1470
        remoteDispatchConnError(rerr, conn);
1471
        return -1;
1472 1473
    }

1474 1475
    if (virDomainGetAutostart (dom, &ret->autostart) == -1) {
        virDomainFree(dom);
1476
        remoteDispatchConnError(rerr, conn);
1477
        return -1;
1478 1479
    }
    virDomainFree(dom);
1480 1481 1482 1483
    return 0;
}

static int
1484
remoteDispatchDomainGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
1485 1486
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1487
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1488
                             remote_error *rerr,
1489 1490 1491 1492 1493 1494
                             remote_domain_get_info_args *args,
                             remote_domain_get_info_ret *ret)
{
    virDomainPtr dom;
    virDomainInfo info;

1495
    dom = get_nonnull_domain (conn, args->dom);
1496
    if (dom == NULL) {
1497
        remoteDispatchConnError(rerr, conn);
1498
        return -1;
1499 1500
    }

1501 1502
    if (virDomainGetInfo (dom, &info) == -1) {
        virDomainFree(dom);
1503
        remoteDispatchConnError(rerr, conn);
1504
        return -1;
1505
    }
1506 1507 1508 1509 1510 1511 1512

    ret->state = info.state;
    ret->max_mem = info.maxMem;
    ret->memory = info.memory;
    ret->nr_virt_cpu = info.nrVirtCpu;
    ret->cpu_time = info.cpuTime;

1513 1514
    virDomainFree(dom);

1515 1516 1517 1518
    return 0;
}

static int
1519
remoteDispatchDomainGetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1520 1521
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1522
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1523
                                  remote_error *rerr,
1524 1525 1526 1527 1528
                                  remote_domain_get_max_memory_args *args,
                                  remote_domain_get_max_memory_ret *ret)
{
    virDomainPtr dom;

1529
    dom = get_nonnull_domain (conn, args->dom);
1530
    if (dom == NULL) {
1531
        remoteDispatchConnError(rerr, conn);
1532
        return -1;
1533 1534 1535
    }

    ret->memory = virDomainGetMaxMemory (dom);
1536 1537
    if (ret->memory == 0) {
        virDomainFree(dom);
1538
        remoteDispatchConnError(rerr, conn);
1539 1540 1541
        return -1;
    }
    virDomainFree(dom);
1542 1543 1544 1545
    return 0;
}

static int
1546
remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1547 1548
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1549
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
1550
                                 remote_error *rerr,
1551 1552 1553 1554 1555
                                 remote_domain_get_max_vcpus_args *args,
                                 remote_domain_get_max_vcpus_ret *ret)
{
    virDomainPtr dom;

1556
    dom = get_nonnull_domain (conn, args->dom);
1557
    if (dom == NULL) {
1558
        remoteDispatchConnError(rerr, conn);
1559
        return -1;
1560 1561 1562
    }

    ret->num = virDomainGetMaxVcpus (dom);
1563 1564
    if (ret->num == -1) {
        virDomainFree(dom);
1565
        remoteDispatchConnError(rerr, conn);
1566 1567 1568
        return -1;
    }
    virDomainFree(dom);
1569 1570 1571
    return 0;
}

1572 1573 1574 1575
static int
remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1576
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
                                     remote_error *rerr,
                                     remote_domain_get_security_label_args *args,
                                     remote_domain_get_security_label_ret *ret)
{
    virDomainPtr dom;
    virSecurityLabel seclabel;

    dom = get_nonnull_domain(conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    memset(&seclabel, 0, sizeof seclabel);
    if (virDomainGetSecurityLabel(dom, &seclabel) == -1) {
        virDomainFree(dom);
1593
        remoteDispatchConnError(rerr, conn);
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
        return -1;
    }

    ret->label.label_len = strlen(seclabel.label) + 1;
    if (VIR_ALLOC_N(ret->label.label_val, ret->label.label_len) < 0) {
        virDomainFree(dom);
        remoteDispatchOOMError(rerr);
        return -1;
    }
    strcpy(ret->label.label_val, seclabel.label);
    ret->enforcing = seclabel.enforcing;
    virDomainFree(dom);

    return 0;
}

static int
remoteDispatchNodeGetSecurityModel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1614
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1615 1616 1617 1618 1619 1620 1621 1622
                                   remote_error *rerr,
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_node_get_security_model_ret *ret)
{
    virSecurityModel secmodel;

    memset(&secmodel, 0, sizeof secmodel);
    if (virNodeGetSecurityModel(conn, &secmodel) == -1) {
1623
        remoteDispatchConnError(rerr, conn);
1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
        return -1;
    }

    ret->model.model_len = strlen(secmodel.model) + 1;
    if (VIR_ALLOC_N(ret->model.model_val, ret->model.model_len) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }
    strcpy(ret->model.model_val, secmodel.model);

    ret->doi.doi_len = strlen(secmodel.doi) + 1;
    if (VIR_ALLOC_N(ret->doi.doi_val, ret->doi.doi_len) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }
    strcpy(ret->doi.doi_val, secmodel.doi);

    return 0;
}

1644
static int
1645
remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED,
1646 1647
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1648
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1649
                               remote_error *rerr,
1650 1651 1652 1653 1654
                               remote_domain_get_os_type_args *args,
                               remote_domain_get_os_type_ret *ret)
{
    virDomainPtr dom;

1655
    dom = get_nonnull_domain (conn, args->dom);
1656
    if (dom == NULL) {
1657
        remoteDispatchConnError(rerr, conn);
1658
        return -1;
1659 1660 1661 1662
    }

    /* remoteDispatchClientRequest will free this */
    ret->type = virDomainGetOSType (dom);
1663
    if (ret->type == NULL) {
1664
        virDomainFree(dom);
1665
        remoteDispatchConnError(rerr, conn);
1666
        return -1;
1667 1668
    }
    virDomainFree(dom);
1669 1670 1671 1672
    return 0;
}

static int
1673
remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1674 1675
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1676
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
1677
                              remote_error *rerr,
1678 1679 1680
                              remote_domain_get_vcpus_args *args,
                              remote_domain_get_vcpus_ret *ret)
{
1681 1682 1683
    virDomainPtr dom = NULL;
    virVcpuInfoPtr info = NULL;
    unsigned char *cpumaps = NULL;
1684 1685
    int info_len, i;

1686
    dom = get_nonnull_domain (conn, args->dom);
1687
    if (dom == NULL) {
1688
        remoteDispatchConnError(rerr, conn);
1689
        return -1;
1690 1691 1692
    }

    if (args->maxinfo > REMOTE_VCPUINFO_MAX) {
1693
        virDomainFree(dom);
1694 1695
        remoteDispatchFormatError (rerr, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX"));
        return -1;
1696 1697
    }

1698
    if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
1699
        virDomainFree(dom);
1700 1701
        remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX"));
        return -1;
1702 1703 1704
    }

    /* Allocate buffers to take the results. */
1705 1706
    if (VIR_ALLOC_N(info, args->maxinfo) < 0)
        goto oom;
1707 1708
    if (args->maplen > 0 &&
        VIR_ALLOC_N(cpumaps, args->maxinfo * args->maplen) < 0)
1709
        goto oom;
1710 1711 1712 1713

    info_len = virDomainGetVcpus (dom,
                                  info, args->maxinfo,
                                  cpumaps, args->maplen);
1714
    if (info_len == -1) {
1715 1716
        VIR_FREE(info);
        VIR_FREE(cpumaps);
1717
        virDomainFree(dom);
1718
        remoteDispatchConnError(rerr, conn);
1719 1720
        return -1;
    }
1721 1722 1723

    /* Allocate the return buffer for info. */
    ret->info.info_len = info_len;
1724 1725
    if (VIR_ALLOC_N(ret->info.info_val, info_len) < 0)
        goto oom;
1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737

    for (i = 0; i < info_len; ++i) {
        ret->info.info_val[i].number = info[i].number;
        ret->info.info_val[i].state = info[i].state;
        ret->info.info_val[i].cpu_time = info[i].cpuTime;
        ret->info.info_val[i].cpu = info[i].cpu;
    }

    /* Don't need to allocate/copy the cpumaps if we make the reasonable
     * assumption that unsigned char and char are the same size.
     * Note that remoteDispatchClientRequest will free.
     */
1738
    ret->cpumaps.cpumaps_len = args->maxinfo * args->maplen;
1739 1740
    ret->cpumaps.cpumaps_val = (char *) cpumaps;

1741
    VIR_FREE(info);
1742
    virDomainFree(dom);
1743
    return 0;
1744 1745 1746 1747 1748

oom:
    VIR_FREE(info);
    VIR_FREE(cpumaps);
    virDomainFree(dom);
1749 1750
    remoteDispatchOOMError(rerr);
    return -1;
1751 1752
}

1753
static int
1754
remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED,
1755 1756
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1757
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1758
                                    remote_error *rerr,
1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772
                                    remote_domain_migrate_prepare_args *args,
                                    remote_domain_migrate_prepare_ret *ret)
{
    int r;
    char *cookie = NULL;
    int cookielen = 0;
    char *uri_in;
    char **uri_out;
    char *dname;

    uri_in = args->uri_in == NULL ? NULL : *args->uri_in;
    dname = args->dname == NULL ? NULL : *args->dname;

    /* Wacky world of XDR ... */
1773
    if (VIR_ALLOC(uri_out) < 0) {
1774 1775
        remoteDispatchOOMError(rerr);
        return -1;
1776
    }
1777

1778
    r = virDomainMigratePrepare (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1779 1780
                                 uri_in, uri_out,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1781
    if (r == -1) {
1782
        VIR_FREE(uri_out);
1783
        remoteDispatchConnError(rerr, conn);
D
Daniel P. Berrange 已提交
1784 1785
        return -1;
    }
1786 1787 1788 1789 1790 1791

    /* remoteDispatchClientRequest will free cookie, uri_out and
     * the string if there is one.
     */
    ret->cookie.cookie_len = cookielen;
    ret->cookie.cookie_val = cookie;
D
Daniel P. Berrange 已提交
1792 1793
    if (*uri_out == NULL) {
        ret->uri_out = NULL;
1794
        VIR_FREE(uri_out);
D
Daniel P. Berrange 已提交
1795 1796 1797
    } else {
        ret->uri_out = uri_out;
    }
1798 1799 1800 1801 1802

    return 0;
}

static int
1803
remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED,
1804 1805
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1806
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1807
                                    remote_error *rerr,
1808 1809 1810 1811 1812 1813 1814
                                    remote_domain_migrate_perform_args *args,
                                    void *ret ATTRIBUTE_UNUSED)
{
    int r;
    virDomainPtr dom;
    char *dname;

1815
    dom = get_nonnull_domain (conn, args->dom);
1816
    if (dom == NULL) {
1817
        remoteDispatchConnError(rerr, conn);
1818
        return -1;
1819 1820 1821 1822
    }

    dname = args->dname == NULL ? NULL : *args->dname;

D
Daniel P. Berrange 已提交
1823 1824 1825 1826 1827
    r = virDomainMigratePerform (dom,
                                 args->cookie.cookie_val,
                                 args->cookie.cookie_len,
                                 args->uri,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1828
    virDomainFree (dom);
1829
    if (r == -1) {
1830
        remoteDispatchConnError(rerr, conn);
1831 1832
        return -1;
    }
1833 1834 1835 1836 1837

    return 0;
}

static int
1838
remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED,
1839 1840
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1841
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1842
                                   remote_error *rerr,
1843 1844 1845 1846 1847 1848
                                   remote_domain_migrate_finish_args *args,
                                   remote_domain_migrate_finish_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1849
    ddom = virDomainMigrateFinish (conn, args->dname,
D
Daniel P. Berrange 已提交
1850 1851 1852 1853
                                   args->cookie.cookie_val,
                                   args->cookie.cookie_len,
                                   args->uri,
                                   args->flags);
1854
    if (ddom == NULL) {
1855
        remoteDispatchConnError(rerr, conn);
1856 1857
        return -1;
    }
1858 1859

    make_nonnull_domain (&ret->ddom, ddom);
D
Daniel P. Berrange 已提交
1860
    virDomainFree (ddom);
1861 1862 1863
    return 0;
}

D
Daniel Veillard 已提交
1864 1865
static int
remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1866 1867
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1868
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
1869
                                     remote_error *rerr,
D
Daniel Veillard 已提交
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885
                                     remote_domain_migrate_prepare2_args *args,
                                     remote_domain_migrate_prepare2_ret *ret)
{
    int r;
    char *cookie = NULL;
    int cookielen = 0;
    char *uri_in;
    char **uri_out;
    char *dname;
    CHECK_CONN (client);

    uri_in = args->uri_in == NULL ? NULL : *args->uri_in;
    dname = args->dname == NULL ? NULL : *args->dname;

    /* Wacky world of XDR ... */
    if (VIR_ALLOC(uri_out) < 0) {
1886 1887
        remoteDispatchOOMError(rerr);
        return -1;
D
Daniel Veillard 已提交
1888 1889
    }

1890
    r = virDomainMigratePrepare2 (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1891 1892 1893
                                  uri_in, uri_out,
                                  args->flags, dname, args->resource,
                                  args->dom_xml);
1894
    if (r == -1) {
1895
        remoteDispatchConnError(rerr, conn);
1896 1897
        return -1;
    }
D
Daniel Veillard 已提交
1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910

    /* remoteDispatchClientRequest will free cookie, uri_out and
     * the string if there is one.
     */
    ret->cookie.cookie_len = cookielen;
    ret->cookie.cookie_val = cookie;
    ret->uri_out = *uri_out == NULL ? NULL : uri_out;

    return 0;
}

static int
remoteDispatchDomainMigrateFinish2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1911 1912
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1913
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1914
                                    remote_error *rerr,
D
Daniel Veillard 已提交
1915 1916 1917 1918 1919 1920
                                    remote_domain_migrate_finish2_args *args,
                                    remote_domain_migrate_finish2_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1921
    ddom = virDomainMigrateFinish2 (conn, args->dname,
D
Daniel P. Berrange 已提交
1922 1923 1924 1925 1926
                                    args->cookie.cookie_val,
                                    args->cookie.cookie_len,
                                    args->uri,
                                    args->flags,
                                    args->retcode);
1927
    if (ddom == NULL) {
1928
        remoteDispatchConnError(rerr, conn);
1929 1930
        return -1;
    }
D
Daniel Veillard 已提交
1931 1932

    make_nonnull_domain (&ret->ddom, ddom);
1933
    virDomainFree (ddom);
D
Daniel Veillard 已提交
1934 1935 1936 1937

    return 0;
}

C
Chris Lalancette 已提交
1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959
static int
remoteDispatchDomainMigratePrepareTunnel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                         struct qemud_client *client,
                                         virConnectPtr conn,
                                         remote_message_header *hdr,
                                         remote_error *rerr,
                                         remote_domain_migrate_prepare_tunnel_args *args,
                                         void *ret ATTRIBUTE_UNUSED)
{
    int r;
    char *dname;
    struct qemud_client_stream *stream;
    CHECK_CONN (client);

    dname = args->dname == NULL ? NULL : *args->dname;

    stream = remoteCreateClientStream(conn, hdr);
    if (!stream) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

1960
    r = virDomainMigratePrepareTunnel(conn, stream->st,
C
Chris Lalancette 已提交
1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
                                      args->flags, dname, args->resource,
                                      args->dom_xml);
    if (r == -1) {
        remoteFreeClientStream(client, stream);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (remoteAddClientStream(client, stream, 0) < 0) {
        remoteDispatchConnError(rerr, conn);
        virStreamAbort(stream->st);
        remoteFreeClientStream(client, stream);
        return -1;
    }

    return 0;
}

1979
static int
1980
remoteDispatchListDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1981 1982
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1983
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1984
                                  remote_error *rerr,
1985 1986 1987 1988 1989
                                  remote_list_defined_domains_args *args,
                                  remote_list_defined_domains_ret *ret)
{

    if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) {
1990 1991 1992
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX"));
        return -1;
1993 1994 1995
    }

    /* Allocate return buffer. */
1996
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
1997 1998
        remoteDispatchOOMError(rerr);
        return -1;
1999
    }
2000 2001

    ret->names.names_len =
2002
        virConnectListDefinedDomains (conn,
2003
                                      ret->names.names_val, args->maxnames);
2004 2005
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
2006
        remoteDispatchConnError(rerr, conn);
2007 2008
        return -1;
    }
2009 2010 2011 2012 2013

    return 0;
}

static int
2014
remoteDispatchDomainLookupById (struct qemud_server *server ATTRIBUTE_UNUSED,
2015 2016
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2017
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
2018
                                remote_error *rerr,
2019 2020 2021 2022 2023
                                remote_domain_lookup_by_id_args *args,
                                remote_domain_lookup_by_id_ret *ret)
{
    virDomainPtr dom;

2024
    dom = virDomainLookupByID (conn, args->id);
2025
    if (dom == NULL) {
2026
        remoteDispatchConnError(rerr, conn);
2027 2028
        return -1;
    }
2029 2030

    make_nonnull_domain (&ret->dom, dom);
2031
    virDomainFree(dom);
2032 2033 2034 2035
    return 0;
}

static int
2036
remoteDispatchDomainLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
2037 2038
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2039
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
2040
                                  remote_error *rerr,
2041 2042 2043 2044 2045
                                  remote_domain_lookup_by_name_args *args,
                                  remote_domain_lookup_by_name_ret *ret)
{
    virDomainPtr dom;

2046
    dom = virDomainLookupByName (conn, args->name);
2047
    if (dom == NULL) {
2048
        remoteDispatchConnError(rerr, conn);
2049 2050
        return -1;
    }
2051 2052

    make_nonnull_domain (&ret->dom, dom);
2053
    virDomainFree(dom);
2054 2055 2056 2057
    return 0;
}

static int
2058
remoteDispatchDomainLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
2059 2060
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2061
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
2062
                                  remote_error *rerr,
2063 2064 2065 2066 2067
                                  remote_domain_lookup_by_uuid_args *args,
                                  remote_domain_lookup_by_uuid_ret *ret)
{
    virDomainPtr dom;

2068
    dom = virDomainLookupByUUID (conn, (unsigned char *) args->uuid);
2069
    if (dom == NULL) {
2070
        remoteDispatchConnError(rerr, conn);
2071 2072
        return -1;
    }
2073 2074

    make_nonnull_domain (&ret->dom, dom);
2075
    virDomainFree(dom);
2076 2077 2078 2079
    return 0;
}

static int
2080
remoteDispatchNumOfDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2081 2082
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2083
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2084
                                   remote_error *rerr,
2085 2086 2087 2088
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_num_of_defined_domains_ret *ret)
{

2089
    ret->num = virConnectNumOfDefinedDomains (conn);
2090
    if (ret->num == -1) {
2091
        remoteDispatchConnError(rerr, conn);
2092 2093
        return -1;
    }
2094 2095 2096 2097 2098

    return 0;
}

static int
2099
remoteDispatchDomainPinVcpu (struct qemud_server *server ATTRIBUTE_UNUSED,
2100 2101
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2102
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2103
                             remote_error *rerr,
2104 2105 2106 2107 2108 2109
                             remote_domain_pin_vcpu_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int rv;

2110
    dom = get_nonnull_domain (conn, args->dom);
2111
    if (dom == NULL) {
2112
        remoteDispatchConnError(rerr, conn);
2113
        return -1;
2114 2115 2116
    }

    if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) {
2117
        virDomainFree(dom);
2118 2119
        remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX"));
        return -1;
2120 2121 2122 2123 2124
    }

    rv = virDomainPinVcpu (dom, args->vcpu,
                           (unsigned char *) args->cpumap.cpumap_val,
                           args->cpumap.cpumap_len);
2125 2126
    if (rv == -1) {
        virDomainFree(dom);
2127
        remoteDispatchConnError(rerr, conn);
2128 2129 2130
        return -1;
    }
    virDomainFree(dom);
2131 2132 2133 2134
    return 0;
}

static int
2135
remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED,
2136 2137
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2138
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2139
                            remote_error *rerr,
2140 2141 2142 2143 2144
                            remote_domain_reboot_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2145
    dom = get_nonnull_domain (conn, args->dom);
2146
    if (dom == NULL) {
2147
        remoteDispatchConnError(rerr, conn);
2148
        return -1;
2149 2150
    }

2151 2152
    if (virDomainReboot (dom, args->flags) == -1) {
        virDomainFree(dom);
2153
        remoteDispatchConnError(rerr, conn);
2154
        return -1;
2155 2156
    }
    virDomainFree(dom);
2157 2158 2159 2160
    return 0;
}

static int
2161
remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED,
2162 2163
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2164
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2165
                             remote_error *rerr,
2166 2167 2168 2169
                             remote_domain_restore_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{

2170 2171
    if (virDomainRestore (conn, args->from) == -1) {
        remoteDispatchConnError(rerr, conn);
2172
        return -1;
2173
    }
2174 2175 2176 2177 2178

    return 0;
}

static int
2179
remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED,
2180 2181
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2182
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2183
                            remote_error *rerr,
2184 2185 2186 2187 2188
                            remote_domain_resume_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2189
    dom = get_nonnull_domain (conn, args->dom);
2190
    if (dom == NULL) {
2191
        remoteDispatchConnError(rerr, conn);
2192
        return -1;
2193 2194
    }

2195 2196
    if (virDomainResume (dom) == -1) {
        virDomainFree(dom);
2197
        remoteDispatchConnError(rerr, conn);
2198
        return -1;
2199 2200
    }
    virDomainFree(dom);
2201 2202 2203 2204
    return 0;
}

static int
2205
remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED,
2206 2207
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
2208
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
2209
                          remote_error *rerr,
2210 2211 2212 2213 2214
                          remote_domain_save_args *args,
                          void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2215
    dom = get_nonnull_domain (conn, args->dom);
2216
    if (dom == NULL) {
2217
        remoteDispatchConnError(rerr, conn);
2218
        return -1;
2219 2220
    }

2221 2222
    if (virDomainSave (dom, args->to) == -1) {
        virDomainFree(dom);
2223
        remoteDispatchConnError(rerr, conn);
2224
        return -1;
2225 2226
    }
    virDomainFree(dom);
2227 2228 2229 2230
    return 0;
}

static int
2231
remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED,
2232 2233
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2234
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2235
                              remote_error *rerr,
2236 2237 2238 2239 2240
                              remote_domain_core_dump_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2241
    dom = get_nonnull_domain (conn, args->dom);
2242
    if (dom == NULL) {
2243
        remoteDispatchConnError(rerr, conn);
2244
        return -1;
2245 2246
    }

2247 2248
    if (virDomainCoreDump (dom, args->to, args->flags) == -1) {
        virDomainFree(dom);
2249
        remoteDispatchConnError(rerr, conn);
2250
        return -1;
2251 2252
    }
    virDomainFree(dom);
2253 2254 2255 2256
    return 0;
}

static int
2257
remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2258 2259
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2260
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
2261
                                  remote_error *rerr,
2262 2263 2264 2265 2266
                                  remote_domain_set_autostart_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2267
    dom = get_nonnull_domain (conn, args->dom);
2268
    if (dom == NULL) {
2269
        remoteDispatchConnError(rerr, conn);
2270
        return -1;
2271 2272
    }

2273 2274
    if (virDomainSetAutostart (dom, args->autostart) == -1) {
        virDomainFree(dom);
2275
        remoteDispatchConnError(rerr, conn);
2276
        return -1;
2277 2278
    }
    virDomainFree(dom);
2279 2280 2281 2282
    return 0;
}

static int
2283
remoteDispatchDomainSetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
2284 2285
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2286
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
2287
                                  remote_error *rerr,
2288 2289 2290 2291 2292
                                  remote_domain_set_max_memory_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2293
    dom = get_nonnull_domain (conn, args->dom);
2294
    if (dom == NULL) {
2295
        remoteDispatchConnError(rerr, conn);
2296
        return -1;
2297 2298
    }

2299 2300
    if (virDomainSetMaxMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
2301
        remoteDispatchConnError(rerr, conn);
2302
        return -1;
2303 2304
    }
    virDomainFree(dom);
2305 2306 2307 2308
    return 0;
}

static int
2309
remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
2310 2311
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2312
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
2313
                               remote_error *rerr,
2314 2315 2316 2317 2318
                               remote_domain_set_memory_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2319
    dom = get_nonnull_domain (conn, args->dom);
2320
    if (dom == NULL) {
2321
        remoteDispatchConnError(rerr, conn);
2322
        return -1;
2323 2324
    }

2325 2326
    if (virDomainSetMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
2327
        remoteDispatchConnError(rerr, conn);
2328
        return -1;
2329 2330
    }
    virDomainFree(dom);
2331 2332 2333 2334
    return 0;
}

static int
2335
remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
2336 2337
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2338
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2339
                              remote_error *rerr,
2340 2341 2342 2343 2344
                              remote_domain_set_vcpus_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2345
    dom = get_nonnull_domain (conn, args->dom);
2346
    if (dom == NULL) {
2347
        remoteDispatchConnError(rerr, conn);
2348
        return -1;
2349 2350
    }

2351 2352
    if (virDomainSetVcpus (dom, args->nvcpus) == -1) {
        virDomainFree(dom);
2353
        remoteDispatchConnError(rerr, conn);
2354
        return -1;
2355 2356
    }
    virDomainFree(dom);
2357 2358 2359 2360
    return 0;
}

static int
2361
remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED,
2362 2363
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2364
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2365
                              remote_error *rerr,
2366 2367 2368 2369 2370
                              remote_domain_shutdown_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2371
    dom = get_nonnull_domain (conn, args->dom);
2372
    if (dom == NULL) {
2373
        remoteDispatchConnError(rerr, conn);
2374
        return -1;
2375 2376
    }

2377 2378
    if (virDomainShutdown (dom) == -1) {
        virDomainFree(dom);
2379
        remoteDispatchConnError(rerr, conn);
2380
        return -1;
2381 2382
    }
    virDomainFree(dom);
2383 2384 2385 2386
    return 0;
}

static int
2387
remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED,
2388 2389
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2390
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2391
                             remote_error *rerr,
2392 2393 2394 2395 2396
                             remote_domain_suspend_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2397
    dom = get_nonnull_domain (conn, args->dom);
2398
    if (dom == NULL) {
2399
        remoteDispatchConnError(rerr, conn);
2400
        return -1;
2401 2402
    }

2403 2404
    if (virDomainSuspend (dom) == -1) {
        virDomainFree(dom);
2405
        remoteDispatchConnError(rerr, conn);
2406
        return -1;
2407 2408
    }
    virDomainFree(dom);
2409 2410 2411 2412
    return 0;
}

static int
2413
remoteDispatchDomainUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2414 2415
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2416
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2417
                              remote_error *rerr,
2418 2419 2420 2421 2422
                              remote_domain_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2423
    dom = get_nonnull_domain (conn, args->dom);
2424
    if (dom == NULL) {
2425
        remoteDispatchConnError(rerr, conn);
2426
        return -1;
2427 2428
    }

2429 2430
    if (virDomainUndefine (dom) == -1) {
        virDomainFree(dom);
2431
        remoteDispatchConnError(rerr, conn);
2432
        return -1;
2433 2434
    }
    virDomainFree(dom);
2435 2436 2437 2438
    return 0;
}

static int
2439
remoteDispatchListDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2440 2441
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2442
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2443
                                   remote_error *rerr,
2444 2445 2446 2447 2448
                                   remote_list_defined_networks_args *args,
                                   remote_list_defined_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2449 2450 2451
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2452 2453 2454
    }

    /* Allocate return buffer. */
2455
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
2456 2457
        remoteDispatchOOMError(rerr);
        return -1;
2458
    }
2459 2460

    ret->names.names_len =
2461
        virConnectListDefinedNetworks (conn,
2462
                                       ret->names.names_val, args->maxnames);
2463 2464
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
2465
        remoteDispatchConnError(rerr, conn);
2466 2467
        return -1;
    }
2468 2469 2470 2471 2472

    return 0;
}

static int
2473
remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2474 2475
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
2476
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
2477
                           remote_error *rerr,
2478 2479 2480 2481 2482
                           remote_list_domains_args *args,
                           remote_list_domains_ret *ret)
{

    if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
2483 2484 2485
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX"));
        return -1;
2486 2487 2488
    }

    /* Allocate return buffer. */
2489
    if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) {
2490 2491
        remoteDispatchOOMError(rerr);
        return -1;
2492
    }
2493

2494
    ret->ids.ids_len = virConnectListDomains (conn,
2495
                                              ret->ids.ids_val, args->maxids);
2496 2497
    if (ret->ids.ids_len == -1) {
        VIR_FREE(ret->ids.ids_val);
2498
        remoteDispatchConnError(rerr, conn);
2499 2500
        return -1;
    }
2501 2502 2503 2504

    return 0;
}

2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583
static int
remoteDispatchDomainManagedSave (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_domain_managed_save_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainManagedSave (dom, args->flags) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

static int
remoteDispatchDomainHasManagedSaveImage (struct qemud_server *server ATTRIBUTE_UNUSED,
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
                                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                                         remote_error *rerr,
                                         remote_domain_has_managed_save_image_args *args,
                                         remote_domain_has_managed_save_image_ret *ret)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    ret->ret = virDomainHasManagedSaveImage (dom, args->flags);
    if (ret->ret == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

static int
remoteDispatchDomainManagedSaveRemove (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_managed_save_remove_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainManagedSaveRemove (dom, args->flags) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

2584
static int
2585
remoteDispatchListNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2586 2587
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2588
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2589
                            remote_error *rerr,
2590 2591 2592 2593 2594
                            remote_list_networks_args *args,
                            remote_list_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2595 2596 2597
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2598 2599 2600
    }

    /* Allocate return buffer. */
2601
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
2602 2603
        remoteDispatchOOMError(rerr);
        return -1;
2604
    }
2605 2606

    ret->names.names_len =
2607
        virConnectListNetworks (conn,
2608
                                ret->names.names_val, args->maxnames);
2609 2610
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
2611
        remoteDispatchConnError(rerr, conn);
2612 2613
        return -1;
    }
2614 2615 2616 2617 2618

    return 0;
}

static int
2619
remoteDispatchNetworkCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
2620 2621
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2622
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2623
                             remote_error *rerr,
2624 2625 2626 2627 2628
                             remote_network_create_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2629
    net = get_nonnull_network (conn, args->net);
2630
    if (net == NULL) {
2631
        remoteDispatchConnError(rerr, conn);
2632
        return -1;
2633 2634
    }

2635 2636
    if (virNetworkCreate (net) == -1) {
        virNetworkFree(net);
2637
        remoteDispatchConnError(rerr, conn);
2638
        return -1;
2639 2640
    }
    virNetworkFree(net);
2641 2642 2643 2644
    return 0;
}

static int
2645
remoteDispatchNetworkCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2646 2647
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2648
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
2649
                                remote_error *rerr,
2650 2651 2652 2653 2654
                                remote_network_create_xml_args *args,
                                remote_network_create_xml_ret *ret)
{
    virNetworkPtr net;

2655
    net = virNetworkCreateXML (conn, args->xml);
2656
    if (net == NULL) {
2657
        remoteDispatchConnError(rerr, conn);
2658 2659
        return -1;
    }
2660 2661

    make_nonnull_network (&ret->net, net);
2662
    virNetworkFree(net);
2663 2664 2665 2666
    return 0;
}

static int
2667
remoteDispatchNetworkDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2668 2669
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2670
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
2671
                                remote_error *rerr,
2672 2673 2674 2675 2676
                                remote_network_define_xml_args *args,
                                remote_network_define_xml_ret *ret)
{
    virNetworkPtr net;

2677
    net = virNetworkDefineXML (conn, args->xml);
2678
    if (net == NULL) {
2679
        remoteDispatchConnError(rerr, conn);
2680 2681
        return -1;
    }
2682 2683

    make_nonnull_network (&ret->net, net);
2684
    virNetworkFree(net);
2685 2686 2687 2688
    return 0;
}

static int
2689
remoteDispatchNetworkDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
2690 2691
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2692
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2693
                              remote_error *rerr,
2694 2695 2696 2697 2698
                              remote_network_destroy_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2699
    net = get_nonnull_network (conn, args->net);
2700
    if (net == NULL) {
2701
        remoteDispatchConnError(rerr, conn);
2702
        return -1;
2703 2704
    }

2705 2706
    if (virNetworkDestroy (net) == -1) {
        virNetworkFree(net);
2707
        remoteDispatchConnError(rerr, conn);
2708
        return -1;
2709 2710
    }
    virNetworkFree(net);
2711 2712 2713 2714
    return 0;
}

static int
2715
remoteDispatchNetworkDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2716 2717
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2718
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2719
                              remote_error *rerr,
2720 2721 2722 2723 2724
                              remote_network_dump_xml_args *args,
                              remote_network_dump_xml_ret *ret)
{
    virNetworkPtr net;

2725
    net = get_nonnull_network (conn, args->net);
2726
    if (net == NULL) {
2727
        remoteDispatchConnError(rerr, conn);
2728
        return -1;
2729 2730 2731 2732
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNetworkGetXMLDesc (net, args->flags);
2733 2734
    if (!ret->xml) {
        virNetworkFree(net);
2735
        remoteDispatchConnError(rerr, conn);
2736 2737 2738
        return -1;
    }
    virNetworkFree(net);
2739 2740 2741 2742
    return 0;
}

static int
2743
remoteDispatchNetworkGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2744 2745
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2746
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2747
                                   remote_error *rerr,
2748 2749 2750 2751 2752
                                   remote_network_get_autostart_args *args,
                                   remote_network_get_autostart_ret *ret)
{
    virNetworkPtr net;

2753
    net = get_nonnull_network (conn, args->net);
2754
    if (net == NULL) {
2755
        remoteDispatchConnError(rerr, conn);
2756
        return -1;
2757 2758
    }

2759 2760
    if (virNetworkGetAutostart (net, &ret->autostart) == -1) {
        virNetworkFree(net);
2761
        remoteDispatchConnError(rerr, conn);
2762
        return -1;
2763 2764
    }
    virNetworkFree(net);
2765 2766 2767 2768
    return 0;
}

static int
2769
remoteDispatchNetworkGetBridgeName (struct qemud_server *server ATTRIBUTE_UNUSED,
2770 2771
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2772
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
2773
                                    remote_error *rerr,
2774 2775 2776 2777 2778
                                    remote_network_get_bridge_name_args *args,
                                    remote_network_get_bridge_name_ret *ret)
{
    virNetworkPtr net;

2779
    net = get_nonnull_network (conn, args->net);
2780
    if (net == NULL) {
2781
        remoteDispatchConnError(rerr, conn);
2782
        return -1;
2783 2784 2785 2786
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virNetworkGetBridgeName (net);
2787 2788
    if (!ret->name) {
        virNetworkFree(net);
2789
        remoteDispatchConnError(rerr, conn);
2790 2791 2792
        return -1;
    }
    virNetworkFree(net);
2793 2794 2795 2796
    return 0;
}

static int
2797
remoteDispatchNetworkLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
2798 2799
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2800
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2801
                                   remote_error *rerr,
2802 2803 2804 2805 2806
                                   remote_network_lookup_by_name_args *args,
                                   remote_network_lookup_by_name_ret *ret)
{
    virNetworkPtr net;

2807
    net = virNetworkLookupByName (conn, args->name);
2808
    if (net == NULL) {
2809
        remoteDispatchConnError(rerr, conn);
2810 2811
        return -1;
    }
2812 2813

    make_nonnull_network (&ret->net, net);
2814
    virNetworkFree(net);
2815 2816 2817 2818
    return 0;
}

static int
2819
remoteDispatchNetworkLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
2820 2821
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2822
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2823
                                   remote_error *rerr,
2824 2825 2826 2827 2828
                                   remote_network_lookup_by_uuid_args *args,
                                   remote_network_lookup_by_uuid_ret *ret)
{
    virNetworkPtr net;

2829
    net = virNetworkLookupByUUID (conn, (unsigned char *) args->uuid);
2830
    if (net == NULL) {
2831
        remoteDispatchConnError(rerr, conn);
2832 2833
        return -1;
    }
2834 2835

    make_nonnull_network (&ret->net, net);
2836
    virNetworkFree(net);
2837 2838 2839 2840
    return 0;
}

static int
2841
remoteDispatchNetworkSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2842 2843
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2844
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2845
                                   remote_error *rerr,
2846 2847 2848 2849 2850
                                   remote_network_set_autostart_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2851
    net = get_nonnull_network (conn, args->net);
2852
    if (net == NULL) {
2853
        remoteDispatchConnError(rerr, conn);
2854
        return -1;
2855 2856
    }

2857 2858
    if (virNetworkSetAutostart (net, args->autostart) == -1) {
        virNetworkFree(net);
2859
        remoteDispatchConnError(rerr, conn);
2860
        return -1;
2861 2862
    }
    virNetworkFree(net);
2863 2864 2865 2866
    return 0;
}

static int
2867
remoteDispatchNetworkUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2868 2869
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2870
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
2871
                               remote_error *rerr,
2872 2873 2874 2875 2876
                               remote_network_undefine_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2877
    net = get_nonnull_network (conn, args->net);
2878
    if (net == NULL) {
2879
        remoteDispatchConnError(rerr, conn);
2880
        return -1;
2881 2882
    }

2883 2884
    if (virNetworkUndefine (net) == -1) {
        virNetworkFree(net);
2885
        remoteDispatchConnError(rerr, conn);
2886
        return -1;
2887 2888
    }
    virNetworkFree(net);
2889 2890 2891 2892
    return 0;
}

static int
2893
remoteDispatchNumOfDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2894 2895
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2896
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
2897
                                    remote_error *rerr,
2898 2899 2900 2901
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_num_of_defined_networks_ret *ret)
{

2902
    ret->num = virConnectNumOfDefinedNetworks (conn);
2903
    if (ret->num == -1) {
2904
        remoteDispatchConnError(rerr, conn);
2905 2906
        return -1;
    }
2907 2908 2909 2910 2911

    return 0;
}

static int
2912
remoteDispatchNumOfDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2913 2914
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2915
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2916
                            remote_error *rerr,
2917 2918 2919 2920
                            void *args ATTRIBUTE_UNUSED,
                            remote_num_of_domains_ret *ret)
{

2921
    ret->num = virConnectNumOfDomains (conn);
2922
    if (ret->num == -1) {
2923
        remoteDispatchConnError(rerr, conn);
2924 2925
        return -1;
    }
2926 2927 2928 2929 2930

    return 0;
}

static int
2931
remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2932 2933
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2934
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2935
                             remote_error *rerr,
2936 2937 2938 2939
                             void *args ATTRIBUTE_UNUSED,
                             remote_num_of_networks_ret *ret)
{

2940
    ret->num = virConnectNumOfNetworks (conn);
2941
    if (ret->num == -1) {
2942
        remoteDispatchConnError(rerr, conn);
2943 2944
        return -1;
    }
2945 2946 2947 2948

    return 0;
}

2949

D
Daniel Veillard 已提交
2950 2951 2952 2953 2954
/*-------------------------------------------------------------*/
static int
remoteDispatchNumOfInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2955
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973
                               remote_error *rerr,
                               void *args ATTRIBUTE_UNUSED,
                               remote_num_of_interfaces_ret *ret)
{

    ret->num = virConnectNumOfInterfaces (conn);
    if (ret->num == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

static int
remoteDispatchListInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2974
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003
                              remote_error *rerr,
                              remote_list_interfaces_args *args,
                              remote_list_interfaces_ret *ret)
{

    if (args->maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) {
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_INTERFACE_NAME_LIST_MAX"));
        return -1;
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

    ret->names.names_len =
        virConnectListInterfaces (conn,
                                  ret->names.names_val, args->maxnames);
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

3004 3005 3006 3007
static int
remoteDispatchNumOfDefinedInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3008
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
                                      remote_error *rerr,
                                      void *args ATTRIBUTE_UNUSED,
                                      remote_num_of_defined_interfaces_ret *ret)
{

    ret->num = virConnectNumOfDefinedInterfaces (conn);
    if (ret->num == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

static int
remoteDispatchListDefinedInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
3027
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056
                                     remote_error *rerr,
                                     remote_list_defined_interfaces_args *args,
                                     remote_list_defined_interfaces_ret *ret)
{

    if (args->maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) {
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX"));
        return -1;
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

    ret->names.names_len =
        virConnectListDefinedInterfaces (conn,
                                         ret->names.names_val, args->maxnames);
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

D
Daniel Veillard 已提交
3057 3058 3059 3060
static int
remoteDispatchInterfaceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
3061
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
3062 3063 3064 3065
                                     remote_error *rerr,
                                     remote_interface_lookup_by_name_args *args,
                                     remote_interface_lookup_by_name_ret *ret)
{
3066
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3067

3068 3069
    iface = virInterfaceLookupByName (conn, args->name);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3070 3071 3072 3073
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3074 3075
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3076 3077 3078 3079 3080 3081 3082
    return 0;
}

static int
remoteDispatchInterfaceLookupByMacString (struct qemud_server *server ATTRIBUTE_UNUSED,
                                          struct qemud_client *client ATTRIBUTE_UNUSED,
                                          virConnectPtr conn,
3083
                                          remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
3084 3085 3086 3087
                                          remote_error *rerr,
                                          remote_interface_lookup_by_mac_string_args *args,
                                          remote_interface_lookup_by_mac_string_ret *ret)
{
3088
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3089

3090 3091
    iface = virInterfaceLookupByMACString (conn, args->mac);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3092 3093 3094 3095
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3096 3097
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3098 3099 3100 3101 3102 3103 3104
    return 0;
}

static int
remoteDispatchInterfaceGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
3105
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
3106 3107 3108 3109
                                   remote_error *rerr,
                                   remote_interface_get_xml_desc_args *args,
                                   remote_interface_get_xml_desc_ret *ret)
{
3110
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3111

3112 3113
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3114 3115 3116 3117 3118
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* remoteDispatchClientRequest will free this. */
3119
    ret->xml = virInterfaceGetXMLDesc (iface, args->flags);
D
Daniel Veillard 已提交
3120
    if (!ret->xml) {
3121
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3122 3123 3124
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
3125
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3126 3127 3128 3129 3130 3131 3132
    return 0;
}

static int
remoteDispatchInterfaceDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3133
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
3134 3135 3136 3137
                                  remote_error *rerr,
                                  remote_interface_define_xml_args *args,
                                  remote_interface_define_xml_ret *ret)
{
3138
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3139

3140 3141
    iface = virInterfaceDefineXML (conn, args->xml, args->flags);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3142 3143 3144 3145
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3146 3147
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3148 3149 3150 3151 3152
    return 0;
}

static int
remoteDispatchInterfaceUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
3153 3154 3155 3156 3157 3158
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_interface_undefine_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
D
Daniel Veillard 已提交
3159
{
3160
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3161

3162 3163
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3164 3165 3166 3167
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3168 3169
    if (virInterfaceUndefine (iface) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3170 3171 3172
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
3173
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3174 3175 3176 3177 3178
    return 0;
}

static int
remoteDispatchInterfaceCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
3179 3180 3181 3182 3183 3184
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *rerr,
                               remote_interface_create_args *args,
                               void *ret ATTRIBUTE_UNUSED)
D
Daniel Veillard 已提交
3185
{
3186
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3187

3188 3189
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3190 3191 3192 3193
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3194 3195
    if (virInterfaceCreate (iface, args->flags) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3196 3197 3198
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
3199
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3200 3201 3202 3203 3204
    return 0;
}

static int
remoteDispatchInterfaceDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
3205 3206 3207 3208 3209 3210
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *rerr,
                                remote_interface_destroy_args *args,
                                void *ret ATTRIBUTE_UNUSED)
D
Daniel Veillard 已提交
3211
{
3212
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3213

3214 3215
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3216 3217 3218 3219
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3220 3221
    if (virInterfaceDestroy (iface, args->flags) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3222 3223 3224
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
3225
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3226 3227 3228 3229 3230
    return 0;
}

/*-------------------------------------------------------------*/

3231
static int
3232
remoteDispatchAuthList (struct qemud_server *server,
3233
                        struct qemud_client *client,
3234
                        virConnectPtr conn ATTRIBUTE_UNUSED,
3235
                        remote_message_header *hdr ATTRIBUTE_UNUSED,
3236
                        remote_error *rerr,
3237 3238 3239 3240
                        void *args ATTRIBUTE_UNUSED,
                        remote_auth_list_ret *ret)
{
    ret->types.types_len = 1;
3241
    if (VIR_ALLOC_N(ret->types.types_val, ret->types.types_len) < 0) {
3242 3243
        remoteDispatchOOMError(rerr);
        return -1;
3244
    }
3245 3246 3247
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3248
    ret->types.types_val[0] = client->auth;
3249
    virMutexUnlock(&client->lock);
3250

3251 3252 3253 3254 3255 3256
    return 0;
}


#if HAVE_SASL
/*
3257
 * NB, keep in sync with similar method in src/remote/remote_driver.c
3258
 */
3259
static char *addrToString(remote_error *rerr,
3260 3261
                          struct sockaddr_storage *ss, socklen_t salen) {
    char host[NI_MAXHOST], port[NI_MAXSERV];
3262 3263
    char *addr;
    int err;
3264
    struct sockaddr *sa = (struct sockaddr *)ss;
3265

3266
    if ((err = getnameinfo(sa, salen,
3267 3268 3269
                           host, sizeof(host),
                           port, sizeof(port),
                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286
        char ip[INET6_ADDRSTRLEN];
        void *rawaddr;

        if (sa->sa_family == AF_INET)
            rawaddr = &((struct sockaddr_in *)sa)->sin_addr;
        else
            rawaddr = &((struct sockaddr_in6 *)sa)->sin6_addr;

        if (inet_ntop(sa->sa_family, rawaddr, ip, sizeof ip)) {
            remoteDispatchFormatError(rerr,
                                      _("Cannot resolve address %s: %s"),
                                      ip, gai_strerror(err));
        } else {
            remoteDispatchFormatError(rerr,
                                      _("Cannot resolve address: %s"),
                                      gai_strerror(err));
        }
3287 3288 3289
        return NULL;
    }

3290
    if (virAsprintf(&addr, "%s;%s", host, port) == -1) {
3291
        virReportOOMError();
3292 3293 3294 3295 3296 3297 3298 3299 3300
        return NULL;
    }

    return addr;
}


/*
 * Initializes the SASL session in prepare for authentication
3301
 * and gives the client a list of allowed mechanisms to choose
3302 3303 3304 3305
 *
 * XXX callbacks for stuff like password verification ?
 */
static int
3306
remoteDispatchAuthSaslInit (struct qemud_server *server,
3307
                            struct qemud_client *client,
3308
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3309
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3310
                            remote_error *rerr,
3311 3312 3313 3314
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret)
{
    const char *mechlist = NULL;
3315
    sasl_security_properties_t secprops;
3316 3317 3318 3319 3320
    int err;
    struct sockaddr_storage sa;
    socklen_t salen;
    char *localAddr, *remoteAddr;

3321 3322 3323
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3324

3325 3326 3327
    REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn != NULL) {
3328
        VIR_ERROR0(_("client tried invalid SASL init request"));
3329
        goto authfail;
3330 3331 3332 3333 3334
    }

    /* Get local address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getsockname(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
3335
        char ebuf[1024];
3336
        remoteDispatchFormatError(rerr,
3337
                                  _("failed to get sock address: %s"),
3338
                                  virStrerror(errno, ebuf, sizeof ebuf));
3339
        goto error;
3340
    }
3341
    if ((localAddr = addrToString(rerr, &sa, salen)) == NULL) {
3342
        goto error;
3343 3344 3345 3346 3347
    }

    /* Get remote address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getpeername(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
3348
        char ebuf[1024];
3349
        remoteDispatchFormatError(rerr, _("failed to get peer address: %s"),
3350
                                  virStrerror(errno, ebuf, sizeof ebuf));
3351
        VIR_FREE(localAddr);
3352
        goto error;
3353
    }
3354
    if ((remoteAddr = addrToString(rerr, &sa, salen)) == NULL) {
3355
        VIR_FREE(localAddr);
3356
        goto error;
3357 3358 3359 3360 3361 3362 3363 3364 3365 3366
    }

    err = sasl_server_new("libvirt",
                          NULL, /* FQDN - just delegates to gethostname */
                          NULL, /* User realm */
                          localAddr,
                          remoteAddr,
                          NULL, /* XXX Callbacks */
                          SASL_SUCCESS_DATA,
                          &client->saslconn);
3367 3368
    VIR_FREE(localAddr);
    VIR_FREE(remoteAddr);
3369
    if (err != SASL_OK) {
3370 3371
        VIR_ERROR(_("sasl context setup failed %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3372
        client->saslconn = NULL;
3373
        goto authfail;
3374 3375
    }

3376 3377 3378 3379 3380 3381 3382
    /* Inform SASL that we've got an external SSF layer from TLS */
    if (client->type == QEMUD_SOCK_TYPE_TLS) {
        gnutls_cipher_algorithm_t cipher;
        sasl_ssf_t ssf;

        cipher = gnutls_cipher_get(client->tlssession);
        if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) {
D
Daniel Veillard 已提交
3383
            VIR_ERROR0(_("cannot get TLS cipher size"));
3384 3385
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
3386
            goto authfail;
3387 3388 3389 3390 3391
        }
        ssf *= 8; /* tls key size is bytes, sasl wants bits */

        err = sasl_setprop(client->saslconn, SASL_SSF_EXTERNAL, &ssf);
        if (err != SASL_OK) {
3392 3393
            VIR_ERROR(_("cannot set SASL external SSF %d (%s)"),
                      err, sasl_errstring(err, NULL, NULL));
3394 3395
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
3396
            goto authfail;
3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419
        }
    }

    memset (&secprops, 0, sizeof secprops);
    if (client->type == QEMUD_SOCK_TYPE_TLS ||
        client->type == QEMUD_SOCK_TYPE_UNIX) {
        /* If we've got TLS or UNIX domain sock, we don't care about SSF */
        secprops.min_ssf = 0;
        secprops.max_ssf = 0;
        secprops.maxbufsize = 8192;
        secprops.security_flags = 0;
    } else {
        /* Plain TCP, better get an SSF layer */
        secprops.min_ssf = 56; /* Good enough to require kerberos */
        secprops.max_ssf = 100000; /* Arbitrary big number */
        secprops.maxbufsize = 8192;
        /* Forbid any anonymous or trivially crackable auth */
        secprops.security_flags =
            SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT;
    }

    err = sasl_setprop(client->saslconn, SASL_SEC_PROPS, &secprops);
    if (err != SASL_OK) {
3420 3421
        VIR_ERROR(_("cannot set SASL security props %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3422 3423
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3424
        goto authfail;
3425 3426
    }

3427 3428 3429 3430 3431 3432 3433 3434 3435
    err = sasl_listmech(client->saslconn,
                        NULL, /* Don't need to set user */
                        "", /* Prefix */
                        ",", /* Separator */
                        "", /* Suffix */
                        &mechlist,
                        NULL,
                        NULL);
    if (err != SASL_OK) {
3436 3437
        VIR_ERROR(_("cannot list SASL mechanisms %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3438 3439
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3440
        goto authfail;
3441 3442 3443 3444
    }
    REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist);
    ret->mechlist = strdup(mechlist);
    if (!ret->mechlist) {
3445
        VIR_ERROR0(_("cannot allocate mechlist"));
3446 3447
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3448
        goto authfail;
3449 3450
    }

3451
    virMutexUnlock(&client->lock);
3452
    return 0;
3453 3454 3455 3456

authfail:
    remoteDispatchAuthError(rerr);
error:
3457
    virMutexUnlock(&client->lock);
3458
    return -1;
3459 3460 3461
}


3462
/* We asked for an SSF layer, so sanity check that we actually
3463 3464 3465
 * got what we asked for
 * Returns 0 if ok, -1 on error, -2 if rejected
 */
3466 3467
static int
remoteSASLCheckSSF (struct qemud_client *client,
3468
                    remote_error *rerr) {
3469 3470 3471 3472 3473 3474 3475 3476 3477
    const void *val;
    int err, ssf;

    if (client->type == QEMUD_SOCK_TYPE_TLS ||
        client->type == QEMUD_SOCK_TYPE_UNIX)
        return 0; /* TLS or UNIX domain sockets trivially OK */

    err = sasl_getprop(client->saslconn, SASL_SSF, &val);
    if (err != SASL_OK) {
3478 3479
        VIR_ERROR(_("cannot query SASL ssf on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3480
        remoteDispatchAuthError(rerr);
3481 3482 3483 3484 3485 3486 3487
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    ssf = *(const int *)val;
    REMOTE_DEBUG("negotiated an SSF of %d", ssf);
    if (ssf < 56) { /* 56 is good for Kerberos */
3488
        VIR_ERROR(_("negotiated SSF %d was not strong enough"), ssf);
3489
        remoteDispatchAuthError(rerr);
3490 3491
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3492
        return -2;
3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506
    }

    /* Only setup for read initially, because we're about to send an RPC
     * reply which must be in plain text. When the next incoming RPC
     * arrives, we'll switch on writes too
     *
     * cf qemudClientReadSASL  in qemud.c
     */
    client->saslSSF = QEMUD_SASL_SSF_READ;

    /* We have a SSF !*/
    return 0;
}

3507 3508 3509
/*
 * Returns 0 if ok, -1 on error, -2 if rejected
 */
3510 3511 3512
static int
remoteSASLCheckAccess (struct qemud_server *server,
                       struct qemud_client *client,
3513
                       remote_error *rerr) {
3514 3515 3516 3517 3518 3519
    const void *val;
    int err;
    char **wildcards;

    err = sasl_getprop(client->saslconn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
3520 3521
        VIR_ERROR(_("cannot query SASL username on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3522
        remoteDispatchAuthError(rerr);
3523 3524 3525 3526 3527
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    if (val == NULL) {
3528
        VIR_ERROR0(_("no client username was found"));
3529
        remoteDispatchAuthError(rerr);
3530 3531 3532 3533 3534 3535 3536 3537
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    REMOTE_DEBUG("SASL client username %s", (const char *)val);

    client->saslUsername = strdup((const char*)val);
    if (client->saslUsername == NULL) {
3538
        VIR_ERROR0(_("out of memory copying username"));
3539
        remoteDispatchAuthError(rerr);
3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }

    /* If the list is not set, allow any DN. */
    wildcards = server->saslUsernameWhitelist;
    if (!wildcards)
        return 0; /* No ACL, allow all */

    while (*wildcards) {
        if (fnmatch (*wildcards, client->saslUsername, 0) == 0)
            return 0; /* Allowed */
        wildcards++;
    }

    /* Denied */
3557
    VIR_ERROR(_("SASL client %s not allowed in whitelist"), client->saslUsername);
3558
    remoteDispatchAuthError(rerr);
3559 3560
    sasl_dispose(&client->saslconn);
    client->saslconn = NULL;
3561
    return -2;
3562 3563 3564
}


3565 3566 3567 3568
/*
 * This starts the SASL authentication negotiation.
 */
static int
3569 3570
remoteDispatchAuthSaslStart (struct qemud_server *server,
                             struct qemud_client *client,
3571
                             virConnectPtr conn ATTRIBUTE_UNUSED,
3572
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
3573
                             remote_error *rerr,
3574 3575 3576 3577 3578 3579 3580
                             remote_auth_sasl_start_args *args,
                             remote_auth_sasl_start_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

3581 3582 3583
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3584

3585 3586 3587
    REMOTE_DEBUG("Start SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
3588
        VIR_ERROR0(_("client tried invalid SASL start request"));
3589
        goto authfail;
3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602
    }

    REMOTE_DEBUG("Using SASL mechanism %s. Data %d bytes, nil: %d",
                 args->mech, args->data.data_len, args->nil);
    err = sasl_server_start(client->saslconn,
                            args->mech,
                            /* NB, distinction of NULL vs "" is *critical* in SASL */
                            args->nil ? NULL : args->data.data_val,
                            args->data.data_len,
                            &serverout,
                            &serveroutlen);
    if (err != SASL_OK &&
        err != SASL_CONTINUE) {
3603 3604
        VIR_ERROR(_("sasl start failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3605 3606
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3607
        goto authfail;
3608 3609
    }
    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
3610
        VIR_ERROR(_("sasl start reply data too long %d"), serveroutlen);
3611 3612
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3613
        goto authfail;
3614 3615 3616 3617
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
3618
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
3619
            remoteDispatchOOMError(rerr);
3620
            goto error;
3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632
        }
        memcpy(ret->data.data_val, serverout, serveroutlen);
    } else {
        ret->data.data_val = NULL;
    }
    ret->nil = serverout ? 0 : 1;
    ret->data.data_len = serveroutlen;

    REMOTE_DEBUG("SASL return data %d bytes, nil; %d", ret->data.data_len, ret->nil);
    if (err == SASL_CONTINUE) {
        ret->complete = 0;
    } else {
3633
        /* Check username whitelist ACL */
3634 3635 3636 3637 3638 3639 3640
        if ((err = remoteSASLCheckAccess(server, client, rerr)) < 0 ||
            (err = remoteSASLCheckSSF(client, rerr)) < 0) {
            if (err == -2)
                goto authdeny;
            else
                goto authfail;
        }
3641

3642 3643 3644 3645 3646
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

3647
    virMutexUnlock(&client->lock);
3648
    return 0;
3649 3650 3651

authfail:
    remoteDispatchAuthError(rerr);
3652 3653 3654 3655 3656
    goto error;

authdeny:
    goto error;

3657
error:
3658
    virMutexUnlock(&client->lock);
3659
    return -1;
3660 3661 3662 3663
}


static int
3664 3665
remoteDispatchAuthSaslStep (struct qemud_server *server,
                            struct qemud_client *client,
3666
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3667
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3668
                            remote_error *rerr,
3669 3670 3671 3672 3673 3674 3675
                            remote_auth_sasl_step_args *args,
                            remote_auth_sasl_step_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

3676 3677 3678
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3679

3680 3681 3682
    REMOTE_DEBUG("Step SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
3683
        VIR_ERROR0(_("client tried invalid SASL start request"));
3684
        goto authfail;
3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696
    }

    REMOTE_DEBUG("Using SASL Data %d bytes, nil: %d",
                 args->data.data_len, args->nil);
    err = sasl_server_step(client->saslconn,
                           /* NB, distinction of NULL vs "" is *critical* in SASL */
                           args->nil ? NULL : args->data.data_val,
                           args->data.data_len,
                           &serverout,
                           &serveroutlen);
    if (err != SASL_OK &&
        err != SASL_CONTINUE) {
3697 3698
        VIR_ERROR(_("sasl step failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3699 3700
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3701
        goto authfail;
3702 3703 3704
    }

    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
3705 3706
        VIR_ERROR(_("sasl step reply data too long %d"),
                  serveroutlen);
3707 3708
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3709
        goto authfail;
3710 3711 3712 3713
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
3714
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
3715
            remoteDispatchOOMError(rerr);
3716
            goto error;
3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728
        }
        memcpy(ret->data.data_val, serverout, serveroutlen);
    } else {
        ret->data.data_val = NULL;
    }
    ret->nil = serverout ? 0 : 1;
    ret->data.data_len = serveroutlen;

    REMOTE_DEBUG("SASL return data %d bytes, nil; %d", ret->data.data_len, ret->nil);
    if (err == SASL_CONTINUE) {
        ret->complete = 0;
    } else {
3729
        /* Check username whitelist ACL */
3730 3731 3732 3733 3734 3735 3736
        if ((err = remoteSASLCheckAccess(server, client, rerr)) < 0 ||
            (err = remoteSASLCheckSSF(client, rerr)) < 0) {
            if (err == -2)
                goto authdeny;
            else
                goto authfail;
        }
3737

3738 3739 3740 3741 3742
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

3743
    virMutexUnlock(&client->lock);
3744
    return 0;
3745 3746 3747

authfail:
    remoteDispatchAuthError(rerr);
3748 3749 3750 3751 3752
    goto error;

authdeny:
    goto error;

3753
error:
3754
    virMutexUnlock(&client->lock);
3755
    return -1;
3756 3757 3758 3759 3760
}


#else /* HAVE_SASL */
static int
3761
remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED,
3762 3763
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3764
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3765
                            remote_error *rerr,
3766 3767 3768
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED)
{
3769
    VIR_ERROR0(_("client tried unsupported SASL init request"));
3770
    remoteDispatchAuthError(rerr);
3771 3772 3773 3774
    return -1;
}

static int
3775
remoteDispatchAuthSaslStart (struct qemud_server *server ATTRIBUTE_UNUSED,
3776 3777
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn ATTRIBUTE_UNUSED,
3778
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
3779
                             remote_error *rerr,
3780 3781 3782
                             remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED,
                             remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED)
{
3783
    VIR_ERROR0(_("client tried unsupported SASL start request"));
3784
    remoteDispatchAuthError(rerr);
3785 3786 3787 3788
    return -1;
}

static int
3789
remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
3790 3791
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3792
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3793
                            remote_error *rerr,
3794 3795 3796
                            remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED)
{
3797
    VIR_ERROR0(_("client tried unsupported SASL step request"));
3798
    remoteDispatchAuthError(rerr);
3799 3800 3801 3802 3803
    return -1;
}
#endif /* HAVE_SASL */


3804 3805 3806 3807 3808
#if HAVE_POLKIT1
static int
remoteDispatchAuthPolkit (struct qemud_server *server,
                          struct qemud_client *client,
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3809
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3810 3811 3812 3813
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
3814 3815
    pid_t callerPid = -1;
    uid_t callerUid = -1;
3816 3817 3818
    const char *action;
    int status = -1;
    char pidbuf[50];
3819
    char ident[100];
3820 3821
    int rv;

3822 3823
    memset(ident, 0, sizeof ident);

3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);

    action = client->readonly ?
        "org.libvirt.unix.monitor" :
        "org.libvirt.unix.manage";

    const char * const pkcheck [] = {
      PKCHECK_PATH,
      "--action-id", action,
      "--process", pidbuf,
      "--allow-user-interaction",
      NULL
    };

    REMOTE_DEBUG("Start PolicyKit auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_POLKIT) {
        VIR_ERROR0(_("client tried invalid PolicyKit init request"));
        goto authfail;
    }

    if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) {
        VIR_ERROR0(_("cannot get peer socket identity"));
        goto authfail;
    }

    VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);

    rv = snprintf(pidbuf, sizeof pidbuf, "%d", callerPid);
    if (rv < 0 || rv >= sizeof pidbuf) {
        VIR_ERROR(_("Caller PID was too large %d"), callerPid);
3856
        goto authfail;
3857 3858
    }

3859 3860 3861 3862 3863 3864
    rv = snprintf(ident, sizeof ident, "pid:%d,uid:%d", callerPid, callerUid);
    if (rv < 0 || rv >= sizeof ident) {
        VIR_ERROR(_("Caller identity was too large %d:%d"), callerPid, callerUid);
        goto authfail;
    }

3865
    if (virRun(pkcheck, &status) < 0) {
3866
        VIR_ERROR(_("Cannot invoke %s"), PKCHECK_PATH);
3867
        goto authfail;
3868 3869
    }
    if (status != 0) {
3870
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %d"),
3871
                  action, callerPid, callerUid, status);
3872
        goto authdeny;
3873 3874 3875 3876 3877 3878 3879 3880 3881 3882
    }
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d"),
             action, callerPid, callerUid);
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;

    virMutexUnlock(&client->lock);
    return 0;

authfail:
3883 3884 3885 3886 3887 3888
    goto error;

authdeny:
    goto error;

error:
3889 3890 3891 3892 3893
    remoteDispatchAuthError(rerr);
    virMutexUnlock(&client->lock);
    return -1;
}
#elif HAVE_POLKIT0
3894
static int
3895
remoteDispatchAuthPolkit (struct qemud_server *server,
3896
                          struct qemud_client *client,
3897
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3898
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3899
                          remote_error *rerr,
3900 3901 3902 3903 3904
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
    pid_t callerPid;
    uid_t callerUid;
3905 3906 3907 3908 3909 3910
    PolKitCaller *pkcaller = NULL;
    PolKitAction *pkaction = NULL;
    PolKitContext *pkcontext = NULL;
    PolKitError *pkerr = NULL;
    PolKitResult pkresult;
    DBusError err;
3911
    const char *action;
3912 3913 3914
    char ident[100];

    memset(ident, 0, sizeof ident);
3915

3916 3917 3918
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3919 3920

    action = client->readonly ?
3921 3922
        "org.libvirt.unix.monitor" :
        "org.libvirt.unix.manage";
3923 3924 3925

    REMOTE_DEBUG("Start PolicyKit auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_POLKIT) {
3926
        VIR_ERROR0(_("client tried invalid PolicyKit init request"));
3927
        goto authfail;
3928 3929 3930
    }

    if (qemudGetSocketIdentity(client->fd, &callerUid, &callerPid) < 0) {
3931
        VIR_ERROR0(_("cannot get peer socket identity"));
3932
        goto authfail;
3933 3934
    }

3935 3936 3937 3938 3939 3940
    rv = snprintf(ident, sizeof ident, "pid:%d,uid:%d", callerPid, callerUid);
    if (rv < 0 || rv >= sizeof ident) {
        VIR_ERROR(_("Caller identity was too large %d:%d"), callerPid, callerUid);
        goto authfail;
    }

3941
    VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
3942 3943 3944
    dbus_error_init(&err);
    if (!(pkcaller = polkit_caller_new_from_pid(server->sysbus,
                                                callerPid, &err))) {
3945
        VIR_ERROR(_("Failed to lookup policy kit caller: %s"), err.message);
3946
        dbus_error_free(&err);
3947
        goto authfail;
3948
    }
3949

3950
    if (!(pkaction = polkit_action_new())) {
3951
        char ebuf[1024];
3952
        VIR_ERROR(_("Failed to create polkit action %s"),
3953
                  virStrerror(errno, ebuf, sizeof ebuf));
3954
        polkit_caller_unref(pkcaller);
3955
        goto authfail;
3956 3957 3958 3959 3960
    }
    polkit_action_set_action_id(pkaction, action);

    if (!(pkcontext = polkit_context_new()) ||
        !polkit_context_init(pkcontext, &pkerr)) {
3961
        char ebuf[1024];
3962
        VIR_ERROR(_("Failed to create polkit context %s"),
3963
                  (pkerr ? polkit_error_get_error_message(pkerr)
3964
                   : virStrerror(errno, ebuf, sizeof ebuf)));
3965 3966 3967 3968 3969
        if (pkerr)
            polkit_error_free(pkerr);
        polkit_caller_unref(pkcaller);
        polkit_action_unref(pkaction);
        dbus_error_free(&err);
3970
        goto authfail;
3971
    }
3972

3973
# if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
3974 3975 3976 3977 3978 3979
    pkresult = polkit_context_is_caller_authorized(pkcontext,
                                                   pkaction,
                                                   pkcaller,
                                                   0,
                                                   &pkerr);
    if (pkerr && polkit_error_is_set(pkerr)) {
3980 3981 3982
        VIR_ERROR(_("Policy kit failed to check authorization %d %s"),
                  polkit_error_get_error_code(pkerr),
                  polkit_error_get_error_message(pkerr));
3983
        goto authfail;
3984
    }
3985
# else
3986 3987 3988
    pkresult = polkit_context_can_caller_do_action(pkcontext,
                                                   pkaction,
                                                   pkcaller);
3989
# endif
3990 3991 3992 3993
    polkit_context_unref(pkcontext);
    polkit_caller_unref(pkcaller);
    polkit_action_unref(pkaction);
    if (pkresult != POLKIT_RESULT_YES) {
3994
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %s"),
3995 3996
                  action, callerPid, callerUid,
                  polkit_result_to_string_representation(pkresult));
3997
        goto authdeny;
3998
    }
3999
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d, result %s"),
4000 4001 4002 4003
             action, callerPid, callerUid,
             polkit_result_to_string_representation(pkresult));
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;
4004

4005
    virMutexUnlock(&client->lock);
4006
    return 0;
4007 4008

authfail:
4009 4010 4011 4012 4013 4014
    goto error;

authdeny:
    goto error;

error:
4015
    remoteDispatchAuthError(rerr);
4016
    virMutexUnlock(&client->lock);
4017
    return -1;
4018 4019
}

4020
#else /* !HAVE_POLKIT0 & !HAVE_POLKIT1*/
4021 4022

static int
4023
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
4024
                          struct qemud_client *client ATTRIBUTE_UNUSED,
4025
                          virConnectPtr conn ATTRIBUTE_UNUSED,
4026
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
4027 4028 4029
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED)
4030
{
4031
    VIR_ERROR0(_("client tried unsupported PolicyKit init request"));
4032
    remoteDispatchAuthError(rerr);
4033 4034
    return -1;
}
4035
#endif /* HAVE_POLKIT1 */
4036

4037 4038 4039 4040 4041 4042 4043 4044

/***************************************************************
 *     STORAGE POOL APIS
 ***************************************************************/


static int
remoteDispatchListDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
4045 4046
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4047
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4048
                                       remote_error *rerr,
4049 4050 4051 4052 4053
                                       remote_list_defined_storage_pools_args *args,
                                       remote_list_defined_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
4054 4055
        remoteDispatchFormatError (rerr, "%s",
                            _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
4056
        return -1;
4057 4058 4059
    }

    /* Allocate return buffer. */
4060
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
4061 4062
        remoteDispatchOOMError(rerr);
        return -1;
4063
    }
4064 4065

    ret->names.names_len =
4066
        virConnectListDefinedStoragePools (conn,
4067 4068 4069
                                           ret->names.names_val, args->maxnames);
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
4070
        remoteDispatchConnError(rerr, conn);
4071 4072
        return -1;
    }
4073 4074 4075 4076 4077 4078

    return 0;
}

static int
remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
4079 4080
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4081
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4082
                                remote_error *rerr,
4083 4084 4085 4086 4087
                                remote_list_storage_pools_args *args,
                                remote_list_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
4088 4089 4090
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX"));
        return -1;
4091 4092 4093
    }

    /* Allocate return buffer. */
4094
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
4095 4096
        remoteDispatchOOMError(rerr);
        return -1;
4097
    }
4098 4099

    ret->names.names_len =
4100
        virConnectListStoragePools (conn,
4101
                                ret->names.names_val, args->maxnames);
4102 4103
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
4104
        remoteDispatchConnError(rerr, conn);
4105 4106
        return -1;
    }
4107 4108 4109 4110

    return 0;
}

4111 4112
static int
remoteDispatchFindStoragePoolSources (struct qemud_server *server ATTRIBUTE_UNUSED,
4113 4114
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4115
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4116
                                      remote_error *rerr,
4117 4118 4119 4120
                                      remote_find_storage_pool_sources_args *args,
                                      remote_find_storage_pool_sources_ret *ret)
{
    ret->xml =
4121
        virConnectFindStoragePoolSources (conn,
4122 4123 4124
                                          args->type,
                                          args->srcSpec ? *args->srcSpec : NULL,
                                          args->flags);
4125
    if (ret->xml == NULL) {
4126
        remoteDispatchConnError(rerr, conn);
4127
        return -1;
4128
    }
4129 4130 4131 4132 4133

    return 0;
}


4134 4135
static int
remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
4136 4137
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4138
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4139
                                 remote_error *rerr,
4140 4141 4142 4143 4144
                                 remote_storage_pool_create_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4145
    pool = get_nonnull_storage_pool (conn, args->pool);
4146
    if (pool == NULL) {
4147
        remoteDispatchConnError(rerr, conn);
4148
        return -1;
4149 4150 4151 4152
    }

    if (virStoragePoolCreate (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
4153
        remoteDispatchConnError(rerr, conn);
4154 4155 4156 4157 4158 4159 4160 4161
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4162 4163
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
4164
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
4165
                                    remote_error *rerr,
4166 4167 4168 4169 4170
                                    remote_storage_pool_create_xml_args *args,
                                    remote_storage_pool_create_xml_ret *ret)
{
    virStoragePoolPtr pool;

4171
    pool = virStoragePoolCreateXML (conn, args->xml, args->flags);
4172
    if (pool == NULL) {
4173
        remoteDispatchConnError(rerr, conn);
4174 4175
        return -1;
    }
4176 4177 4178 4179 4180 4181 4182 4183

    make_nonnull_storage_pool (&ret->pool, pool);
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4184 4185
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
4186
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
4187
                                    remote_error *rerr,
4188 4189 4190 4191 4192
                                    remote_storage_pool_define_xml_args *args,
                                    remote_storage_pool_define_xml_ret *ret)
{
    virStoragePoolPtr pool;

4193
    pool = virStoragePoolDefineXML (conn, args->xml, args->flags);
4194
    if (pool == NULL) {
4195
        remoteDispatchConnError(rerr, conn);
4196 4197
        return -1;
    }
4198 4199 4200 4201 4202 4203 4204 4205

    make_nonnull_storage_pool (&ret->pool, pool);
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolBuild (struct qemud_server *server ATTRIBUTE_UNUSED,
4206 4207
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4208
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4209 4210 4211
                                remote_error *rerr,
                                remote_storage_pool_build_args *args,
                                void *ret ATTRIBUTE_UNUSED)
4212 4213 4214
{
    virStoragePoolPtr pool;

4215
    pool = get_nonnull_storage_pool (conn, args->pool);
4216
    if (pool == NULL) {
4217
        remoteDispatchConnError(rerr, conn);
4218
        return -1;
4219 4220 4221 4222
    }

    if (virStoragePoolBuild (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
4223
        remoteDispatchConnError(rerr, conn);
4224 4225 4226 4227 4228 4229 4230 4231 4232
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
4233 4234
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4235
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4236
                                  remote_error *rerr,
4237 4238 4239 4240 4241
                                  remote_storage_pool_destroy_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4242
    pool = get_nonnull_storage_pool (conn, args->pool);
4243
    if (pool == NULL) {
4244
        remoteDispatchConnError(rerr, conn);
4245
        return -1;
4246 4247 4248 4249
    }

    if (virStoragePoolDestroy (pool) == -1) {
        virStoragePoolFree(pool);
4250
        remoteDispatchConnError(rerr, conn);
4251 4252 4253 4254 4255 4256 4257 4258
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
4259 4260
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4261
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4262
                                 remote_error *rerr,
4263 4264 4265 4266 4267
                                 remote_storage_pool_delete_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4268
    pool = get_nonnull_storage_pool (conn, args->pool);
4269
    if (pool == NULL) {
4270
        remoteDispatchConnError(rerr, conn);
4271
        return -1;
4272 4273 4274 4275
    }

    if (virStoragePoolDelete (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
4276
        remoteDispatchConnError(rerr, conn);
4277 4278 4279 4280 4281 4282 4283 4284
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolRefresh (struct qemud_server *server ATTRIBUTE_UNUSED,
4285 4286
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4287
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4288
                                  remote_error *rerr,
4289 4290 4291 4292 4293
                                  remote_storage_pool_refresh_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4294
    pool = get_nonnull_storage_pool (conn, args->pool);
4295
    if (pool == NULL) {
4296
        remoteDispatchConnError(rerr, conn);
4297
        return -1;
4298 4299 4300 4301
    }

    if (virStoragePoolRefresh (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
4302
        remoteDispatchConnError(rerr, conn);
4303 4304 4305 4306 4307 4308 4309 4310
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
4311 4312
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4313
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4314
                                  remote_error *rerr,
4315 4316 4317 4318 4319 4320
                                  remote_storage_pool_get_info_args *args,
                                  remote_storage_pool_get_info_ret *ret)
{
    virStoragePoolPtr pool;
    virStoragePoolInfo info;

4321
    pool = get_nonnull_storage_pool (conn, args->pool);
4322
    if (pool == NULL) {
4323
        remoteDispatchConnError(rerr, conn);
4324
        return -1;
4325 4326 4327 4328
    }

    if (virStoragePoolGetInfo (pool, &info) == -1) {
        virStoragePoolFree(pool);
4329
        remoteDispatchConnError(rerr, conn);
4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344
        return -1;
    }

    ret->state = info.state;
    ret->capacity = info.capacity;
    ret->allocation = info.allocation;
    ret->available = info.available;

    virStoragePoolFree(pool);

    return 0;
}

static int
remoteDispatchStoragePoolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4345 4346
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4347
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4348
                                  remote_error *rerr,
4349 4350 4351 4352 4353
                                  remote_storage_pool_dump_xml_args *args,
                                  remote_storage_pool_dump_xml_ret *ret)
{
    virStoragePoolPtr pool;

4354
    pool = get_nonnull_storage_pool (conn, args->pool);
4355
    if (pool == NULL) {
4356
        remoteDispatchConnError(rerr, conn);
4357
        return -1;
4358 4359 4360 4361 4362 4363
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStoragePoolGetXMLDesc (pool, args->flags);
    if (!ret->xml) {
        virStoragePoolFree(pool);
4364
        remoteDispatchConnError(rerr, conn);
4365 4366 4367 4368 4369 4370 4371 4372
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
4373 4374
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4375
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4376
                                       remote_error *rerr,
4377 4378 4379 4380 4381
                                       remote_storage_pool_get_autostart_args *args,
                                       remote_storage_pool_get_autostart_ret *ret)
{
    virStoragePoolPtr pool;

4382
    pool = get_nonnull_storage_pool (conn, args->pool);
4383
    if (pool == NULL) {
4384
        remoteDispatchConnError(rerr, conn);
4385
        return -1;
4386 4387 4388 4389
    }

    if (virStoragePoolGetAutostart (pool, &ret->autostart) == -1) {
        virStoragePoolFree(pool);
4390
        remoteDispatchConnError(rerr, conn);
4391 4392 4393 4394 4395 4396 4397 4398 4399
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4400 4401
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4402
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4403
                                       remote_error *rerr,
4404 4405 4406 4407 4408
                                       remote_storage_pool_lookup_by_name_args *args,
                                       remote_storage_pool_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;

4409
    pool = virStoragePoolLookupByName (conn, args->name);
4410
    if (pool == NULL) {
4411
        remoteDispatchConnError(rerr, conn);
4412 4413
        return -1;
    }
4414 4415 4416 4417 4418 4419 4420 4421

    make_nonnull_storage_pool (&ret->pool, pool);
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
4422 4423
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4424
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4425
                                       remote_error *rerr,
4426 4427 4428 4429 4430
                                       remote_storage_pool_lookup_by_uuid_args *args,
                                       remote_storage_pool_lookup_by_uuid_ret *ret)
{
    virStoragePoolPtr pool;

4431
    pool = virStoragePoolLookupByUUID (conn, (unsigned char *) args->uuid);
4432
    if (pool == NULL) {
4433
        remoteDispatchConnError(rerr, conn);
4434 4435
        return -1;
    }
4436 4437 4438 4439 4440 4441 4442 4443

    make_nonnull_storage_pool (&ret->pool, pool);
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server ATTRIBUTE_UNUSED,
4444 4445
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
4446
                                         remote_message_header *hdr ATTRIBUTE_UNUSED,
4447
                                         remote_error *rerr,
4448 4449 4450 4451 4452 4453
                                         remote_storage_pool_lookup_by_volume_args *args,
                                         remote_storage_pool_lookup_by_volume_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4454
    vol = get_nonnull_storage_vol (conn, args->vol);
4455
    if (vol == NULL) {
4456
        remoteDispatchConnError(rerr, conn);
4457 4458
        return -1;
    }
4459 4460 4461

    pool = virStoragePoolLookupByVolume (vol);
    virStorageVolFree(vol);
4462
    if (pool == NULL) {
4463
        remoteDispatchConnError(rerr, conn);
4464 4465
        return -1;
    }
4466 4467 4468 4469 4470 4471 4472 4473

    make_nonnull_storage_pool (&ret->pool, pool);
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
4474 4475
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4476
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4477
                                       remote_error *rerr,
4478 4479 4480 4481 4482
                                       remote_storage_pool_set_autostart_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4483
    pool = get_nonnull_storage_pool (conn, args->pool);
4484
    if (pool == NULL) {
4485
        remoteDispatchConnError(rerr, conn);
4486
        return -1;
4487 4488 4489 4490
    }

    if (virStoragePoolSetAutostart (pool, args->autostart) == -1) {
        virStoragePoolFree(pool);
4491
        remoteDispatchConnError(rerr, conn);
4492 4493 4494 4495 4496 4497 4498 4499
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
4500 4501
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4502
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4503
                                   remote_error *rerr,
4504 4505 4506 4507 4508
                                   remote_storage_pool_undefine_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4509
    pool = get_nonnull_storage_pool (conn, args->pool);
4510
    if (pool == NULL) {
4511
        remoteDispatchConnError(rerr, conn);
4512
        return -1;
4513 4514 4515 4516
    }

    if (virStoragePoolUndefine (pool) == -1) {
        virStoragePoolFree(pool);
4517
        remoteDispatchConnError(rerr, conn);
4518 4519 4520 4521 4522 4523 4524 4525
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchNumOfStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
4526 4527
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4528
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4529
                                 remote_error *rerr,
4530 4531 4532 4533
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_num_of_storage_pools_ret *ret)
{

4534
    ret->num = virConnectNumOfStoragePools (conn);
4535
    if (ret->num == -1) {
4536
        remoteDispatchConnError(rerr, conn);
4537 4538
        return -1;
    }
4539 4540 4541 4542 4543 4544

    return 0;
}

static int
remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
4545 4546
                                        struct qemud_client *client ATTRIBUTE_UNUSED,
                                        virConnectPtr conn,
4547
                                        remote_message_header *hdr ATTRIBUTE_UNUSED,
4548
                                        remote_error *rerr,
4549 4550 4551 4552
                                        void *args ATTRIBUTE_UNUSED,
                                        remote_num_of_defined_storage_pools_ret *ret)
{

4553
    ret->num = virConnectNumOfDefinedStoragePools (conn);
4554
    if (ret->num == -1) {
4555
        remoteDispatchConnError(rerr, conn);
4556 4557
        return -1;
    }
4558 4559 4560 4561 4562 4563

    return 0;
}

static int
remoteDispatchStoragePoolListVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
4564 4565
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4566
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4567
                                      remote_error *rerr,
4568 4569 4570 4571 4572 4573
                                      remote_storage_pool_list_volumes_args *args,
                                      remote_storage_pool_list_volumes_ret *ret)
{
    virStoragePoolPtr pool;

    if (args->maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) {
4574 4575 4576
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX"));
        return -1;
4577 4578
    }

4579
    pool = get_nonnull_storage_pool (conn, args->pool);
4580
    if (pool == NULL) {
4581
        remoteDispatchConnError(rerr, conn);
4582
        return -1;
4583 4584 4585
    }

    /* Allocate return buffer. */
4586 4587
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        virStoragePoolFree(pool);
4588 4589
        remoteDispatchOOMError(rerr);
        return -1;
4590
    }
4591 4592 4593 4594 4595

    ret->names.names_len =
        virStoragePoolListVolumes (pool,
                                   ret->names.names_val, args->maxnames);
    virStoragePoolFree(pool);
4596 4597
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
4598
        remoteDispatchConnError(rerr, conn);
4599 4600
        return -1;
    }
4601 4602 4603 4604 4605 4606 4607

    return 0;
}


static int
remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
4608 4609
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4610
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4611
                                       remote_error *rerr,
4612 4613 4614 4615 4616
                                       remote_storage_pool_num_of_volumes_args *args,
                                       remote_storage_pool_num_of_volumes_ret *ret)
{
    virStoragePoolPtr pool;

4617
    pool = get_nonnull_storage_pool (conn, args->pool);
4618
    if (pool == NULL) {
4619
        remoteDispatchConnError(rerr, conn);
4620
        return -1;
4621 4622 4623 4624
    }

    ret->num = virStoragePoolNumOfVolumes (pool);
    virStoragePoolFree(pool);
4625
    if (ret->num == -1) {
4626
        remoteDispatchConnError(rerr, conn);
4627 4628
        return -1;
    }
4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641

    return 0;
}


/***************************************************************
 *     STORAGE VOL APIS
 ***************************************************************/



static int
remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4642 4643
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4644
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4645
                                   remote_error *rerr,
4646 4647 4648 4649 4650 4651
                                   remote_storage_vol_create_xml_args *args,
                                   remote_storage_vol_create_xml_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4652
    pool = get_nonnull_storage_pool (conn, args->pool);
4653
    if (pool == NULL) {
4654
        remoteDispatchConnError(rerr, conn);
4655
        return -1;
4656 4657 4658 4659
    }

    vol = virStorageVolCreateXML (pool, args->xml, args->flags);
    virStoragePoolFree(pool);
4660
    if (vol == NULL) {
4661
        remoteDispatchConnError(rerr, conn);
4662 4663
        return -1;
    }
4664 4665 4666 4667 4668 4669

    make_nonnull_storage_vol (&ret->vol, vol);
    virStorageVolFree(vol);
    return 0;
}

4670 4671 4672 4673
static int
remoteDispatchStorageVolCreateXmlFrom (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4674
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689
                                       remote_error *rerr,
                                       remote_storage_vol_create_xml_from_args *args,
                                       remote_storage_vol_create_xml_from_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr clonevol, newvol;

    pool = get_nonnull_storage_pool (conn, args->pool);
    if (pool == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    clonevol = get_nonnull_storage_vol (conn, args->clonevol);
    if (clonevol == NULL) {
4690
        virStoragePoolFree(pool);
4691 4692 4693 4694 4695 4696
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    newvol = virStorageVolCreateXMLFrom (pool, args->xml, clonevol,
                                         args->flags);
4697 4698
    virStorageVolFree(clonevol);
    virStoragePoolFree(pool);
4699 4700 4701 4702 4703 4704 4705 4706 4707
    if (newvol == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_storage_vol (&ret->vol, newvol);
    virStorageVolFree(newvol);
    return 0;
}
4708 4709 4710

static int
remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
4711 4712
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4713
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4714
                                remote_error *rerr,
4715 4716 4717 4718 4719
                                remote_storage_vol_delete_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virStorageVolPtr vol;

4720
    vol = get_nonnull_storage_vol (conn, args->vol);
4721
    if (vol == NULL) {
4722
        remoteDispatchConnError(rerr, conn);
4723
        return -1;
4724 4725 4726 4727
    }

    if (virStorageVolDelete (vol, args->flags) == -1) {
        virStorageVolFree(vol);
4728
        remoteDispatchConnError(rerr, conn);
4729 4730 4731 4732 4733 4734
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}

4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766
static int
remoteDispatchStorageVolWipe(struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *rerr,
                             remote_storage_vol_wipe_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    int retval = -1;
    virStorageVolPtr vol;

    vol = get_nonnull_storage_vol(conn, args->vol);
    if (vol == NULL) {
        remoteDispatchConnError(rerr, conn);
        goto out;
    }

    if (virStorageVolWipe(vol, args->flags) == -1) {
        remoteDispatchConnError(rerr, conn);
        goto out;
    }

    retval = 0;

out:
    if (vol != NULL) {
        virStorageVolFree(vol);
    }
    return retval;
}

4767 4768
static int
remoteDispatchStorageVolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
4769 4770
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4771
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4772
                                 remote_error *rerr,
4773 4774 4775 4776 4777 4778
                                 remote_storage_vol_get_info_args *args,
                                 remote_storage_vol_get_info_ret *ret)
{
    virStorageVolPtr vol;
    virStorageVolInfo info;

4779
    vol = get_nonnull_storage_vol (conn, args->vol);
4780
    if (vol == NULL) {
4781
        remoteDispatchConnError(rerr, conn);
4782
        return -1;
4783 4784 4785 4786
    }

    if (virStorageVolGetInfo (vol, &info) == -1) {
        virStorageVolFree(vol);
4787
        remoteDispatchConnError(rerr, conn);
4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801
        return -1;
    }

    ret->type = info.type;
    ret->capacity = info.capacity;
    ret->allocation = info.allocation;

    virStorageVolFree(vol);

    return 0;
}

static int
remoteDispatchStorageVolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4802 4803
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4804
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4805
                                 remote_error *rerr,
4806 4807 4808 4809 4810
                                 remote_storage_vol_dump_xml_args *args,
                                 remote_storage_vol_dump_xml_ret *ret)
{
    virStorageVolPtr vol;

4811
    vol = get_nonnull_storage_vol (conn, args->vol);
4812
    if (vol == NULL) {
4813
        remoteDispatchConnError(rerr, conn);
4814
        return -1;
4815 4816 4817 4818 4819 4820
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStorageVolGetXMLDesc (vol, args->flags);
    if (!ret->xml) {
        virStorageVolFree(vol);
4821
        remoteDispatchConnError(rerr, conn);
4822 4823 4824 4825 4826 4827 4828 4829 4830
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolGetPath (struct qemud_server *server ATTRIBUTE_UNUSED,
4831 4832
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4833
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4834
                                 remote_error *rerr,
4835 4836 4837 4838 4839
                                 remote_storage_vol_get_path_args *args,
                                 remote_storage_vol_get_path_ret *ret)
{
    virStorageVolPtr vol;

4840
    vol = get_nonnull_storage_vol (conn, args->vol);
4841
    if (vol == NULL) {
4842
        remoteDispatchConnError(rerr, conn);
4843
        return -1;
4844 4845 4846 4847 4848 4849
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virStorageVolGetPath (vol);
    if (!ret->name) {
        virStorageVolFree(vol);
4850
        remoteDispatchConnError(rerr, conn);
4851 4852 4853 4854 4855 4856 4857 4858 4859
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4860 4861
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4862
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4863
                                      remote_error *rerr,
4864 4865 4866 4867 4868 4869
                                      remote_storage_vol_lookup_by_name_args *args,
                                      remote_storage_vol_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4870
    pool = get_nonnull_storage_pool (conn, args->pool);
4871
    if (pool == NULL) {
4872
        remoteDispatchConnError(rerr, conn);
4873
        return -1;
4874 4875 4876 4877
    }

    vol = virStorageVolLookupByName (pool, args->name);
    virStoragePoolFree(pool);
4878
    if (vol == NULL) {
4879
        remoteDispatchConnError(rerr, conn);
4880 4881
        return -1;
    }
4882 4883 4884 4885 4886 4887 4888 4889

    make_nonnull_storage_vol (&ret->vol, vol);
    virStorageVolFree(vol);
    return 0;
}

static int
remoteDispatchStorageVolLookupByKey (struct qemud_server *server ATTRIBUTE_UNUSED,
4890 4891
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
4892
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
4893
                                     remote_error *rerr,
4894 4895 4896 4897 4898
                                     remote_storage_vol_lookup_by_key_args *args,
                                     remote_storage_vol_lookup_by_key_ret *ret)
{
    virStorageVolPtr vol;

4899
    vol = virStorageVolLookupByKey (conn, args->key);
4900
    if (vol == NULL) {
4901
        remoteDispatchConnError(rerr, conn);
4902 4903
        return -1;
    }
4904 4905 4906 4907 4908 4909 4910 4911 4912

    make_nonnull_storage_vol (&ret->vol, vol);
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUSED,
4913 4914
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4915
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4916
                                      remote_error *rerr,
4917 4918 4919 4920 4921
                                      remote_storage_vol_lookup_by_path_args *args,
                                      remote_storage_vol_lookup_by_path_ret *ret)
{
    virStorageVolPtr vol;

4922
    vol = virStorageVolLookupByPath (conn, args->path);
4923
    if (vol == NULL) {
4924
        remoteDispatchConnError(rerr, conn);
4925 4926
        return -1;
    }
4927 4928 4929 4930 4931 4932 4933

    make_nonnull_storage_vol (&ret->vol, vol);
    virStorageVolFree(vol);
    return 0;
}


4934 4935 4936 4937 4938 4939
/***************************************************************
 *     NODE INFO APIS
 **************************************************************/

static int
remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
4940 4941
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4942
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4943
                                remote_error *rerr,
4944 4945 4946 4947 4948
                                remote_node_num_of_devices_args *args,
                                remote_node_num_of_devices_ret *ret)
{
    CHECK_CONN(client);

4949
    ret->num = virNodeNumOfDevices (conn,
4950 4951
                                    args->cap ? *args->cap : NULL,
                                    args->flags);
4952
    if (ret->num == -1) {
4953
        remoteDispatchConnError(rerr, conn);
4954 4955
        return -1;
    }
4956 4957 4958 4959 4960 4961 4962

    return 0;
}


static int
remoteDispatchNodeListDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
4963 4964
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
4965
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
4966
                               remote_error *rerr,
4967 4968 4969 4970 4971 4972
                               remote_node_list_devices_args *args,
                               remote_node_list_devices_ret *ret)
{
    CHECK_CONN(client);

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
4973 4974 4975
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
4976 4977 4978 4979
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
4980 4981
        remoteDispatchOOMError(rerr);
        return -1;
4982 4983 4984
    }

    ret->names.names_len =
4985
        virNodeListDevices (conn,
4986 4987 4988
                            args->cap ? *args->cap : NULL,
                            ret->names.names_val, args->maxnames, args->flags);
    if (ret->names.names_len == -1) {
4989
        remoteDispatchConnError(rerr, conn);
4990 4991 4992 4993 4994 4995 4996 4997 4998 4999
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
5000 5001
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
5002
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
5003
                                      remote_error *rerr,
5004 5005 5006 5007 5008 5009 5010
                                      remote_node_device_lookup_by_name_args *args,
                                      remote_node_device_lookup_by_name_ret *ret)
{
    virNodeDevicePtr dev;

    CHECK_CONN(client);

5011
    dev = virNodeDeviceLookupByName (conn, args->name);
5012
    if (dev == NULL) {
5013
        remoteDispatchConnError(rerr, conn);
5014 5015
        return -1;
    }
5016 5017 5018 5019 5020 5021 5022 5023 5024

    make_nonnull_node_device (&ret->dev, dev);
    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
5025 5026
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
5027
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
5028
                                 remote_error *rerr,
5029 5030 5031 5032 5033 5034
                                 remote_node_device_dump_xml_args *args,
                                 remote_node_device_dump_xml_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

5035
    dev = virNodeDeviceLookupByName(conn, args->name);
5036
    if (dev == NULL) {
5037
        remoteDispatchConnError(rerr, conn);
5038
        return -1;
5039 5040 5041 5042 5043
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags);
    if (!ret->xml) {
5044
        remoteDispatchConnError(rerr, conn);
5045 5046 5047 5048 5049 5050 5051 5052 5053 5054
        virNodeDeviceFree(dev);
        return -1;
    }
    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED,
5055 5056
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
5057
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
5058
                                   remote_error *rerr,
5059 5060 5061 5062 5063 5064 5065
                                   remote_node_device_get_parent_args *args,
                                   remote_node_device_get_parent_ret *ret)
{
    virNodeDevicePtr dev;
    const char *parent;
    CHECK_CONN(client);

5066
    dev = virNodeDeviceLookupByName(conn, args->name);
5067
    if (dev == NULL) {
5068
        remoteDispatchConnError(rerr, conn);
5069
        return -1;
5070 5071 5072 5073 5074 5075 5076 5077 5078 5079
    }

    parent = virNodeDeviceGetParent(dev);

    if (parent == NULL) {
        ret->parent = NULL;
    } else {
        /* remoteDispatchClientRequest will free this. */
        char **parent_p;
        if (VIR_ALLOC(parent_p) < 0) {
5080
            virNodeDeviceFree(dev);
5081 5082
            remoteDispatchOOMError(rerr);
            return -1;
5083 5084 5085
        }
        *parent_p = strdup(parent);
        if (*parent_p == NULL) {
5086
            virNodeDeviceFree(dev);
5087 5088
            remoteDispatchOOMError(rerr);
            return -1;
5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099
        }
        ret->parent = parent_p;
    }

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
5100 5101
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
5102
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
5103
                                   remote_error *rerr,
5104 5105 5106 5107 5108 5109
                                   remote_node_device_num_of_caps_args *args,
                                   remote_node_device_num_of_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

5110
    dev = virNodeDeviceLookupByName(conn, args->name);
5111
    if (dev == NULL) {
5112
        remoteDispatchConnError(rerr, conn);
5113
        return -1;
5114 5115 5116
    }

    ret->num = virNodeDeviceNumOfCaps(dev);
5117
    if (ret->num < 0) {
5118
        virNodeDeviceFree(dev);
5119
        remoteDispatchConnError(rerr, conn);
5120 5121
        return -1;
    }
5122 5123 5124 5125 5126 5127 5128 5129

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
5130 5131
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
5132
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
5133
                                  remote_error *rerr,
5134 5135 5136 5137 5138 5139
                                  remote_node_device_list_caps_args *args,
                                  remote_node_device_list_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

5140
    dev = virNodeDeviceLookupByName(conn, args->name);
5141
    if (dev == NULL) {
5142
        remoteDispatchConnError(rerr, conn);
5143
        return -1;
5144 5145 5146
    }

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
5147
        virNodeDeviceFree(dev);
5148 5149 5150
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
5151 5152 5153 5154
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
5155
        virNodeDeviceFree(dev);
5156 5157
        remoteDispatchOOMError(rerr);
        return -1;
5158 5159 5160 5161 5162 5163
    }

    ret->names.names_len =
        virNodeDeviceListCaps (dev, ret->names.names_val,
                               args->maxnames);
    if (ret->names.names_len == -1) {
5164
        virNodeDeviceFree(dev);
5165
        remoteDispatchConnError(rerr, conn);
5166 5167 5168 5169
        VIR_FREE(ret->names.names_val);
        return -1;
    }

5170
    virNodeDeviceFree(dev);
5171 5172 5173 5174
    return 0;
}


5175 5176 5177 5178
static int
remoteDispatchNodeDeviceDettach (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
5179
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
5180 5181 5182 5183 5184 5185 5186 5187 5188
                                 remote_error *rerr,
                                 remote_node_device_dettach_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5189
        remoteDispatchConnError(rerr, conn);
5190 5191 5192 5193
        return -1;
    }

    if (virNodeDeviceDettach(dev) == -1) {
5194
        virNodeDeviceFree(dev);
5195 5196 5197 5198
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

5199
    virNodeDeviceFree(dev);
5200 5201 5202 5203 5204 5205 5206 5207
    return 0;
}


static int
remoteDispatchNodeDeviceReAttach (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
5208
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
5209 5210 5211 5212 5213 5214 5215 5216 5217
                                  remote_error *rerr,
                                  remote_node_device_re_attach_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5218
        remoteDispatchConnError(rerr, conn);
5219 5220 5221 5222
        return -1;
    }

    if (virNodeDeviceReAttach(dev) == -1) {
5223
        virNodeDeviceFree(dev);
5224 5225 5226 5227
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

5228
    virNodeDeviceFree(dev);
5229 5230 5231 5232 5233 5234 5235 5236
    return 0;
}


static int
remoteDispatchNodeDeviceReset (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
5237
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
5238 5239 5240 5241 5242 5243 5244 5245 5246
                               remote_error *rerr,
                               remote_node_device_reset_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5247
        remoteDispatchConnError(rerr, conn);
5248 5249 5250 5251
        return -1;
    }

    if (virNodeDeviceReset(dev) == -1) {
5252
        virNodeDeviceFree(dev);
5253 5254 5255 5256
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

5257
    virNodeDeviceFree(dev);
5258 5259 5260 5261
    return 0;
}


5262 5263 5264 5265
static int
remoteDispatchNodeDeviceCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
5266
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289
                                  remote_error *rerr,
                                  remote_node_device_create_xml_args *args,
                                  remote_node_device_create_xml_ret *ret)
{
    virNodeDevicePtr dev;

    dev = virNodeDeviceCreateXML (conn, args->xml_desc, args->flags);
    if (dev == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_node_device (&ret->dev, dev);
    virNodeDeviceFree(dev);

    return 0;
}


static int
remoteDispatchNodeDeviceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
5290
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
5291 5292 5293 5294 5295 5296 5297 5298
                                remote_error *rerr,
                                remote_node_device_destroy_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5299
        remoteDispatchConnError(rerr, conn);
5300 5301 5302 5303
        return -1;
    }

    if (virNodeDeviceDestroy(dev) == -1) {
5304
        virNodeDeviceFree(dev);
5305 5306 5307 5308
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

5309
    virNodeDeviceFree(dev);
5310 5311 5312 5313
    return 0;
}


5314 5315 5316 5317 5318 5319

/***************************
 * Register / deregister events
 ***************************/
static int
remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED,
5320 5321
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
5322
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
5323
                                    remote_error *rerr ATTRIBUTE_UNUSED,
5324 5325 5326 5327
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_domain_events_register_ret *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);
5328 5329 5330 5331 5332 5333
    int callbackID;

    if (client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] != -1) {
        remoteDispatchFormatError(rerr, _("domain event %d already registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE);
        return -1;
    }
5334

5335 5336 5337 5338 5339
    if ((callbackID = virConnectDomainEventRegisterAny(conn,
                                                       NULL,
                                                       VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                                       VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
                                                       client, NULL)) < 0) {
5340 5341 5342
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
5343

5344
    client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = callbackID;
5345

5346 5347 5348 5349 5350
    return 0;
}

static int
remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED,
5351 5352
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
5353
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
5354
                                      remote_error *rerr ATTRIBUTE_UNUSED,
5355 5356 5357 5358 5359
                                      void *args ATTRIBUTE_UNUSED,
                                      remote_domain_events_deregister_ret *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);

5360 5361
    if (client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] == -1) {
        remoteDispatchFormatError(rerr, _("domain event %d not registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE);
5362 5363
        return -1;
    }
5364

5365 5366 5367 5368 5369
    if (virConnectDomainEventDeregisterAny(conn,
                                           client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE]) < 0) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
5370

5371
    client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = -1;
5372 5373 5374 5375 5376
    return 0;
}

static void
remoteDispatchDomainEventSend (struct qemud_client *client,
5377 5378 5379
                               int procnr,
                               xdrproc_t proc,
                               void *data)
5380
{
5381
    struct qemud_client_message *msg = NULL;
5382
    XDR xdr;
5383
    unsigned int len;
5384

5385
    if (VIR_ALLOC(msg) < 0)
5386 5387
        return;

5388 5389
    msg->hdr.prog = REMOTE_PROGRAM;
    msg->hdr.vers = REMOTE_PROTOCOL_VERSION;
5390
    msg->hdr.proc = procnr;
5391
    msg->hdr.type = REMOTE_MESSAGE;
5392 5393
    msg->hdr.serial = 1;
    msg->hdr.status = REMOTE_OK;
5394

5395 5396
    if (remoteEncodeClientMessageHeader(msg) < 0)
        goto error;
5397

5398 5399
    /* Serialise the return header and event. */
    xdrmem_create (&xdr,
5400 5401
                   msg->buffer,
                   msg->bufferLength,
5402
                   XDR_ENCODE);
5403

5404 5405
    /* Skip over the header we just wrote */
    if (xdr_setpos (&xdr, msg->bufferOffset) == 0)
5406
        goto xdr_error;
5407

5408 5409
    if (!(proc)(&xdr, data)) {
        VIR_WARN("Failed to serialize domain event %d", procnr);
5410
        goto xdr_error;
5411
    }
5412

5413 5414
    /* Update length word to include payload*/
    len = msg->bufferOffset = xdr_getpos (&xdr);
5415 5416
    if (xdr_setpos (&xdr, 0) == 0)
        goto xdr_error;
5417

5418 5419
    if (!xdr_u_int (&xdr, &len))
        goto xdr_error;
5420 5421

    /* Send it. */
5422 5423 5424 5425
    msg->async = 1;
    msg->bufferLength = len;
    msg->bufferOffset = 0;
    qemudClientMessageQueuePush(&client->tx, msg);
5426
    qemudUpdateClientEvent(client);
5427 5428 5429 5430 5431 5432 5433 5434

    xdr_destroy (&xdr);
    return;

xdr_error:
    xdr_destroy(&xdr);
error:
    VIR_FREE(msg);
5435
}
5436

5437 5438 5439
static int
remoteDispatchNumOfSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
                            struct qemud_client *client ATTRIBUTE_UNUSED,
5440 5441 5442
                            virConnectPtr conn,
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                            remote_error *err,
5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457
                            void *args ATTRIBUTE_UNUSED,
                            remote_num_of_secrets_ret *ret)
{
    ret->num = virConnectNumOfSecrets (conn);
    if (ret->num == -1) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

    return 0;
}

static int
remoteDispatchListSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
                           struct qemud_client *client ATTRIBUTE_UNUSED,
5458 5459 5460
                           virConnectPtr conn,
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                           remote_error *err,
5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488
                           remote_list_secrets_args *args,
                           remote_list_secrets_ret *ret)
{
    if (args->maxuuids > REMOTE_SECRET_UUID_LIST_MAX) {
        remoteDispatchFormatError (err, "%s",
                                   _("maxuuids > REMOTE_SECRET_UUID_LIST_MAX"));
        return -1;
    }

    if (VIR_ALLOC_N (ret->uuids.uuids_val, args->maxuuids) < 0) {
        remoteDispatchOOMError (err);
        return -1;
    }

    ret->uuids.uuids_len = virConnectListSecrets (conn, ret->uuids.uuids_val,
                                                  args->maxuuids);
    if (ret->uuids.uuids_len == -1) {
        VIR_FREE (ret->uuids.uuids_val);
        remoteDispatchConnError (err, conn);
        return -1;
    }

    return 0;
}

static int
remoteDispatchSecretDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
5489 5490 5491
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *err,
5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510
                               remote_secret_define_xml_args *args,
                               remote_secret_define_xml_ret *ret)
{
    virSecretPtr secret;

    secret = virSecretDefineXML (conn, args->xml, args->flags);
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

    make_nonnull_secret (&ret->secret, secret);
    virSecretFree (secret);
    return 0;
}

static int
remoteDispatchSecretGetValue (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
5511 5512 5513
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542
                              remote_secret_get_value_args *args,
                              remote_secret_get_value_ret *ret)
{
    virSecretPtr secret;
    size_t value_size;
    unsigned char *value;

    secret = get_nonnull_secret (conn, args->secret);
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

    value = virSecretGetValue (secret, &value_size, args->flags);
    if (value == NULL) {
        remoteDispatchConnError (err, conn);
        virSecretFree(secret);
        return -1;
    }

    ret->value.value_len = value_size;
    ret->value.value_val = (char *)value;
    virSecretFree(secret);
    return 0;
}

static int
remoteDispatchSecretGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
5543 5544 5545
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *err,
5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566
                                remote_secret_get_xml_desc_args *args,
                                remote_secret_get_xml_desc_ret *ret)
{
    virSecretPtr secret;

    secret = get_nonnull_secret (conn, args->secret);
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }
    ret->xml = virSecretGetXMLDesc (secret, args->flags);
    if (ret->xml == NULL) {
        remoteDispatchConnError (err, conn);
        virSecretFree(secret);
        return -1;
    }
    virSecretFree(secret);
    return 0;
}

static int
5567 5568
remoteDispatchSecretLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
5569 5570 5571
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *err,
5572 5573
                                  remote_secret_lookup_by_uuid_args *args,
                                  remote_secret_lookup_by_uuid_ret *ret)
5574 5575 5576
{
    virSecretPtr secret;

5577
    secret = virSecretLookupByUUID (conn, (unsigned char *)args->uuid);
5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

    make_nonnull_secret (&ret->secret, secret);
    virSecretFree (secret);
    return 0;
}

static int
remoteDispatchSecretSetValue (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
5591 5592 5593
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617
                              remote_secret_set_value_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virSecretPtr secret;

    secret = get_nonnull_secret (conn, args->secret);
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }
    if (virSecretSetValue (secret, (const unsigned char *)args->value.value_val,
                           args->value.value_len, args->flags) < 0) {
        remoteDispatchConnError (err, conn);
        virSecretFree(secret);
        return -1;
    }

    virSecretFree(secret);
    return 0;
}

static int
remoteDispatchSecretUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
5618 5619 5620
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640
                              remote_secret_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virSecretPtr secret;

    secret = get_nonnull_secret (conn, args->secret);
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }
    if (virSecretUndefine (secret) < 0) {
        remoteDispatchConnError (err, conn);
        virSecretFree(secret);
        return -1;
    }

    virSecretFree(secret);
    return 0;
}

5641 5642 5643
static int
remoteDispatchSecretLookupByUsage (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
5644 5645 5646
                                   virConnectPtr conn,
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
                                   remote_error *err,
5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662
                                   remote_secret_lookup_by_usage_args *args,
                                   remote_secret_lookup_by_usage_ret *ret)
{
    virSecretPtr secret;

    secret = virSecretLookupByUsage (conn, args->usageType, args->usageID);
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

    make_nonnull_secret (&ret->secret, secret);
    virSecretFree (secret);
    return 0;
}

5663

5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682
static int remoteDispatchDomainIsActive(struct qemud_server *server ATTRIBUTE_UNUSED,
                                        struct qemud_client *client ATTRIBUTE_UNUSED,
                                        virConnectPtr conn,
                                        remote_message_header *hdr ATTRIBUTE_UNUSED,
                                        remote_error *err,
                                        remote_domain_is_active_args *args,
                                        remote_domain_is_active_ret *ret)
{
    virDomainPtr domain;

    domain = get_nonnull_domain(conn, args->dom);
    if (domain == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->active = virDomainIsActive(domain);

    if (ret->active < 0) {
5683
        virDomainFree(domain);
5684 5685 5686 5687
        remoteDispatchConnError(err, conn);
        return -1;
    }

5688
    virDomainFree(domain);
5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710
    return 0;
}

static int remoteDispatchDomainIsPersistent(struct qemud_server *server ATTRIBUTE_UNUSED,
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
                                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                                            remote_error *err,
                                            remote_domain_is_persistent_args *args,
                                            remote_domain_is_persistent_ret *ret)
{
    virDomainPtr domain;

    domain = get_nonnull_domain(conn, args->dom);
    if (domain == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->persistent = virDomainIsPersistent(domain);

    if (ret->persistent < 0) {
5711
        virDomainFree(domain);
5712 5713 5714 5715
        remoteDispatchConnError(err, conn);
        return -1;
    }

5716
    virDomainFree(domain);
5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738
    return 0;
}

static int remoteDispatchInterfaceIsActive(struct qemud_server *server ATTRIBUTE_UNUSED,
                                           struct qemud_client *client ATTRIBUTE_UNUSED,
                                           virConnectPtr conn,
                                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                                           remote_error *err,
                                           remote_interface_is_active_args *args,
                                           remote_interface_is_active_ret *ret)
{
    virInterfacePtr iface;

    iface = get_nonnull_interface(conn, args->iface);
    if (iface == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->active = virInterfaceIsActive(iface);

    if (ret->active < 0) {
5739
        virInterfaceFree(iface);
5740 5741 5742 5743
        remoteDispatchConnError(err, conn);
        return -1;
    }

5744
    virInterfaceFree(iface);
5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766
    return 0;
}

static int remoteDispatchNetworkIsActive(struct qemud_server *server ATTRIBUTE_UNUSED,
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
                                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                                         remote_error *err,
                                         remote_network_is_active_args *args,
                                         remote_network_is_active_ret *ret)
{
    virNetworkPtr network;

    network = get_nonnull_network(conn, args->net);
    if (network == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->active = virNetworkIsActive(network);

    if (ret->active < 0) {
5767
        virNetworkFree(network);
5768 5769 5770 5771
        remoteDispatchConnError(err, conn);
        return -1;
    }

5772
    virNetworkFree(network);
5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794
    return 0;
}

static int remoteDispatchNetworkIsPersistent(struct qemud_server *server ATTRIBUTE_UNUSED,
                                             struct qemud_client *client ATTRIBUTE_UNUSED,
                                             virConnectPtr conn,
                                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                                             remote_error *err,
                                             remote_network_is_persistent_args *args,
                                             remote_network_is_persistent_ret *ret)
{
    virNetworkPtr network;

    network = get_nonnull_network(conn, args->net);
    if (network == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->persistent = virNetworkIsPersistent(network);

    if (ret->persistent < 0) {
5795
        virNetworkFree(network);
5796 5797 5798 5799
        remoteDispatchConnError(err, conn);
        return -1;
    }

5800
    virNetworkFree(network);
5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822
    return 0;
}

static int remoteDispatchStoragePoolIsActive(struct qemud_server *server ATTRIBUTE_UNUSED,
                                             struct qemud_client *client ATTRIBUTE_UNUSED,
                                             virConnectPtr conn,
                                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                                             remote_error *err,
                                             remote_storage_pool_is_active_args *args,
                                             remote_storage_pool_is_active_ret *ret)
{
    virStoragePoolPtr pool;

    pool = get_nonnull_storage_pool(conn, args->pool);
    if (pool == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->active = virStoragePoolIsActive(pool);

    if (ret->active < 0) {
5823
        virStoragePoolFree(pool);
5824 5825 5826 5827
        remoteDispatchConnError(err, conn);
        return -1;
    }

5828
    virStoragePoolFree(pool);
5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850
    return 0;
}

static int remoteDispatchStoragePoolIsPersistent(struct qemud_server *server ATTRIBUTE_UNUSED,
                                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                                 virConnectPtr conn,
                                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                                 remote_error *err,
                                                 remote_storage_pool_is_persistent_args *args,
                                                 remote_storage_pool_is_persistent_ret *ret)
{
    virStoragePoolPtr pool;

    pool = get_nonnull_storage_pool(conn, args->pool);
    if (pool == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->persistent = virStoragePoolIsPersistent(pool);

    if (ret->persistent < 0) {
5851
        virStoragePoolFree(pool);
5852 5853 5854 5855
        remoteDispatchConnError(err, conn);
        return -1;
    }

5856
    virStoragePoolFree(pool);
5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879
    return 0;
}


static int remoteDispatchIsSecure(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *err,
                                  void *args ATTRIBUTE_UNUSED,
                                  remote_is_secure_ret *ret)
{
    ret->secure = virConnectIsSecure(conn);

    if (ret->secure < 0) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    return 0;
}


5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901
static int
remoteDispatchCpuCompare(struct qemud_server *server ATTRIBUTE_UNUSED,
                         struct qemud_client *client ATTRIBUTE_UNUSED,
                         virConnectPtr conn,
                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                         remote_error *err,
                         remote_cpu_compare_args *args,
                         remote_cpu_compare_ret *ret)
{
    int result;

    result = virConnectCompareCPU(conn, args->xml, args->flags);
    if (result == VIR_CPU_COMPARE_ERROR) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->result = result;
    return 0;
}


5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922
static int
remoteDispatchCpuBaseline(struct qemud_server *server ATTRIBUTE_UNUSED,
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
                          remote_error *err,
                          remote_cpu_baseline_args *args,
                          remote_cpu_baseline_ret *ret)
{
    char *cpu;

    cpu = virConnectBaselineCPU(conn,
                                (const char **) args->xmlCPUs.xmlCPUs_val,
                                args->xmlCPUs.xmlCPUs_len,
                                args->flags);
    if (cpu == NULL) {
        remoteDispatchConnError(err, conn);
        return -1;
    }

    ret->cpu = cpu;
5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966

    return 0;
}


static int
remoteDispatchDomainGetJobInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *rerr,
                                remote_domain_get_job_info_args *args,
                                remote_domain_get_job_info_ret *ret)
{
    virDomainPtr dom;
    virDomainJobInfo info;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainGetJobInfo (dom, &info) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

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

    virDomainFree(dom);

5967 5968 5969 5970
    return 0;
}


5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999
static int
remoteDispatchDomainAbortJob (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *rerr,
                              remote_domain_abort_job_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainAbortJob (dom) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    virDomainFree(dom);

    return 0;
}


6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027
static int
remoteDispatchDomainMigrateSetMaxDowntime(struct qemud_server *server ATTRIBUTE_UNUSED,
                                          struct qemud_client *client ATTRIBUTE_UNUSED,
                                          virConnectPtr conn,
                                          remote_message_header *hdr ATTRIBUTE_UNUSED,
                                          remote_error *rerr,
                                          remote_domain_migrate_set_max_downtime_args *args,
                                          void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

    dom = get_nonnull_domain(conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainMigrateSetMaxDowntime(dom, args->downtime, args->flags) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    virDomainFree(dom);

    return 0;
}

C
Chris Lalancette 已提交
6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069
static int
remoteDispatchDomainSnapshotCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_snapshot_create_xml_args *args,
                                       remote_domain_snapshot_create_xml_ret *ret)
{
    virDomainSnapshotPtr snapshot;
    virDomainPtr domain;

    domain = get_nonnull_domain(conn, args->domain);
    if (domain == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    snapshot = virDomainSnapshotCreateXML(domain, args->xml_desc, args->flags);
    if (snapshot == NULL) {
        virDomainFree(domain);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_domain_snapshot(&ret->snap, snapshot);

    virDomainSnapshotFree(snapshot);
    virDomainFree(domain);

    return 0;
}

static int
remoteDispatchDomainSnapshotDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
                                     remote_error *rerr,
                                     remote_domain_snapshot_dump_xml_args *args,
                                     remote_domain_snapshot_dump_xml_ret *ret)
{
6070 6071 6072
    virDomainPtr domain = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    int rc = -1;
C
Chris Lalancette 已提交
6073

6074 6075 6076 6077 6078 6079 6080
    domain = get_nonnull_domain(conn, args->snap.domain);
    if (domain == NULL)
        goto cleanup;

    snapshot = get_nonnull_domain_snapshot(domain, args->snap);
    if (snapshot == NULL)
        goto cleanup;
C
Chris Lalancette 已提交
6081 6082 6083

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virDomainSnapshotGetXMLDesc(snapshot, args->flags);
6084 6085 6086 6087 6088 6089 6090
    if (!ret->xml)
        goto cleanup;

    rc = 0;

cleanup:
    if (snapshot)
C
Chris Lalancette 已提交
6091
        virDomainSnapshotFree(snapshot);
6092 6093 6094
    if (domain)
        virDomainFree(domain);
    if (rc < 0)
C
Chris Lalancette 已提交
6095 6096
        remoteDispatchConnError(rerr, conn);

6097
    return rc;
C
Chris Lalancette 已提交
6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281
}

static int
remoteDispatchDomainSnapshotNum (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_domain_snapshot_num_args *args,
                                 remote_domain_snapshot_num_ret *ret)
{
    virDomainPtr domain;

    domain = get_nonnull_domain(conn, args->domain);
    if (domain == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    ret->num = virDomainSnapshotNum(domain, args->flags);
    if (ret->num == -1) {
        virDomainFree(domain);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    virDomainFree(domain);

    return 0;
}

static int
remoteDispatchDomainSnapshotListNames (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_snapshot_list_names_args *args,
                                       remote_domain_snapshot_list_names_ret *ret)
{
    virDomainPtr domain;

    if (args->nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) {
        remoteDispatchFormatError (rerr, "%s",
                                   _("nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX"));
        return -1;
    }

    domain = get_nonnull_domain(conn, args->domain);
    if (domain == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->nameslen) < 0) {
        virDomainFree(domain);
        remoteDispatchOOMError(rerr);
        return -1;
    }

    ret->names.names_len = virDomainSnapshotListNames(domain,
                                                      ret->names.names_val,
                                                      args->nameslen,
                                                      args->flags);
    if (ret->names.names_len == -1) {
        virDomainFree(domain);
        VIR_FREE(ret->names.names_val);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    virDomainFree(domain);

    return 0;
}

static int
remoteDispatchDomainSnapshotLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
                                          struct qemud_client *client ATTRIBUTE_UNUSED,
                                          virConnectPtr conn,
                                          remote_message_header *hdr ATTRIBUTE_UNUSED,
                                          remote_error *rerr,
                                          remote_domain_snapshot_lookup_by_name_args *args,
                                          remote_domain_snapshot_lookup_by_name_ret *ret)
{
    virDomainSnapshotPtr snapshot;
    virDomainPtr domain;

    domain = get_nonnull_domain(conn, args->domain);
    if (domain == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    snapshot = virDomainSnapshotLookupByName(domain, args->name, args->flags);
    if (snapshot == NULL) {
        virDomainFree(domain);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_domain_snapshot (&ret->snap, snapshot);

    virDomainSnapshotFree(snapshot);
    virDomainFree(domain);

    return 0;
}

static int
remoteDispatchDomainHasCurrentSnapshot(struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_has_current_snapshot_args *args,
                                       remote_domain_has_current_snapshot_ret *ret)
{
    virDomainPtr domain;
    int result;

    domain = get_nonnull_domain(conn, args->domain);
    if (domain == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    result = virDomainHasCurrentSnapshot(domain, args->flags);
    if (result < 0) {
        virDomainFree(domain);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    ret->result = result;

    virDomainFree(domain);

    return 0;
}

static int
remoteDispatchDomainSnapshotCurrent(struct qemud_server *server ATTRIBUTE_UNUSED,
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
                                    remote_error *rerr,
                                    remote_domain_snapshot_current_args *args,
                                    remote_domain_snapshot_current_ret *ret)
{
    virDomainSnapshotPtr snapshot;
    virDomainPtr domain;

    domain = get_nonnull_domain(conn, args->domain);
    if (domain == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    snapshot = virDomainSnapshotCurrent(domain, args->flags);
    if (snapshot == NULL) {
        virDomainFree(domain);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_domain_snapshot(&ret->snap, snapshot);

    virDomainSnapshotFree(snapshot);
    virDomainFree(domain);

    return 0;
}

static int
remoteDispatchDomainRevertToSnapshot (struct qemud_server *server ATTRIBUTE_UNUSED,
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
                                      remote_error *rerr,
                                      remote_domain_revert_to_snapshot_args *args,
                                      void *ret ATTRIBUTE_UNUSED)
{
6282 6283 6284
    virDomainPtr domain = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    int rc = -1;
C
Chris Lalancette 已提交
6285

6286 6287 6288 6289 6290 6291 6292
    domain = get_nonnull_domain(conn, args->snap.domain);
    if (domain == NULL)
        goto cleanup;

    snapshot = get_nonnull_domain_snapshot(domain, args->snap);
    if (snapshot == NULL)
        goto cleanup;
C
Chris Lalancette 已提交
6293

6294 6295 6296 6297 6298 6299 6300
    if (virDomainRevertToSnapshot(snapshot, args->flags) == -1)
        goto cleanup;

    rc = 0;

cleanup:
    if (snapshot)
C
Chris Lalancette 已提交
6301
        virDomainSnapshotFree(snapshot);
6302 6303 6304
    if (domain)
        virDomainFree(domain);
    if (rc < 0)
C
Chris Lalancette 已提交
6305 6306
        remoteDispatchConnError(rerr, conn);

6307
    return rc;
C
Chris Lalancette 已提交
6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318
}

static int
remoteDispatchDomainSnapshotDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
                                    remote_error *rerr,
                                    remote_domain_snapshot_delete_args *args,
                                    void *ret ATTRIBUTE_UNUSED)
{
6319 6320 6321
    virDomainPtr domain = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    int rc = -1;
C
Chris Lalancette 已提交
6322

6323 6324 6325 6326 6327 6328 6329
    domain = get_nonnull_domain(conn, args->snap.domain);
    if (domain == NULL)
        goto cleanup;

    snapshot = get_nonnull_domain_snapshot(domain, args->snap);
    if (snapshot == NULL)
        goto cleanup;
C
Chris Lalancette 已提交
6330

6331 6332 6333 6334 6335 6336 6337
    if (virDomainSnapshotDelete(snapshot, args->flags) == -1)
        goto cleanup;

    rc = 0;

cleanup:
    if (snapshot)
C
Chris Lalancette 已提交
6338
        virDomainSnapshotFree(snapshot);
6339 6340 6341
    if (domain)
        virDomainFree(domain);
    if (rc < 0)
C
Chris Lalancette 已提交
6342 6343
        remoteDispatchConnError(rerr, conn);

6344
    return rc;
C
Chris Lalancette 已提交
6345 6346
}

6347

6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419
static int
remoteDispatchDomainEventsRegisterAny (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr ATTRIBUTE_UNUSED,
                                       remote_domain_events_register_any_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);
    int callbackID;

    if (args->eventID >= VIR_DOMAIN_EVENT_ID_LAST ||
        args->eventID < 0) {
        remoteDispatchFormatError(rerr, _("unsupported event ID %d"), args->eventID);
        return -1;
    }

    if (client->domainEventCallbackID[args->eventID] != -1)  {
        remoteDispatchFormatError(rerr, _("domain event %d already registered"), args->eventID);
        return -1;
    }

    if ((callbackID = virConnectDomainEventRegisterAny(conn,
                                                       NULL,
                                                       args->eventID,
                                                       domainEventCallbacks[args->eventID],
                                                       client, NULL)) < 0) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    client->domainEventCallbackID[args->eventID] = callbackID;

    return 0;
}


static int
remoteDispatchDomainEventsDeregisterAny (struct qemud_server *server ATTRIBUTE_UNUSED,
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
                                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                                         remote_error *rerr ATTRIBUTE_UNUSED,
                                         remote_domain_events_deregister_any_args *args,
                                         void *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);
    int callbackID = -1;

    if (args->eventID >= VIR_DOMAIN_EVENT_ID_LAST ||
        args->eventID < 0) {
        remoteDispatchFormatError(rerr, _("unsupported event ID %d"), args->eventID);
        return -1;
    }

    callbackID = client->domainEventCallbackID[args->eventID];
    if (callbackID < 0) {
        remoteDispatchFormatError(rerr, _("domain event %d not registered"), args->eventID);
        return -1;
    }

    if (virConnectDomainEventDeregisterAny(conn, callbackID) < 0) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    client->domainEventCallbackID[args->eventID] = -1;
    return 0;
}


6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598

static int
remoteDispatchNwfilterLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
                                    remote_error *rerr,
                                    remote_nwfilter_lookup_by_name_args *args,
                                    remote_nwfilter_lookup_by_name_ret *ret)
{
    virNWFilterPtr nwfilter;

    nwfilter = virNWFilterLookupByName (conn, args->name);
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_nwfilter (&ret->nwfilter, nwfilter);
    virNWFilterFree(nwfilter);
    return 0;
}

static int
remoteDispatchNwfilterLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
                                    remote_error *rerr,
                                    remote_nwfilter_lookup_by_uuid_args *args,
                                    remote_nwfilter_lookup_by_uuid_ret *ret)
{
    virNWFilterPtr nwfilter;

    nwfilter = virNWFilterLookupByUUID (conn, (unsigned char *) args->uuid);
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_nwfilter (&ret->nwfilter, nwfilter);
    virNWFilterFree(nwfilter);
    return 0;
}


static int
remoteDispatchNwfilterDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_nwfilter_define_xml_args *args,
                                 remote_nwfilter_define_xml_ret *ret)
{
    virNWFilterPtr nwfilter;

    nwfilter = virNWFilterDefineXML (conn, args->xml);
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_nwfilter (&ret->nwfilter, nwfilter);
    virNWFilterFree(nwfilter);
    return 0;
}


static int
remoteDispatchNwfilterUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *rerr,
                                remote_nwfilter_undefine_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virNWFilterPtr nwfilter;

    nwfilter = get_nonnull_nwfilter (conn, args->nwfilter);
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virNWFilterUndefine (nwfilter) == -1) {
        virNWFilterFree(nwfilter);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    virNWFilterFree(nwfilter);
    return 0;
}

static int
remoteDispatchListNwfilters (struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *rerr,
                             remote_list_nwfilters_args *args,
                             remote_list_nwfilters_ret *ret)
{

    if (args->maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) {
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NWFILTER_NAME_LIST_MAX"));
        return -1;
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

    ret->names.names_len =
        virConnectListNWFilters (conn,
                                 ret->names.names_val, args->maxnames);
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNwfilterGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *rerr,
                              remote_nwfilter_get_xml_desc_args *args,
                              remote_nwfilter_get_xml_desc_ret *ret)
{
    virNWFilterPtr nwfilter;

    nwfilter = get_nonnull_nwfilter (conn, args->nwfilter);
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNWFilterGetXMLDesc (nwfilter, args->flags);
    if (!ret->xml) {
        virNWFilterFree(nwfilter);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    virNWFilterFree(nwfilter);
    return 0;
}


static int
remoteDispatchNumOfNwfilters (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *rerr,
                              void *args ATTRIBUTE_UNUSED,
                              remote_num_of_nwfilters_ret *ret)
{

    ret->num = virConnectNumOfNWFilters (conn);
    if (ret->num == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631
static int
remoteDispatchDomainGetBlockInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_domain_get_block_info_args *args,
                                  remote_domain_get_block_info_ret *ret)
{
    virDomainPtr dom;
    virDomainBlockInfo info;

    dom = get_nonnull_domain (conn, args->dom);
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainGetBlockInfo (dom, args->path, &info, args->flags) == -1) {
        virDomainFree(dom);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    ret->capacity = info.capacity;
    ret->allocation = info.allocation;
    ret->physical = info.physical;

    virDomainFree(dom);

    return 0;
}

C
Chris Lalancette 已提交
6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660
static int
qemuDispatchMonitorCommand (struct qemud_server *server ATTRIBUTE_UNUSED,
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                            remote_error *rerr,
                            qemu_monitor_command_args *args,
                            qemu_monitor_command_ret *ret)
{
    virDomainPtr domain;

    domain = get_nonnull_domain(conn, args->domain);
    if (domain == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    if (virDomainQemuMonitorCommand(domain, args->cmd, &ret->result,
                                    args->flags) == -1) {
        virDomainFree(domain);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    virDomainFree(domain);

    return 0;
}

6661

6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687
/*----- Helpers. -----*/

/* get_nonnull_domain and get_nonnull_network turn an on-wire
 * (name, uuid) pair into virDomainPtr or virNetworkPtr object.
 * virDomainPtr or virNetworkPtr cannot be NULL.
 *
 * NB. If these return NULL then the caller must return an error.
 */
static virDomainPtr
get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain)
{
    virDomainPtr dom;
    dom = virGetDomain (conn, domain.name, BAD_CAST domain.uuid);
    /* Should we believe the domain.id sent by the client?  Maybe
     * this should be a check rather than an assignment? XXX
     */
    if (dom) dom->id = domain.id;
    return dom;
}

static virNetworkPtr
get_nonnull_network (virConnectPtr conn, remote_nonnull_network network)
{
    return virGetNetwork (conn, network.name, BAD_CAST network.uuid);
}

D
Daniel Veillard 已提交
6688
static virInterfacePtr
6689
get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface)
D
Daniel Veillard 已提交
6690
{
6691
    return virGetInterface (conn, iface.name, iface.mac);
D
Daniel Veillard 已提交
6692 6693
}

6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707
static virStoragePoolPtr
get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool)
{
    return virGetStoragePool (conn, pool.name, BAD_CAST pool.uuid);
}

static virStorageVolPtr
get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol)
{
    virStorageVolPtr ret;
    ret = virGetStorageVol (conn, vol.pool, vol.name, vol.key);
    return ret;
}

6708 6709 6710
static virSecretPtr
get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret)
{
6711
    return virGetSecret (conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
6712 6713
}

6714 6715 6716 6717 6718 6719
static virNWFilterPtr
get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter)
{
    return virGetNWFilter (conn, nwfilter.name, BAD_CAST nwfilter.uuid);
}

C
Chris Lalancette 已提交
6720
static virDomainSnapshotPtr
6721
get_nonnull_domain_snapshot (virDomainPtr domain, remote_nonnull_domain_snapshot snapshot)
C
Chris Lalancette 已提交
6722 6723 6724 6725
{
    return virGetDomainSnapshot(domain, snapshot.name);
}

6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741
/* Make remote_nonnull_domain and remote_nonnull_network. */
static void
make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
{
    dom_dst->id = dom_src->id;
    dom_dst->name = strdup (dom_src->name);
    memcpy (dom_dst->uuid, dom_src->uuid, VIR_UUID_BUFLEN);
}

static void
make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src)
{
    net_dst->name = strdup (net_src->name);
    memcpy (net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN);
}

D
Daniel Veillard 已提交
6742 6743 6744 6745 6746 6747 6748 6749
static void
make_nonnull_interface (remote_nonnull_interface *interface_dst,
                        virInterfacePtr interface_src)
{
    interface_dst->name = strdup (interface_src->name);
    interface_dst->mac = strdup (interface_src->mac);
}

6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763
static void
make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
{
    pool_dst->name = strdup (pool_src->name);
    memcpy (pool_dst->uuid, pool_src->uuid, VIR_UUID_BUFLEN);
}

static void
make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src)
{
    vol_dst->pool = strdup (vol_src->pool);
    vol_dst->name = strdup (vol_src->name);
    vol_dst->key = strdup (vol_src->key);
}
6764 6765 6766 6767 6768 6769

static void
make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src)
{
    dev_dst->name = strdup(dev_src->name);
}
6770 6771 6772 6773

static void
make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
{
6774
    memcpy (secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
6775 6776
    secret_dst->usageType = secret_src->usageType;
    secret_dst->usageID = strdup (secret_src->usageID);
6777
}
6778 6779 6780 6781 6782 6783 6784

static void
make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src)
{
    nwfilter_dst->name = strdup (nwfilter_src->name);
    memcpy (nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
}
C
Chris Lalancette 已提交
6785 6786 6787 6788 6789 6790 6791

static void
make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src)
{
    snapshot_dst->name = strdup(snapshot_src->name);
    make_nonnull_domain(&snapshot_dst->domain, snapshot_src->domain);
}