remote.c 243.8 KB
Newer Older
1
/*
2
 * remote.c: handlers for RPC method calls
3
 *
4
 * Copyright (C) 2007-2011 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"
60
#include "uuid.h"
61
#include "network.h"
C
Chris Lalancette 已提交
62
#include "libvirt/libvirt-qemu.h"
63
#include "command.h"
64

65
#define VIR_FROM_THIS VIR_FROM_REMOTE
66
#define REMOTE_DEBUG(fmt, ...) VIR_DEBUG(fmt, __VA_ARGS__)
67

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain);
static virNetworkPtr get_nonnull_network(virConnectPtr conn, remote_nonnull_network network);
static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface);
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);
static virSecretPtr get_nonnull_secret(virConnectPtr conn, remote_nonnull_secret secret);
static virNWFilterPtr get_nonnull_nwfilter(virConnectPtr conn, remote_nonnull_nwfilter nwfilter);
static virDomainSnapshotPtr get_nonnull_domain_snapshot(virDomainPtr domain, remote_nonnull_domain_snapshot snapshot);
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);
static void make_nonnull_interface(remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
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);
static void make_nonnull_node_device(remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src);
static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
static void make_nonnull_nwfilter(remote_nonnull_nwfilter *net_dst, virNWFilterPtr nwfilter_src);
static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
85

86

87
#include "remote_dispatch_prototypes.h"
C
Chris Lalancette 已提交
88
#include "qemu_dispatch_prototypes.h"
89 90 91 92

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

C
Chris Lalancette 已提交
94 95 96 97
static const dispatch_data const qemu_dispatch_table[] = {
#include "qemu_dispatch_table.h"
};

98 99 100 101 102 103 104 105 106 107
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 已提交
108 109 110 111 112 113 114 115 116 117
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]);
}

118 119
/* Prototypes */
static void
120 121 122 123
remoteDispatchDomainEventSend(struct qemud_client *client,
                              int procnr,
                              xdrproc_t proc,
                              void *data);
124

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

134 135 136 137
    if (!client)
        return -1;

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

139
    virMutexLock(&client->lock);
140

141 142
    /* build return data */
    memset(&data, 0, sizeof data);
143
    make_nonnull_domain(&data.dom, dom);
144 145
    data.event = event;
    data.detail = detail;
146

147 148 149
    remoteDispatchDomainEventSend(client,
                                  REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
                                  (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, &data);
150 151

    virMutexUnlock(&client->lock);
152

153 154
    return 0;
}
155

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
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);
172
    make_nonnull_domain(&data.dom, dom);
173

174 175 176
    remoteDispatchDomainEventSend(client,
                                  REMOTE_PROC_DOMAIN_EVENT_REBOOT,
                                  (xdrproc_t)xdr_remote_domain_event_reboot_msg, &data);
177 178 179 180 181 182

    virMutexUnlock(&client->lock);

    return 0;
}

183

184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
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);
201
    make_nonnull_domain(&data.dom, dom);
202 203
    data.offset = offset;

204 205 206
    remoteDispatchDomainEventSend(client,
                                  REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
                                  (xdrproc_t)xdr_remote_domain_event_rtc_change_msg, &data);
207 208 209 210 211 212 213

    virMutexUnlock(&client->lock);

    return 0;
}


214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
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);
231
    make_nonnull_domain(&data.dom, dom);
232 233
    data.action = action;

234 235 236
    remoteDispatchDomainEventSend(client,
                                  REMOTE_PROC_DOMAIN_EVENT_WATCHDOG,
                                  (xdrproc_t)xdr_remote_domain_event_watchdog_msg, &data);
237 238 239 240 241 242 243

    virMutexUnlock(&client->lock);

    return 0;
}


244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
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);
263
    make_nonnull_domain(&data.dom, dom);
264 265 266 267
    data.srcPath = (char*)srcPath;
    data.devAlias = (char*)devAlias;
    data.action = action;

268 269 270
    remoteDispatchDomainEventSend(client,
                                  REMOTE_PROC_DOMAIN_EVENT_IO_ERROR,
                                  (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data);
271 272 273 274 275 276 277

    virMutexUnlock(&client->lock);

    return 0;
}


278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
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);
299
    make_nonnull_domain(&data.dom, dom);
300 301 302 303 304
    data.srcPath = (char*)srcPath;
    data.devAlias = (char*)devAlias;
    data.action = action;
    data.reason = (char*)reason;

305 306 307
    remoteDispatchDomainEventSend(client,
                                  REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON,
                                  (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data);
308 309 310 311 312 313 314

    virMutexUnlock(&client->lock);

    return 0;
}


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
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);
345
    make_nonnull_domain(&data.dom, dom);
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
    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;
    }

367 368 369
    remoteDispatchDomainEventSend(client,
                                  REMOTE_PROC_DOMAIN_EVENT_GRAPHICS,
                                  (xdrproc_t)xdr_remote_domain_event_graphics_msg, &data);
370 371 372 373 374 375 376 377 378

    VIR_FREE(data.subject.subject_val);

    virMutexUnlock(&client->lock);

    return 0;
}


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

verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);

391 392 393
/*----- Functions. -----*/

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

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

410 411 412
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
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
424 425
        ? virConnectOpenReadOnly(name)
        : virConnectOpen(name);
426

427
    if (client->conn == NULL)
428 429
        remoteDispatchConnError(rerr, NULL);

430
    rc = client->conn ? 0 : -1;
431
    virMutexUnlock(&client->lock);
432
    return rc;
433 434
}

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

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

453
    client->closing = 1;
454

455
    virMutexUnlock(&client->lock);
456
    return 0;
457 458
}

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

    if (ret->supported == -1) {
470
        remoteDispatchConnError(rerr, conn);
471 472
        return -1;
    }
473 474 475 476

    return 0;
}

477
static int
478 479 480 481 482 483
remoteDispatchGetType(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_type_ret *ret)
484 485 486
{
    const char *type;

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

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

    return 0;
}

static int
506 507 508 509 510 511 512
remoteDispatchGetVersion(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_version_ret *ret)
513 514 515
{
    unsigned long hvVer;

516
    if (virConnectGetVersion(conn, &hvVer) == -1) {
517
        remoteDispatchConnError(rerr, conn);
518
        return -1;
519
    }
520 521 522 523 524

    ret->hv_ver = hvVer;
    return 0;
}

525
static int
526 527 528 529 530 531 532
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)
533 534 535
{
    unsigned long libVer;

536
    if (virConnectGetLibVersion(conn, &libVer) == -1) {
537 538 539 540 541 542 543 544
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    ret->lib_ver = libVer;
    return 0;
}

545
static int
546 547 548 549 550 551 552
remoteDispatchGetHostname(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_hostname_ret *ret)
553 554 555
{
    char *hostname;

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

    ret->hostname = hostname;
    return 0;
}

566
static int
567 568 569 570 571 572 573
remoteDispatchGetUri(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_uri_ret *ret)
574 575 576 577
{
    char *uri;
    CHECK_CONN(client);

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

    ret->uri = uri;
    return 0;
}

588
static int
589 590 591 592 593 594 595
remoteDispatchGetSysinfo(struct qemud_server *server ATTRIBUTE_UNUSED,
                         struct qemud_client *client ATTRIBUTE_UNUSED,
                         virConnectPtr conn,
                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                         remote_error *rerr,
                         remote_get_sysinfo_args *args,
                         remote_get_sysinfo_ret *ret)
596 597 598 599 600
{
    unsigned int flags;
    char *sysinfo;

    flags = args->flags;
601
    sysinfo = virConnectGetSysinfo(conn, flags);
602 603 604 605 606 607 608 609 610
    if (sysinfo == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    ret->sysinfo = sysinfo;
    return 0;
}

611
static int
612 613 614 615 616 617 618
remoteDispatchGetMaxVcpus(struct qemud_server *server ATTRIBUTE_UNUSED,
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
                          remote_error *rerr,
                          remote_get_max_vcpus_args *args,
                          remote_get_max_vcpus_ret *ret)
619 620 621 622
{
    char *type;

    type = args->type ? *args->type : NULL;
623
    ret->max_vcpus = virConnectGetMaxVcpus(conn, type);
624
    if (ret->max_vcpus == -1) {
625
        remoteDispatchConnError(rerr, conn);
626 627
        return -1;
    }
628 629 630 631 632

    return 0;
}

static int
633 634 635 636 637 638 639
remoteDispatchNodeGetInfo(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_node_get_info_ret *ret)
640 641 642
{
    virNodeInfo info;

643
    if (virNodeGetInfo(conn, &info) == -1) {
644
        remoteDispatchConnError(rerr, conn);
645
        return -1;
646
    }
647

648
    memcpy(ret->model, info.model, sizeof ret->model);
649 650 651 652 653 654 655 656 657 658 659 660
    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
661 662 663 664 665 666 667
remoteDispatchGetCapabilities(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_capabilities_ret *ret)
668 669 670
{
    char *caps;

671
    caps = virConnectGetCapabilities(conn);
672
    if (caps == NULL) {
673
        remoteDispatchConnError(rerr, conn);
674 675
        return -1;
    }
676 677 678 679 680

    ret->capabilities = caps;
    return 0;
}

681
static int
682 683 684 685 686 687 688
remoteDispatchNodeGetCellsFreeMemory(struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
                                     remote_error *rerr,
                                     remote_node_get_cells_free_memory_args *args,
                                     remote_node_get_cells_free_memory_ret *ret)
689
{
D
Daniel P. Berrange 已提交
690
    int err;
691 692

    if (args->maxCells > REMOTE_NODE_MAX_CELLS) {
693
        remoteDispatchFormatError(rerr,
694 695
                                   "%s", _("maxCells > REMOTE_NODE_MAX_CELLS"));
        return -1;
696 697 698
    }

    /* Allocate return buffer. */
699
    if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) {
700 701
        remoteDispatchOOMError(rerr);
        return -1;
702
    }
703

D
Daniel P. Berrange 已提交
704 705 706 707 708
    err = virNodeGetCellsFreeMemory(conn,
                                    (unsigned long long *)ret->freeMems.freeMems_val,
                                    args->startCell,
                                    args->maxCells);
    if (err <= 0) {
709
        VIR_FREE(ret->freeMems.freeMems_val);
710
        remoteDispatchConnError(rerr, conn);
711
        return -1;
712
    }
D
Daniel P. Berrange 已提交
713
    ret->freeMems.freeMems_len = err;
714 715 716 717 718 719

    return 0;
}


static int
720 721 722 723 724 725 726
remoteDispatchNodeGetFreeMemory(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_node_get_free_memory_ret *ret)
727 728 729
{
    unsigned long long freeMem;

730
    freeMem = virNodeGetFreeMemory(conn);
731
    if (freeMem == 0) {
732
        remoteDispatchConnError(rerr, conn);
733 734
        return -1;
    }
735 736 737 738 739
    ret->freeMem = freeMem;
    return 0;
}


740
static int
741 742 743 744 745 746 747
remoteDispatchDomainGetSchedulerType(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_scheduler_type_args *args,
                                     remote_domain_get_scheduler_type_ret *ret)
748 749 750 751 752
{
    virDomainPtr dom;
    char *type;
    int nparams;

753
    dom = get_nonnull_domain(conn, args->dom);
754
    if (dom == NULL) {
755
        remoteDispatchConnError(rerr, conn);
756
        return -1;
757 758
    }

759
    type = virDomainGetSchedulerType(dom, &nparams);
760
    if (type == NULL) {
761
        remoteDispatchConnError(rerr, conn);
762
        virDomainFree(dom);
763 764
        return -1;
    }
765 766 767

    ret->type = type;
    ret->nparams = nparams;
768
    virDomainFree(dom);
769 770 771 772
    return 0;
}

static int
773 774 775 776 777 778 779
remoteDispatchDomainGetSchedulerParameters(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_scheduler_parameters_args *args,
                                           remote_domain_get_scheduler_parameters_ret *ret)
780 781 782 783 784 785 786 787
{
    virDomainPtr dom;
    virSchedParameterPtr params;
    int i, r, nparams;

    nparams = args->nparams;

    if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) {
788
        remoteDispatchFormatError(rerr, "%s", _("nparams too large"));
789
        return -1;
790
    }
791
    if (VIR_ALLOC_N(params, nparams) < 0) {
792 793
        remoteDispatchOOMError(rerr);
        return -1;
794 795
    }

796
    dom = get_nonnull_domain(conn, args->dom);
797
    if (dom == NULL) {
798
        VIR_FREE(params);
799
        remoteDispatchConnError(rerr, conn);
800
        return -1;
801 802
    }

803
    r = virDomainGetSchedulerParameters(dom, params, &nparams);
804
    if (r == -1) {
805
        remoteDispatchConnError(rerr, conn);
806
        virDomainFree(dom);
807
        VIR_FREE(params);
808 809 810 811 812
        return -1;
    }

    /* Serialise the scheduler parameters. */
    ret->params.params_len = nparams;
813 814
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;
815 816

    for (i = 0; i < nparams; ++i) {
817
        /* remoteDispatchClientRequest will free this: */
818
        ret->params.params_val[i].field = strdup(params[i].field);
819 820 821
        if (ret->params.params_val[i].field == NULL)
            goto oom;

822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
        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:
837
            remoteDispatchFormatError(rerr, "%s", _("unknown type"));
838
            goto cleanup;
839 840
        }
    }
841
    virDomainFree(dom);
842
    VIR_FREE(params);
843 844

    return 0;
845 846

oom:
847
    remoteDispatchOOMError(rerr);
848 849 850 851 852
cleanup:
    virDomainFree(dom);
    for (i = 0 ; i < nparams ; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
853
    return -1;
854 855 856
}

static int
857 858 859 860 861 862 863
remoteDispatchDomainSetSchedulerParameters(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_set_scheduler_parameters_args *args,
                                           void *ret ATTRIBUTE_UNUSED)
864 865 866 867 868 869 870 871
{
    virDomainPtr dom;
    int i, r, nparams;
    virSchedParameterPtr params;

    nparams = args->params.params_len;

    if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) {
872
        remoteDispatchFormatError(rerr, "%s", _("nparams too large"));
873
        return -1;
874
    }
875
    if (VIR_ALLOC_N(params, nparams) < 0) {
876 877
        remoteDispatchOOMError(rerr);
        return -1;
878 879 880 881
    }

    /* Deserialise parameters. */
    for (i = 0; i < nparams; ++i) {
C
Chris Lalancette 已提交
882 883 884 885 886
        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;
        }
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
        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;
        }
    }

904
    dom = get_nonnull_domain(conn, args->dom);
905
    if (dom == NULL) {
906
        VIR_FREE(params);
907
        remoteDispatchConnError(rerr, conn);
908
        return -1;
909 910
    }

911
    r = virDomainSetSchedulerParameters(dom, params, nparams);
912
    VIR_FREE(params);
913
    if (r == -1) {
914
        remoteDispatchConnError(rerr, conn);
915
        virDomainFree(dom);
916 917
        return -1;
    }
918
    virDomainFree(dom);
919 920 921 922

    return 0;
}

923
static int
924 925 926 927 928 929 930
remoteDispatchDomainBlockStats(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_block_stats_args *args,
                               remote_domain_block_stats_ret *ret)
931 932 933 934 935
{
    virDomainPtr dom;
    char *path;
    struct _virDomainBlockStats stats;

936
    dom = get_nonnull_domain(conn, args->dom);
937
    if (dom == NULL) {
938
        remoteDispatchConnError(rerr, conn);
939
        return -1;
940 941 942
    }
    path = args->path;

943
    if (virDomainBlockStats(dom, path, &stats, sizeof stats) == -1) {
944
        remoteDispatchConnError(rerr, conn);
945
        virDomainFree(dom);
946
        return -1;
D
Daniel P. Berrange 已提交
947
    }
948
    virDomainFree(dom);
949 950 951 952 953 954 955 956 957 958 959

    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
960 961 962 963 964 965 966
remoteDispatchDomainInterfaceStats(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_interface_stats_args *args,
                                   remote_domain_interface_stats_ret *ret)
967 968 969 970 971
{
    virDomainPtr dom;
    char *path;
    struct _virDomainInterfaceStats stats;

972
    dom = get_nonnull_domain(conn, args->dom);
973
    if (dom == NULL) {
974
        remoteDispatchConnError(rerr, conn);
975
        return -1;
976 977 978
    }
    path = args->path;

979
    if (virDomainInterfaceStats(dom, path, &stats, sizeof stats) == -1) {
980
        remoteDispatchConnError(rerr, conn);
981
        virDomainFree(dom);
982
        return -1;
D
Daniel P. Berrange 已提交
983
    }
984
    virDomainFree(dom);
985 986 987 988 989 990 991 992 993 994 995 996 997

    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;
}

998
static int
999 1000 1001 1002 1003 1004 1005
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)
1006 1007 1008 1009 1010 1011
{
    virDomainPtr dom;
    struct _virDomainMemoryStat *stats;
    unsigned int nr_stats, i;

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

1017
    dom = get_nonnull_domain(conn, args->dom);
1018 1019 1020 1021 1022 1023 1024
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* Allocate stats array for making dispatch call */
    if (VIR_ALLOC_N(stats, args->maxStats) < 0) {
1025
        virDomainFree(dom);
1026 1027
        remoteDispatchOOMError(rerr);
        return -1;
1028
    }
1029

1030
    nr_stats = virDomainMemoryStats(dom, stats, args->maxStats, 0);
1031 1032 1033
    if (nr_stats == -1) {
        VIR_FREE(stats);
        remoteDispatchConnError(rerr, conn);
1034
        virDomainFree(dom);
1035 1036
        return -1;
    }
1037
    virDomainFree(dom);
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055

    /* 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;
}

1056
static int
1057 1058 1059 1060 1061 1062 1063
remoteDispatchDomainBlockPeek(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_block_peek_args *args,
                              remote_domain_block_peek_ret *ret)
1064 1065 1066 1067 1068 1069 1070
{
    virDomainPtr dom;
    char *path;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

1071
    dom = get_nonnull_domain(conn, args->dom);
1072
    if (dom == NULL) {
1073
        remoteDispatchConnError(rerr, conn);
1074
        return -1;
1075 1076 1077 1078 1079 1080 1081
    }
    path = args->path;
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
1082 1083
        virDomainFree(dom);
        remoteDispatchFormatError(rerr,
1084 1085
                                   "%s", _("size > maximum buffer size"));
        return -1;
1086 1087 1088
    }

    ret->buffer.buffer_len = size;
1089 1090
    if (VIR_ALLOC_N(ret->buffer.buffer_val, size) < 0) {
        virDomainFree(dom);
1091
        remoteDispatchOOMError(rerr);
1092
        return -1;
1093 1094
    }

1095 1096 1097
    if (virDomainBlockPeek(dom, path, offset, size,
                           ret->buffer.buffer_val, flags) == -1) {
        /* free(ret->buffer.buffer_val); - caller frees */
1098
        remoteDispatchConnError(rerr, conn);
1099
        virDomainFree(dom);
1100 1101
        return -1;
    }
1102
    virDomainFree(dom);
1103 1104 1105 1106

    return 0;
}

R
Richard W.M. Jones 已提交
1107
static int
1108 1109 1110 1111 1112 1113 1114
remoteDispatchDomainMemoryPeek(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_peek_args *args,
                               remote_domain_memory_peek_ret *ret)
R
Richard W.M. Jones 已提交
1115 1116 1117 1118 1119 1120
{
    virDomainPtr dom;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

1121
    dom = get_nonnull_domain(conn, args->dom);
R
Richard W.M. Jones 已提交
1122
    if (dom == NULL) {
1123
        remoteDispatchConnError(rerr, conn);
1124
        return -1;
R
Richard W.M. Jones 已提交
1125 1126 1127 1128 1129 1130
    }
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
1131 1132
        virDomainFree(dom);
        remoteDispatchFormatError(rerr,
1133 1134
                                   "%s", _("size > maximum buffer size"));
        return -1;
R
Richard W.M. Jones 已提交
1135 1136 1137
    }

    ret->buffer.buffer_len = size;
1138 1139
    if (VIR_ALLOC_N(ret->buffer.buffer_val, size) < 0) {
        virDomainFree(dom);
1140
        remoteDispatchOOMError(rerr);
1141
        return -1;
R
Richard W.M. Jones 已提交
1142 1143
    }

1144 1145 1146
    if (virDomainMemoryPeek(dom, offset, size,
                            ret->buffer.buffer_val, flags) == -1) {
        /* free(ret->buffer.buffer_val); - caller frees */
1147
        remoteDispatchConnError(rerr, conn);
1148
        virDomainFree(dom);
R
Richard W.M. Jones 已提交
1149 1150
        return -1;
    }
1151
    virDomainFree(dom);
R
Richard W.M. Jones 已提交
1152 1153 1154 1155

    return 0;
}

1156
static int
1157 1158 1159 1160 1161 1162 1163
remoteDispatchDomainAttachDevice(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_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
1164 1165 1166
{
    virDomainPtr dom;

1167
    dom = get_nonnull_domain(conn, args->dom);
1168
    if (dom == NULL) {
1169
        remoteDispatchConnError(rerr, conn);
1170
        return -1;
1171 1172
    }

1173
    if (virDomainAttachDevice(dom, args->xml) == -1) {
1174
        remoteDispatchConnError(rerr, conn);
1175
        virDomainFree(dom);
1176
        return -1;
1177 1178
    }
    virDomainFree(dom);
1179 1180 1181
    return 0;
}

J
Jim Fehlig 已提交
1182
static int
1183 1184 1185 1186 1187 1188 1189
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)
J
Jim Fehlig 已提交
1190 1191 1192
{
    virDomainPtr dom;

1193
    dom = get_nonnull_domain(conn, args->dom);
J
Jim Fehlig 已提交
1194 1195 1196 1197 1198
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

1199
    if (virDomainAttachDeviceFlags(dom, args->xml, args->flags) == -1) {
J
Jim Fehlig 已提交
1200
        remoteDispatchConnError(rerr, conn);
1201
        virDomainFree(dom);
J
Jim Fehlig 已提交
1202 1203 1204 1205 1206 1207
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

1208
static int
1209 1210 1211 1212 1213 1214 1215
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)
1216 1217 1218
{
    virDomainPtr dom;

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

1225
    if (virDomainUpdateDeviceFlags(dom, args->xml, args->flags) == -1) {
1226
        remoteDispatchConnError(rerr, conn);
1227
        virDomainFree(dom);
1228 1229 1230 1231 1232 1233
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

1234
static int
1235 1236 1237 1238 1239 1240 1241
remoteDispatchDomainCreate(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_args *args,
                           void *ret ATTRIBUTE_UNUSED)
1242 1243 1244
{
    virDomainPtr dom;

1245
    dom = get_nonnull_domain(conn, args->dom);
1246
    if (dom == NULL) {
1247
        remoteDispatchConnError(rerr, conn);
1248
        return -1;
1249 1250
    }

1251
    if (virDomainCreate(dom) == -1) {
1252
        remoteDispatchConnError(rerr, conn);
1253
        virDomainFree(dom);
1254
        return -1;
1255 1256
    }
    virDomainFree(dom);
1257 1258 1259
    return 0;
}

1260
static int
1261 1262 1263 1264 1265 1266 1267
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)
1268 1269 1270
{
    virDomainPtr dom;

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

1277
    if (virDomainCreateWithFlags(dom, args->flags) == -1) {
1278
        remoteDispatchConnError(rerr, conn);
1279
        virDomainFree(dom);
1280 1281 1282
        return -1;
    }

1283
    make_nonnull_domain(&ret->dom, dom);
1284 1285 1286 1287
    virDomainFree(dom);
    return 0;
}

1288
static int
1289 1290 1291 1292 1293 1294 1295
remoteDispatchDomainCreateXml(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_xml_args *args,
                              remote_domain_create_xml_ret *ret)
1296 1297 1298
{
    virDomainPtr dom;

1299
    dom = virDomainCreateXML(conn, args->xml_desc, args->flags);
1300
    if (dom == NULL) {
1301
        remoteDispatchConnError(rerr, conn);
1302 1303
        return -1;
    }
1304

1305
    make_nonnull_domain(&ret->dom, dom);
1306
    virDomainFree(dom);
1307 1308 1309 1310 1311

    return 0;
}

static int
1312 1313 1314 1315 1316 1317 1318
remoteDispatchDomainDefineXml(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_define_xml_args *args,
                              remote_domain_define_xml_ret *ret)
1319 1320 1321
{
    virDomainPtr dom;

1322
    dom = virDomainDefineXML(conn, args->xml);
1323
    if (dom == NULL) {
1324
        remoteDispatchConnError(rerr, conn);
1325 1326
        return -1;
    }
1327

1328
    make_nonnull_domain(&ret->dom, dom);
1329
    virDomainFree(dom);
1330 1331 1332 1333 1334

    return 0;
}

static int
1335 1336 1337 1338 1339 1340 1341
remoteDispatchDomainDestroy(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_destroy_args *args,
                            void *ret ATTRIBUTE_UNUSED)
1342 1343 1344
{
    virDomainPtr dom;

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

1351
    if (virDomainDestroy(dom) == -1) {
1352
        remoteDispatchConnError(rerr, conn);
1353
        virDomainFree(dom);
1354
        return -1;
1355 1356
    }
    virDomainFree(dom);
1357 1358 1359 1360
    return 0;
}

static int
1361 1362 1363 1364 1365 1366 1367
remoteDispatchDomainDetachDevice(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_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
1368 1369 1370
{
    virDomainPtr dom;

1371
    dom = get_nonnull_domain(conn, args->dom);
1372
    if (dom == NULL) {
1373
        remoteDispatchConnError(rerr, conn);
1374
        return -1;
1375 1376
    }

1377
    if (virDomainDetachDevice(dom, args->xml) == -1) {
J
Jim Fehlig 已提交
1378
        remoteDispatchConnError(rerr, conn);
1379
        virDomainFree(dom);
J
Jim Fehlig 已提交
1380 1381 1382 1383 1384 1385 1386 1387
        return -1;
    }

    virDomainFree(dom);
    return 0;
}

static int
1388 1389 1390 1391 1392 1393 1394
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)
J
Jim Fehlig 已提交
1395 1396 1397
{
    virDomainPtr dom;

1398
    dom = get_nonnull_domain(conn, args->dom);
J
Jim Fehlig 已提交
1399 1400 1401 1402 1403
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

1404
    if (virDomainDetachDeviceFlags(dom, args->xml, args->flags) == -1) {
1405
        remoteDispatchConnError(rerr, conn);
1406
        virDomainFree(dom);
1407
        return -1;
1408
    }
1409

1410
    virDomainFree(dom);
1411 1412 1413 1414
    return 0;
}

static int
1415 1416 1417 1418 1419 1420 1421
remoteDispatchDomainDumpXml(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_dump_xml_args *args,
                            remote_domain_dump_xml_ret *ret)
1422 1423 1424
{
    virDomainPtr dom;

1425
    dom = get_nonnull_domain(conn, args->dom);
1426
    if (dom == NULL) {
1427
        remoteDispatchConnError(rerr, conn);
1428
        return -1;
1429 1430 1431
    }

    /* remoteDispatchClientRequest will free this. */
1432
    ret->xml = virDomainGetXMLDesc(dom, args->flags);
1433
    if (!ret->xml) {
1434
        remoteDispatchConnError(rerr, conn);
1435
        virDomainFree(dom);
1436
        return -1;
1437 1438
    }
    virDomainFree(dom);
1439 1440 1441
    return 0;
}

1442
static int
1443 1444 1445 1446 1447 1448 1449
remoteDispatchDomainXmlFromNative(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_xml_from_native_args *args,
                                  remote_domain_xml_from_native_ret *ret)
1450 1451
{
    /* remoteDispatchClientRequest will free this. */
1452 1453 1454 1455
    ret->domainXml = virConnectDomainXMLFromNative(conn,
                                                   args->nativeFormat,
                                                   args->nativeConfig,
                                                   args->flags);
1456 1457 1458 1459 1460 1461 1462 1463
    if (!ret->domainXml) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}

static int
1464 1465 1466 1467 1468 1469 1470
remoteDispatchDomainXmlToNative(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_xml_to_native_args *args,
                                remote_domain_xml_to_native_ret *ret)
1471 1472
{
    /* remoteDispatchClientRequest will free this. */
1473 1474 1475 1476
    ret->nativeConfig = virConnectDomainXMLToNative(conn,
                                                    args->nativeFormat,
                                                    args->domainXml,
                                                    args->flags);
1477 1478 1479 1480 1481 1482 1483 1484
    if (!ret->nativeConfig) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}


1485
static int
1486 1487 1488 1489 1490 1491 1492
remoteDispatchDomainGetAutostart(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_autostart_args *args,
                                 remote_domain_get_autostart_ret *ret)
1493 1494 1495
{
    virDomainPtr dom;

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

1502
    if (virDomainGetAutostart(dom, &ret->autostart) == -1) {
1503
        remoteDispatchConnError(rerr, conn);
1504
        virDomainFree(dom);
1505
        return -1;
1506 1507
    }
    virDomainFree(dom);
1508 1509 1510 1511
    return 0;
}

static int
1512 1513 1514 1515 1516 1517 1518
remoteDispatchDomainGetInfo(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_info_args *args,
                            remote_domain_get_info_ret *ret)
1519 1520 1521 1522
{
    virDomainPtr dom;
    virDomainInfo info;

1523
    dom = get_nonnull_domain(conn, args->dom);
1524
    if (dom == NULL) {
1525
        remoteDispatchConnError(rerr, conn);
1526
        return -1;
1527 1528
    }

1529
    if (virDomainGetInfo(dom, &info) == -1) {
1530
        remoteDispatchConnError(rerr, conn);
1531
        virDomainFree(dom);
1532
        return -1;
1533
    }
1534 1535 1536 1537 1538 1539 1540

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

1541 1542
    virDomainFree(dom);

1543 1544 1545 1546
    return 0;
}

static int
1547 1548 1549 1550 1551 1552 1553
remoteDispatchDomainGetMaxMemory(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_max_memory_args *args,
                                 remote_domain_get_max_memory_ret *ret)
1554 1555 1556
{
    virDomainPtr dom;

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

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

static int
1574 1575 1576 1577 1578 1579 1580
remoteDispatchDomainGetMaxVcpus(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_max_vcpus_args *args,
                                remote_domain_get_max_vcpus_ret *ret)
1581 1582 1583
{
    virDomainPtr dom;

1584
    dom = get_nonnull_domain(conn, args->dom);
1585
    if (dom == NULL) {
1586
        remoteDispatchConnError(rerr, conn);
1587
        return -1;
1588 1589
    }

1590
    ret->num = virDomainGetMaxVcpus(dom);
1591
    if (ret->num == -1) {
1592
        remoteDispatchConnError(rerr, conn);
1593
        virDomainFree(dom);
1594 1595 1596
        return -1;
    }
    virDomainFree(dom);
1597 1598 1599
    return 0;
}

1600 1601 1602 1603
static int
remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1604
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
1605 1606 1607 1608 1609
                                     remote_error *rerr,
                                     remote_domain_get_security_label_args *args,
                                     remote_domain_get_security_label_ret *ret)
{
    virDomainPtr dom;
1610
    virSecurityLabelPtr seclabel;
1611 1612 1613 1614 1615 1616 1617

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

1618 1619 1620 1621 1622 1623 1624
    if (VIR_ALLOC(seclabel) < 0) {
        virDomainFree(dom);
        remoteDispatchOOMError(rerr);
        return -1;
    }

    if (virDomainGetSecurityLabel(dom, seclabel) == -1) {
1625
        remoteDispatchConnError(rerr, conn);
1626
        virDomainFree(dom);
1627
        VIR_FREE(seclabel);
1628 1629 1630
        return -1;
    }

1631
    ret->label.label_len = strlen(seclabel->label) + 1;
1632 1633
    if (VIR_ALLOC_N(ret->label.label_val, ret->label.label_len) < 0) {
        virDomainFree(dom);
1634
        VIR_FREE(seclabel);
1635 1636 1637
        remoteDispatchOOMError(rerr);
        return -1;
    }
1638 1639
    strcpy(ret->label.label_val, seclabel->label);
    ret->enforcing = seclabel->enforcing;
1640
    virDomainFree(dom);
1641
    VIR_FREE(seclabel);
1642 1643 1644 1645 1646 1647 1648 1649

    return 0;
}

static int
remoteDispatchNodeGetSecurityModel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1650
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1651 1652 1653 1654 1655 1656 1657 1658
                                   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) {
1659
        remoteDispatchConnError(rerr, conn);
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
        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;
}

1680
static int
1681 1682 1683 1684 1685 1686 1687
remoteDispatchDomainGetOsType(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_os_type_args *args,
                              remote_domain_get_os_type_ret *ret)
1688 1689 1690
{
    virDomainPtr dom;

1691
    dom = get_nonnull_domain(conn, args->dom);
1692
    if (dom == NULL) {
1693
        remoteDispatchConnError(rerr, conn);
1694
        return -1;
1695 1696 1697
    }

    /* remoteDispatchClientRequest will free this */
1698
    ret->type = virDomainGetOSType(dom);
1699
    if (ret->type == NULL) {
1700
        remoteDispatchConnError(rerr, conn);
1701
        virDomainFree(dom);
1702
        return -1;
1703 1704
    }
    virDomainFree(dom);
1705 1706 1707 1708
    return 0;
}

static int
1709 1710 1711 1712 1713 1714 1715
remoteDispatchDomainGetVcpus(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_vcpus_args *args,
                             remote_domain_get_vcpus_ret *ret)
1716
{
1717 1718 1719
    virDomainPtr dom = NULL;
    virVcpuInfoPtr info = NULL;
    unsigned char *cpumaps = NULL;
1720 1721
    int info_len, i;

1722
    dom = get_nonnull_domain(conn, args->dom);
1723
    if (dom == NULL) {
1724
        remoteDispatchConnError(rerr, conn);
1725
        return -1;
1726 1727 1728
    }

    if (args->maxinfo > REMOTE_VCPUINFO_MAX) {
1729
        virDomainFree(dom);
1730
        remoteDispatchFormatError(rerr, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX"));
1731
        return -1;
1732 1733
    }

1734
    if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
1735
        virDomainFree(dom);
1736
        remoteDispatchFormatError(rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX"));
1737
        return -1;
1738 1739 1740
    }

    /* Allocate buffers to take the results. */
1741 1742
    if (VIR_ALLOC_N(info, args->maxinfo) < 0)
        goto oom;
1743 1744
    if (args->maplen > 0 &&
        VIR_ALLOC_N(cpumaps, args->maxinfo * args->maplen) < 0)
1745
        goto oom;
1746

1747 1748 1749
    info_len = virDomainGetVcpus(dom,
                                 info, args->maxinfo,
                                 cpumaps, args->maplen);
1750
    if (info_len == -1) {
1751
        remoteDispatchConnError(rerr, conn);
1752 1753
        VIR_FREE(info);
        VIR_FREE(cpumaps);
1754 1755 1756
        virDomainFree(dom);
        return -1;
    }
1757 1758 1759

    /* Allocate the return buffer for info. */
    ret->info.info_len = info_len;
1760 1761
    if (VIR_ALLOC_N(ret->info.info_val, info_len) < 0)
        goto oom;
1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773

    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.
     */
1774
    ret->cpumaps.cpumaps_len = args->maxinfo * args->maplen;
1775 1776
    ret->cpumaps.cpumaps_val = (char *) cpumaps;

1777
    VIR_FREE(info);
1778
    virDomainFree(dom);
1779
    return 0;
1780 1781 1782 1783 1784

oom:
    VIR_FREE(info);
    VIR_FREE(cpumaps);
    virDomainFree(dom);
1785 1786
    remoteDispatchOOMError(rerr);
    return -1;
1787 1788
}

E
Eric Blake 已提交
1789
static int
1790 1791 1792 1793 1794 1795 1796
remoteDispatchDomainGetVcpusFlags(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_vcpus_flags_args *args,
                                  remote_domain_get_vcpus_flags_ret *ret)
E
Eric Blake 已提交
1797 1798 1799
{
    virDomainPtr dom;

1800
    dom = get_nonnull_domain(conn, args->dom);
E
Eric Blake 已提交
1801 1802 1803 1804 1805
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

1806
    ret->num = virDomainGetVcpusFlags(dom, args->flags);
E
Eric Blake 已提交
1807 1808
    if (ret->num == -1) {
        remoteDispatchConnError(rerr, conn);
1809
        virDomainFree(dom);
E
Eric Blake 已提交
1810 1811 1812 1813 1814 1815
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

1816
static int
1817 1818 1819 1820 1821 1822 1823
remoteDispatchDomainMigratePrepare(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_prepare_args *args,
                                   remote_domain_migrate_prepare_ret *ret)
1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835
{
    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 ... */
1836
    if (VIR_ALLOC(uri_out) < 0) {
1837 1838
        remoteDispatchOOMError(rerr);
        return -1;
1839
    }
1840

1841 1842 1843
    r = virDomainMigratePrepare(conn, &cookie, &cookielen,
                                uri_in, uri_out,
                                args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1844
    if (r == -1) {
1845
        VIR_FREE(uri_out);
1846
        remoteDispatchConnError(rerr, conn);
D
Daniel P. Berrange 已提交
1847 1848
        return -1;
    }
1849 1850 1851 1852 1853 1854

    /* 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 已提交
1855 1856
    if (*uri_out == NULL) {
        ret->uri_out = NULL;
1857
        VIR_FREE(uri_out);
D
Daniel P. Berrange 已提交
1858 1859 1860
    } else {
        ret->uri_out = uri_out;
    }
1861 1862 1863 1864 1865

    return 0;
}

static int
1866 1867 1868 1869 1870 1871 1872
remoteDispatchDomainMigratePerform(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_perform_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
1873 1874 1875
{
    int r;
    virDomainPtr dom;
1876
    char *dname;
1877

1878
    dom = get_nonnull_domain(conn, args->dom);
1879
    if (dom == NULL) {
1880
        remoteDispatchConnError(rerr, conn);
1881
        return -1;
1882 1883 1884 1885
    }

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

1886 1887 1888 1889 1890
    r = virDomainMigratePerform(dom,
                                args->cookie.cookie_val,
                                args->cookie.cookie_len,
                                args->uri,
                                args->flags, dname, args->resource);
1891
    if (r == -1) {
1892
        remoteDispatchConnError(rerr, conn);
1893
        virDomainFree(dom);
1894 1895
        return -1;
    }
1896
    virDomainFree(dom);
1897 1898 1899 1900 1901

    return 0;
}

static int
1902 1903 1904 1905 1906 1907 1908
remoteDispatchDomainMigrateFinish(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_finish_args *args,
                                  remote_domain_migrate_finish_ret *ret)
1909 1910
{
    virDomainPtr ddom;
1911
    CHECK_CONN(client);
1912

1913 1914 1915 1916 1917
    ddom = virDomainMigrateFinish(conn, args->dname,
                                  args->cookie.cookie_val,
                                  args->cookie.cookie_len,
                                  args->uri,
                                  args->flags);
1918
    if (ddom == NULL) {
1919
        remoteDispatchConnError(rerr, conn);
1920 1921
        return -1;
    }
1922

1923 1924
    make_nonnull_domain(&ret->ddom, ddom);
    virDomainFree(ddom);
1925 1926 1927
    return 0;
}

D
Daniel Veillard 已提交
1928
static int
1929 1930 1931 1932 1933 1934 1935
remoteDispatchDomainMigratePrepare2(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_prepare2_args *args,
                                    remote_domain_migrate_prepare2_ret *ret)
D
Daniel Veillard 已提交
1936 1937 1938 1939 1940 1941 1942
{
    int r;
    char *cookie = NULL;
    int cookielen = 0;
    char *uri_in;
    char **uri_out;
    char *dname;
1943
    CHECK_CONN(client);
D
Daniel Veillard 已提交
1944 1945 1946 1947 1948 1949

    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) {
1950 1951
        remoteDispatchOOMError(rerr);
        return -1;
D
Daniel Veillard 已提交
1952 1953
    }

1954 1955 1956 1957
    r = virDomainMigratePrepare2(conn, &cookie, &cookielen,
                                 uri_in, uri_out,
                                 args->flags, dname, args->resource,
                                 args->dom_xml);
1958
    if (r == -1) {
1959
        remoteDispatchConnError(rerr, conn);
1960 1961
        return -1;
    }
D
Daniel Veillard 已提交
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973

    /* 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
1974 1975 1976 1977 1978 1979 1980
remoteDispatchDomainMigrateFinish2(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_finish2_args *args,
                                   remote_domain_migrate_finish2_ret *ret)
D
Daniel Veillard 已提交
1981 1982 1983 1984
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1985 1986 1987 1988 1989 1990
    ddom = virDomainMigrateFinish2(conn, args->dname,
                                   args->cookie.cookie_val,
                                   args->cookie.cookie_len,
                                   args->uri,
                                   args->flags,
                                   args->retcode);
1991
    if (ddom == NULL) {
1992
        remoteDispatchConnError(rerr, conn);
1993 1994
        return -1;
    }
D
Daniel Veillard 已提交
1995

1996 1997
    make_nonnull_domain(&ret->ddom, ddom);
    virDomainFree(ddom);
D
Daniel Veillard 已提交
1998 1999 2000 2001

    return 0;
}

C
Chris Lalancette 已提交
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
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;
2014
    CHECK_CONN(client);
C
Chris Lalancette 已提交
2015 2016 2017 2018 2019 2020 2021 2022 2023

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

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

2024
    r = virDomainMigratePrepareTunnel(conn, stream->st,
C
Chris Lalancette 已提交
2025 2026 2027 2028
                                      args->flags, dname, args->resource,
                                      args->dom_xml);
    if (r == -1) {
        remoteDispatchConnError(rerr, conn);
2029
        remoteFreeClientStream(client, stream);
C
Chris Lalancette 已提交
2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042
        return -1;
    }

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

    return 0;
}

2043
static int
2044 2045 2046 2047 2048 2049 2050
remoteDispatchListDefinedDomains(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_defined_domains_args *args,
                                 remote_list_defined_domains_ret *ret)
2051 2052 2053
{

    if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) {
2054
        remoteDispatchFormatError(rerr,
2055 2056
                                   "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX"));
        return -1;
2057 2058 2059
    }

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

    ret->names.names_len =
2066 2067
        virConnectListDefinedDomains(conn,
                                     ret->names.names_val, args->maxnames);
2068 2069
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
2070
        remoteDispatchConnError(rerr, conn);
2071 2072
        return -1;
    }
2073 2074 2075 2076 2077

    return 0;
}

static int
2078 2079 2080 2081 2082 2083 2084
remoteDispatchDomainLookupById(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_lookup_by_id_args *args,
                               remote_domain_lookup_by_id_ret *ret)
2085 2086 2087
{
    virDomainPtr dom;

2088
    dom = virDomainLookupByID(conn, args->id);
2089
    if (dom == NULL) {
2090
        remoteDispatchConnError(rerr, conn);
2091 2092
        return -1;
    }
2093

2094
    make_nonnull_domain(&ret->dom, dom);
2095
    virDomainFree(dom);
2096 2097 2098 2099
    return 0;
}

static int
2100 2101 2102 2103 2104 2105 2106
remoteDispatchDomainLookupByName(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_lookup_by_name_args *args,
                                 remote_domain_lookup_by_name_ret *ret)
2107 2108 2109
{
    virDomainPtr dom;

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

2116
    make_nonnull_domain(&ret->dom, dom);
2117
    virDomainFree(dom);
2118 2119 2120 2121
    return 0;
}

static int
2122 2123 2124 2125 2126 2127 2128
remoteDispatchDomainLookupByUuid(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_lookup_by_uuid_args *args,
                                 remote_domain_lookup_by_uuid_ret *ret)
2129 2130 2131
{
    virDomainPtr dom;

2132
    dom = virDomainLookupByUUID(conn, (unsigned char *) args->uuid);
2133
    if (dom == NULL) {
2134
        remoteDispatchConnError(rerr, conn);
2135 2136
        return -1;
    }
2137

2138
    make_nonnull_domain(&ret->dom, dom);
2139
    virDomainFree(dom);
2140 2141 2142 2143
    return 0;
}

static int
2144 2145 2146 2147 2148 2149 2150
remoteDispatchNumOfDefinedDomains(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_defined_domains_ret *ret)
2151 2152
{

2153
    ret->num = virConnectNumOfDefinedDomains(conn);
2154
    if (ret->num == -1) {
2155
        remoteDispatchConnError(rerr, conn);
2156 2157
        return -1;
    }
2158 2159 2160 2161 2162

    return 0;
}

static int
2163 2164 2165 2166 2167 2168 2169
remoteDispatchDomainPinVcpu(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_pin_vcpu_args *args,
                            void *ret ATTRIBUTE_UNUSED)
2170 2171 2172 2173
{
    virDomainPtr dom;
    int rv;

2174
    dom = get_nonnull_domain(conn, args->dom);
2175
    if (dom == NULL) {
2176
        remoteDispatchConnError(rerr, conn);
2177
        return -1;
2178 2179 2180
    }

    if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) {
2181
        virDomainFree(dom);
2182
        remoteDispatchFormatError(rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX"));
2183
        return -1;
2184 2185
    }

2186 2187 2188
    rv = virDomainPinVcpu(dom, args->vcpu,
                          (unsigned char *) args->cpumap.cpumap_val,
                          args->cpumap.cpumap_len);
2189
    if (rv == -1) {
2190
        remoteDispatchConnError(rerr, conn);
2191
        virDomainFree(dom);
2192 2193 2194
        return -1;
    }
    virDomainFree(dom);
2195 2196 2197 2198
    return 0;
}

static int
2199 2200 2201 2202 2203 2204 2205
remoteDispatchDomainReboot(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_reboot_args *args,
                           void *ret ATTRIBUTE_UNUSED)
2206 2207 2208
{
    virDomainPtr dom;

2209
    dom = get_nonnull_domain(conn, args->dom);
2210
    if (dom == NULL) {
2211
        remoteDispatchConnError(rerr, conn);
2212
        return -1;
2213 2214
    }

2215
    if (virDomainReboot(dom, args->flags) == -1) {
2216
        remoteDispatchConnError(rerr, conn);
2217
        virDomainFree(dom);
2218
        return -1;
2219 2220
    }
    virDomainFree(dom);
2221 2222 2223 2224
    return 0;
}

static int
2225 2226 2227 2228 2229 2230 2231
remoteDispatchDomainRestore(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_restore_args *args,
                            void *ret ATTRIBUTE_UNUSED)
2232
{
2233

2234
    if (virDomainRestore(conn, args->from) == -1) {
2235
        remoteDispatchConnError(rerr, conn);
2236
        return -1;
2237
    }
2238 2239 2240 2241 2242

    return 0;
}

static int
2243 2244 2245 2246 2247 2248 2249
remoteDispatchDomainResume(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_resume_args *args,
                           void *ret ATTRIBUTE_UNUSED)
2250 2251 2252
{
    virDomainPtr dom;

2253
    dom = get_nonnull_domain(conn, args->dom);
2254
    if (dom == NULL) {
2255
        remoteDispatchConnError(rerr, conn);
2256
        return -1;
2257 2258
    }

2259
    if (virDomainResume(dom) == -1) {
2260
        remoteDispatchConnError(rerr, conn);
2261
        virDomainFree(dom);
2262
        return -1;
2263 2264
    }
    virDomainFree(dom);
2265 2266 2267 2268
    return 0;
}

static int
2269 2270 2271 2272 2273 2274 2275
remoteDispatchDomainSave(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_save_args *args,
                         void *ret ATTRIBUTE_UNUSED)
2276 2277 2278
{
    virDomainPtr dom;

2279
    dom = get_nonnull_domain(conn, args->dom);
2280
    if (dom == NULL) {
2281
        remoteDispatchConnError(rerr, conn);
2282
        return -1;
2283 2284
    }

2285
    if (virDomainSave(dom, args->to) == -1) {
2286
        remoteDispatchConnError(rerr, conn);
2287
        virDomainFree(dom);
2288
        return -1;
2289 2290
    }
    virDomainFree(dom);
2291 2292 2293 2294
    return 0;
}

static int
2295 2296 2297 2298 2299 2300 2301
remoteDispatchDomainCoreDump(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_core_dump_args *args,
                             void *ret ATTRIBUTE_UNUSED)
2302 2303 2304
{
    virDomainPtr dom;

2305
    dom = get_nonnull_domain(conn, args->dom);
2306
    if (dom == NULL) {
2307
        remoteDispatchConnError(rerr, conn);
2308
        return -1;
2309 2310
    }

2311
    if (virDomainCoreDump(dom, args->to, args->flags) == -1) {
2312
        remoteDispatchConnError(rerr, conn);
2313
        virDomainFree(dom);
2314
        return -1;
2315 2316
    }
    virDomainFree(dom);
2317 2318 2319 2320
    return 0;
}

static int
2321 2322 2323 2324 2325 2326 2327
remoteDispatchDomainSetAutostart(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_set_autostart_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
2328 2329 2330
{
    virDomainPtr dom;

2331
    dom = get_nonnull_domain(conn, args->dom);
2332
    if (dom == NULL) {
2333
        remoteDispatchConnError(rerr, conn);
2334
        return -1;
2335 2336
    }

2337
    if (virDomainSetAutostart(dom, args->autostart) == -1) {
2338
        remoteDispatchConnError(rerr, conn);
2339
        virDomainFree(dom);
2340
        return -1;
2341 2342
    }
    virDomainFree(dom);
2343 2344 2345 2346
    return 0;
}

static int
2347 2348 2349 2350 2351 2352 2353
remoteDispatchDomainSetMaxMemory(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_set_max_memory_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
2354 2355 2356
{
    virDomainPtr dom;

2357
    dom = get_nonnull_domain(conn, args->dom);
2358
    if (dom == NULL) {
2359
        remoteDispatchConnError(rerr, conn);
2360
        return -1;
2361 2362
    }

2363
    if (virDomainSetMaxMemory(dom, args->memory) == -1) {
2364
        remoteDispatchConnError(rerr, conn);
2365
        virDomainFree(dom);
2366
        return -1;
2367 2368
    }
    virDomainFree(dom);
2369 2370 2371 2372
    return 0;
}

static int
2373 2374 2375 2376 2377 2378 2379
remoteDispatchDomainSetMemory(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_set_memory_args *args,
                              void *ret ATTRIBUTE_UNUSED)
2380 2381 2382
{
    virDomainPtr dom;

2383
    dom = get_nonnull_domain(conn, args->dom);
2384
    if (dom == NULL) {
2385
        remoteDispatchConnError(rerr, conn);
2386
        return -1;
2387 2388
    }

2389
    if (virDomainSetMemory(dom, args->memory) == -1) {
2390
        remoteDispatchConnError(rerr, conn);
2391
        virDomainFree(dom);
2392
        return -1;
2393 2394
    }
    virDomainFree(dom);
2395 2396 2397
    return 0;
}

2398
static int
2399 2400 2401 2402 2403 2404 2405
remoteDispatchDomainSetMemoryFlags(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_set_memory_flags_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
2406 2407 2408
{
    virDomainPtr dom;

2409
    dom = get_nonnull_domain(conn, args->dom);
2410 2411 2412 2413 2414
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2415
    if (virDomainSetMemoryFlags(dom, args->memory, args->flags) == -1) {
2416
        remoteDispatchConnError(rerr, conn);
2417
        virDomainFree(dom);
2418 2419 2420 2421 2422 2423
        return -1;
    }
   virDomainFree(dom);
   return 0;
}

2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508
static int
remoteDispatchDomainSetMemoryParameters(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_set_memory_parameters_args
                                        * args, void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int i, r, nparams;
    virMemoryParameterPtr params;
    unsigned int flags;

    nparams = args->params.params_len;
    flags = args->flags;

    if (nparams > REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX) {
        remoteDispatchFormatError(rerr, "%s", _("nparams too large"));
        return -1;
    }
    if (VIR_ALLOC_N(params, nparams) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

    /* Deserialise parameters. */
    for (i = 0; i < nparams; ++i) {
        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;
        }
        params[i].type = args->params.params_val[i].value.type;
        switch (params[i].type) {
            case VIR_DOMAIN_MEMORY_PARAM_INT:
                params[i].value.i =
                    args->params.params_val[i].value.
                    remote_memory_param_value_u.i;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_UINT:
                params[i].value.ui =
                    args->params.params_val[i].value.
                    remote_memory_param_value_u.ui;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_LLONG:
                params[i].value.l =
                    args->params.params_val[i].value.
                    remote_memory_param_value_u.l;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_ULLONG:
                params[i].value.ul =
                    args->params.params_val[i].value.
                    remote_memory_param_value_u.ul;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_DOUBLE:
                params[i].value.d =
                    args->params.params_val[i].value.
                    remote_memory_param_value_u.d;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_BOOLEAN:
                params[i].value.b =
                    args->params.params_val[i].value.
                    remote_memory_param_value_u.b;
                break;
        }
    }

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

    r = virDomainSetMemoryParameters(dom, params, nparams, flags);
    VIR_FREE(params);
    if (r == -1) {
        remoteDispatchConnError(rerr, conn);
2509
        virDomainFree(dom);
2510 2511
        return -1;
    }
2512
    virDomainFree(dom);
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

    return 0;
}

static int
remoteDispatchDomainGetMemoryParameters(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_memory_parameters_args
                                        * args,
                                        remote_domain_get_memory_parameters_ret
                                        * ret)
{
    virDomainPtr dom;
    virMemoryParameterPtr params;
    int i, r, nparams;
    unsigned int flags;

    nparams = args->nparams;
    flags = args->flags;

    if (nparams > REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX) {
        remoteDispatchFormatError(rerr, "%s", _("nparams too large"));
        return -1;
    }
    if (VIR_ALLOC_N(params, nparams) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

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

    r = virDomainGetMemoryParameters(dom, params, &nparams, flags);
    if (r == -1) {
2557
        remoteDispatchConnError(rerr, conn);
2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575
        virDomainFree(dom);
        VIR_FREE(params);
        return -1;
    }
    /* In this case, we need to send back the number of parameters
     * supported
     */
    if (args->nparams == 0) {
        ret->nparams = nparams;
        goto success;
    }

    /* Serialise the memory parameters. */
    ret->params.params_len = nparams;
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;

    for (i = 0; i < nparams; ++i) {
2576
        /* remoteDispatchClientRequest will free this: */
2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611
        ret->params.params_val[i].field = strdup(params[i].field);
        if (ret->params.params_val[i].field == NULL)
            goto oom;

        ret->params.params_val[i].value.type = params[i].type;
        switch (params[i].type) {
            case VIR_DOMAIN_MEMORY_PARAM_INT:
                ret->params.params_val[i].
                    value.remote_memory_param_value_u.i =
                    params[i].value.i;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_UINT:
                ret->params.params_val[i].
                    value.remote_memory_param_value_u.ui =
                    params[i].value.ui;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_LLONG:
                ret->params.params_val[i].
                    value.remote_memory_param_value_u.l =
                    params[i].value.l;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_ULLONG:
                ret->params.params_val[i].
                    value.remote_memory_param_value_u.ul =
                    params[i].value.ul;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_DOUBLE:
                ret->params.params_val[i].
                    value.remote_memory_param_value_u.d =
                    params[i].value.d;
                break;
            case VIR_DOMAIN_MEMORY_PARAM_BOOLEAN:
                ret->params.params_val[i].
                    value.remote_memory_param_value_u.b =
                    params[i].value.b;
2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719
                break;
            default:
                remoteDispatchFormatError(rerr, "%s", _("unknown type"));
                goto cleanup;
        }
    }

  success:
    virDomainFree(dom);
    VIR_FREE(params);

    return 0;

  oom:
    remoteDispatchOOMError(rerr);
  cleanup:
    virDomainFree(dom);
    for (i = 0; i < nparams; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
    return -1;
}

static int
remoteDispatchDomainSetBlkioParameters(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_set_blkio_parameters_args
                                        * args, void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int i, r, nparams;
    virBlkioParameterPtr params;
    unsigned int flags;

    nparams = args->params.params_len;
    flags = args->flags;

    if (nparams > REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX) {
        remoteDispatchFormatError(rerr, "%s", _("nparams too large"));
        return -1;
    }
    if (VIR_ALLOC_N(params, nparams) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

    /* Deserialise parameters. */
    for (i = 0; i < nparams; ++i) {
        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;
        }
        params[i].type = args->params.params_val[i].value.type;
        switch (params[i].type) {
            case VIR_DOMAIN_BLKIO_PARAM_INT:
                params[i].value.i =
                    args->params.params_val[i].value.
                    remote_blkio_param_value_u.i;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_UINT:
                params[i].value.ui =
                    args->params.params_val[i].value.
                    remote_blkio_param_value_u.ui;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_LLONG:
                params[i].value.l =
                    args->params.params_val[i].value.
                    remote_blkio_param_value_u.l;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_ULLONG:
                params[i].value.ul =
                    args->params.params_val[i].value.
                    remote_blkio_param_value_u.ul;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_DOUBLE:
                params[i].value.d =
                    args->params.params_val[i].value.
                    remote_blkio_param_value_u.d;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_BOOLEAN:
                params[i].value.b =
                    args->params.params_val[i].value.
                    remote_blkio_param_value_u.b;
                break;
        }
    }

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

    r = virDomainSetBlkioParameters(dom, params, nparams, flags);
    VIR_FREE(params);
    if (r == -1) {
        remoteDispatchConnError(rerr, conn);
2720
        virDomainFree(dom);
2721 2722
        return -1;
    }
2723
    virDomainFree(dom);
2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767

    return 0;
}

static int
remoteDispatchDomainGetBlkioParameters(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_blkio_parameters_args
                                        * args,
                                        remote_domain_get_blkio_parameters_ret
                                        * ret)
{
    virDomainPtr dom;
    virBlkioParameterPtr params;
    int i, r, nparams;
    unsigned int flags;

    nparams = args->nparams;
    flags = args->flags;

    if (nparams > REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX) {
        remoteDispatchFormatError(rerr, "%s", _("nparams too large"));
        return -1;
    }
    if (VIR_ALLOC_N(params, nparams) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
    }

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

    r = virDomainGetBlkioParameters(dom, params, &nparams, flags);
    if (r == -1) {
2768
        remoteDispatchConnError(rerr, conn);
2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822
        virDomainFree(dom);
        VIR_FREE(params);
        return -1;
    }
    /* In this case, we need to send back the number of parameters
     * supported
     */
    if (args->nparams == 0) {
        ret->nparams = nparams;
        goto success;
    }

    /* Serialise the blkio parameters. */
    ret->params.params_len = nparams;
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;

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

        ret->params.params_val[i].value.type = params[i].type;
        switch (params[i].type) {
            case VIR_DOMAIN_BLKIO_PARAM_INT:
                ret->params.params_val[i].
                    value.remote_blkio_param_value_u.i =
                    params[i].value.i;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_UINT:
                ret->params.params_val[i].
                    value.remote_blkio_param_value_u.ui =
                    params[i].value.ui;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_LLONG:
                ret->params.params_val[i].
                    value.remote_blkio_param_value_u.l =
                    params[i].value.l;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_ULLONG:
                ret->params.params_val[i].
                    value.remote_blkio_param_value_u.ul =
                    params[i].value.ul;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_DOUBLE:
                ret->params.params_val[i].
                    value.remote_blkio_param_value_u.d =
                    params[i].value.d;
                break;
            case VIR_DOMAIN_BLKIO_PARAM_BOOLEAN:
                ret->params.params_val[i].
                    value.remote_blkio_param_value_u.b =
                    params[i].value.b;
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845
                break;
            default:
                remoteDispatchFormatError(rerr, "%s", _("unknown type"));
                goto cleanup;
        }
    }

  success:
    virDomainFree(dom);
    VIR_FREE(params);

    return 0;

  oom:
    remoteDispatchOOMError(rerr);
  cleanup:
    virDomainFree(dom);
    for (i = 0; i < nparams; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
    return -1;
}

2846
static int
2847 2848 2849 2850 2851 2852 2853
remoteDispatchDomainSetVcpus(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_set_vcpus_args *args,
                             void *ret ATTRIBUTE_UNUSED)
2854 2855 2856
{
    virDomainPtr dom;

2857
    dom = get_nonnull_domain(conn, args->dom);
2858
    if (dom == NULL) {
2859
        remoteDispatchConnError(rerr, conn);
2860
        return -1;
2861 2862
    }

2863
    if (virDomainSetVcpus(dom, args->nvcpus) == -1) {
2864
        remoteDispatchConnError(rerr, conn);
2865
        virDomainFree(dom);
2866
        return -1;
2867 2868
    }
    virDomainFree(dom);
2869 2870 2871
    return 0;
}

E
Eric Blake 已提交
2872
static int
2873 2874 2875 2876 2877 2878 2879
remoteDispatchDomainSetVcpusFlags(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_set_vcpus_flags_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
E
Eric Blake 已提交
2880 2881 2882
{
    virDomainPtr dom;

2883
    dom = get_nonnull_domain(conn, args->dom);
E
Eric Blake 已提交
2884 2885 2886 2887 2888
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2889
    if (virDomainSetVcpusFlags(dom, args->nvcpus, args->flags) == -1) {
E
Eric Blake 已提交
2890
        remoteDispatchConnError(rerr, conn);
2891
        virDomainFree(dom);
E
Eric Blake 已提交
2892 2893 2894 2895 2896 2897
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

2898
static int
2899 2900 2901 2902 2903 2904 2905
remoteDispatchDomainShutdown(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_shutdown_args *args,
                             void *ret ATTRIBUTE_UNUSED)
2906 2907 2908
{
    virDomainPtr dom;

2909
    dom = get_nonnull_domain(conn, args->dom);
2910
    if (dom == NULL) {
2911
        remoteDispatchConnError(rerr, conn);
2912
        return -1;
2913 2914
    }

2915
    if (virDomainShutdown(dom) == -1) {
2916
        remoteDispatchConnError(rerr, conn);
2917
        virDomainFree(dom);
2918
        return -1;
2919 2920
    }
    virDomainFree(dom);
2921 2922 2923 2924
    return 0;
}

static int
2925 2926 2927 2928 2929 2930 2931
remoteDispatchDomainSuspend(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_suspend_args *args,
                            void *ret ATTRIBUTE_UNUSED)
2932 2933 2934
{
    virDomainPtr dom;

2935
    dom = get_nonnull_domain(conn, args->dom);
2936
    if (dom == NULL) {
2937
        remoteDispatchConnError(rerr, conn);
2938
        return -1;
2939 2940
    }

2941
    if (virDomainSuspend(dom) == -1) {
2942
        remoteDispatchConnError(rerr, conn);
2943
        virDomainFree(dom);
2944
        return -1;
2945 2946
    }
    virDomainFree(dom);
2947 2948 2949 2950
    return 0;
}

static int
2951 2952 2953 2954 2955 2956 2957
remoteDispatchDomainUndefine(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_undefine_args *args,
                             void *ret ATTRIBUTE_UNUSED)
2958 2959 2960
{
    virDomainPtr dom;

2961
    dom = get_nonnull_domain(conn, args->dom);
2962
    if (dom == NULL) {
2963
        remoteDispatchConnError(rerr, conn);
2964
        return -1;
2965 2966
    }

2967
    if (virDomainUndefine(dom) == -1) {
2968
        remoteDispatchConnError(rerr, conn);
2969
        virDomainFree(dom);
2970
        return -1;
2971 2972
    }
    virDomainFree(dom);
2973 2974 2975 2976
    return 0;
}

static int
2977 2978 2979 2980 2981 2982 2983
remoteDispatchListDefinedNetworks(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_defined_networks_args *args,
                                  remote_list_defined_networks_ret *ret)
2984 2985 2986
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2987
        remoteDispatchFormatError(rerr,
2988 2989
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2990 2991 2992
    }

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

    ret->names.names_len =
2999 3000
        virConnectListDefinedNetworks(conn,
                                      ret->names.names_val, args->maxnames);
3001 3002
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3003
        remoteDispatchConnError(rerr, conn);
3004 3005
        return -1;
    }
3006 3007 3008 3009 3010

    return 0;
}

static int
3011 3012 3013 3014 3015 3016 3017
remoteDispatchListDomains(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_domains_args *args,
                          remote_list_domains_ret *ret)
3018 3019 3020
{

    if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
3021
        remoteDispatchFormatError(rerr,
3022 3023
                                   "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX"));
        return -1;
3024 3025 3026
    }

    /* Allocate return buffer. */
3027
    if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) {
3028 3029
        remoteDispatchOOMError(rerr);
        return -1;
3030
    }
3031

3032 3033
    ret->ids.ids_len = virConnectListDomains(conn,
                                             ret->ids.ids_val, args->maxids);
3034 3035
    if (ret->ids.ids_len == -1) {
        VIR_FREE(ret->ids.ids_val);
3036
        remoteDispatchConnError(rerr, conn);
3037 3038
        return -1;
    }
3039 3040 3041 3042

    return 0;
}

3043
static int
3044 3045 3046 3047 3048 3049 3050
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)
3051 3052 3053
{
    virDomainPtr dom;

3054
    dom = get_nonnull_domain(conn, args->dom);
3055 3056 3057 3058 3059
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3060
    if (virDomainManagedSave(dom, args->flags) == -1) {
3061
        remoteDispatchConnError(rerr, conn);
3062
        virDomainFree(dom);
3063 3064 3065 3066 3067 3068 3069
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

static int
3070 3071 3072 3073 3074 3075 3076
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)
3077 3078 3079
{
    virDomainPtr dom;

3080
    dom = get_nonnull_domain(conn, args->dom);
3081 3082 3083 3084 3085
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3086
    ret->ret = virDomainHasManagedSaveImage(dom, args->flags);
3087 3088
    if (ret->ret == -1) {
        remoteDispatchConnError(rerr, conn);
3089
        virDomainFree(dom);
3090 3091 3092 3093 3094 3095 3096
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

static int
3097 3098 3099 3100 3101 3102 3103
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)
3104 3105 3106
{
    virDomainPtr dom;

3107
    dom = get_nonnull_domain(conn, args->dom);
3108 3109 3110 3111 3112
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3113
    if (virDomainManagedSaveRemove(dom, args->flags) == -1) {
3114
        remoteDispatchConnError(rerr, conn);
3115
        virDomainFree(dom);
3116 3117 3118 3119 3120 3121
        return -1;
    }
    virDomainFree(dom);
    return 0;
}

3122
static int
3123 3124 3125 3126 3127 3128 3129
remoteDispatchListNetworks(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_networks_args *args,
                           remote_list_networks_ret *ret)
3130 3131 3132
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
3133
        remoteDispatchFormatError(rerr,
3134 3135
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
3136 3137 3138
    }

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

    ret->names.names_len =
3145 3146
        virConnectListNetworks(conn,
                               ret->names.names_val, args->maxnames);
3147 3148
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
3149
        remoteDispatchConnError(rerr, conn);
3150 3151
        return -1;
    }
3152 3153 3154 3155 3156

    return 0;
}

static int
3157 3158 3159 3160 3161 3162 3163
remoteDispatchNetworkCreate(struct qemud_server *server ATTRIBUTE_UNUSED,
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                            remote_error *rerr,
                            remote_network_create_args *args,
                            void *ret ATTRIBUTE_UNUSED)
3164 3165 3166
{
    virNetworkPtr net;

3167
    net = get_nonnull_network(conn, args->net);
3168
    if (net == NULL) {
3169
        remoteDispatchConnError(rerr, conn);
3170
        return -1;
3171 3172
    }

3173
    if (virNetworkCreate(net) == -1) {
3174
        remoteDispatchConnError(rerr, conn);
3175
        virNetworkFree(net);
3176
        return -1;
3177 3178
    }
    virNetworkFree(net);
3179 3180 3181 3182
    return 0;
}

static int
3183 3184 3185 3186 3187 3188 3189
remoteDispatchNetworkCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *rerr,
                               remote_network_create_xml_args *args,
                               remote_network_create_xml_ret *ret)
3190 3191 3192
{
    virNetworkPtr net;

3193
    net = virNetworkCreateXML(conn, args->xml);
3194
    if (net == NULL) {
3195
        remoteDispatchConnError(rerr, conn);
3196 3197
        return -1;
    }
3198

3199
    make_nonnull_network(&ret->net, net);
3200
    virNetworkFree(net);
3201 3202 3203 3204
    return 0;
}

static int
3205 3206 3207 3208 3209 3210 3211
remoteDispatchNetworkDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *rerr,
                               remote_network_define_xml_args *args,
                               remote_network_define_xml_ret *ret)
3212 3213 3214
{
    virNetworkPtr net;

3215
    net = virNetworkDefineXML(conn, args->xml);
3216
    if (net == NULL) {
3217
        remoteDispatchConnError(rerr, conn);
3218 3219
        return -1;
    }
3220

3221
    make_nonnull_network(&ret->net, net);
3222
    virNetworkFree(net);
3223 3224 3225 3226
    return 0;
}

static int
3227 3228 3229 3230 3231 3232 3233
remoteDispatchNetworkDestroy(struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *rerr,
                             remote_network_destroy_args *args,
                             void *ret ATTRIBUTE_UNUSED)
3234 3235 3236
{
    virNetworkPtr net;

3237
    net = get_nonnull_network(conn, args->net);
3238
    if (net == NULL) {
3239
        remoteDispatchConnError(rerr, conn);
3240
        return -1;
3241 3242
    }

3243
    if (virNetworkDestroy(net) == -1) {
3244
        remoteDispatchConnError(rerr, conn);
3245
        virNetworkFree(net);
3246
        return -1;
3247 3248
    }
    virNetworkFree(net);
3249 3250 3251 3252
    return 0;
}

static int
3253 3254 3255 3256 3257 3258 3259
remoteDispatchNetworkDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *rerr,
                             remote_network_dump_xml_args *args,
                             remote_network_dump_xml_ret *ret)
3260 3261 3262
{
    virNetworkPtr net;

3263
    net = get_nonnull_network(conn, args->net);
3264
    if (net == NULL) {
3265
        remoteDispatchConnError(rerr, conn);
3266
        return -1;
3267 3268 3269
    }

    /* remoteDispatchClientRequest will free this. */
3270
    ret->xml = virNetworkGetXMLDesc(net, args->flags);
3271
    if (!ret->xml) {
3272
        remoteDispatchConnError(rerr, conn);
3273
        virNetworkFree(net);
3274 3275 3276
        return -1;
    }
    virNetworkFree(net);
3277 3278 3279 3280
    return 0;
}

static int
3281 3282 3283 3284 3285 3286 3287
remoteDispatchNetworkGetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_network_get_autostart_args *args,
                                  remote_network_get_autostart_ret *ret)
3288 3289 3290
{
    virNetworkPtr net;

3291
    net = get_nonnull_network(conn, args->net);
3292
    if (net == NULL) {
3293
        remoteDispatchConnError(rerr, conn);
3294
        return -1;
3295 3296
    }

3297
    if (virNetworkGetAutostart(net, &ret->autostart) == -1) {
3298
        remoteDispatchConnError(rerr, conn);
3299
        virNetworkFree(net);
3300
        return -1;
3301 3302
    }
    virNetworkFree(net);
3303 3304 3305 3306
    return 0;
}

static int
3307 3308 3309 3310 3311 3312 3313
remoteDispatchNetworkGetBridgeName(struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
                                   remote_error *rerr,
                                   remote_network_get_bridge_name_args *args,
                                   remote_network_get_bridge_name_ret *ret)
3314 3315 3316
{
    virNetworkPtr net;

3317
    net = get_nonnull_network(conn, args->net);
3318
    if (net == NULL) {
3319
        remoteDispatchConnError(rerr, conn);
3320
        return -1;
3321 3322 3323
    }

    /* remoteDispatchClientRequest will free this. */
3324
    ret->name = virNetworkGetBridgeName(net);
3325
    if (!ret->name) {
3326
        remoteDispatchConnError(rerr, conn);
3327
        virNetworkFree(net);
3328 3329 3330
        return -1;
    }
    virNetworkFree(net);
3331 3332 3333 3334
    return 0;
}

static int
3335 3336 3337 3338 3339 3340 3341
remoteDispatchNetworkLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_network_lookup_by_name_args *args,
                                  remote_network_lookup_by_name_ret *ret)
3342 3343 3344
{
    virNetworkPtr net;

3345
    net = virNetworkLookupByName(conn, args->name);
3346
    if (net == NULL) {
3347
        remoteDispatchConnError(rerr, conn);
3348 3349
        return -1;
    }
3350

3351
    make_nonnull_network(&ret->net, net);
3352
    virNetworkFree(net);
3353 3354 3355 3356
    return 0;
}

static int
3357 3358 3359 3360 3361 3362 3363
remoteDispatchNetworkLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_network_lookup_by_uuid_args *args,
                                  remote_network_lookup_by_uuid_ret *ret)
3364 3365 3366
{
    virNetworkPtr net;

3367
    net = virNetworkLookupByUUID(conn, (unsigned char *) args->uuid);
3368
    if (net == NULL) {
3369
        remoteDispatchConnError(rerr, conn);
3370 3371
        return -1;
    }
3372

3373
    make_nonnull_network(&ret->net, net);
3374
    virNetworkFree(net);
3375 3376 3377 3378
    return 0;
}

static int
3379 3380 3381 3382 3383 3384 3385
remoteDispatchNetworkSetAutostart(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_network_set_autostart_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
3386 3387 3388
{
    virNetworkPtr net;

3389
    net = get_nonnull_network(conn, args->net);
3390
    if (net == NULL) {
3391
        remoteDispatchConnError(rerr, conn);
3392
        return -1;
3393 3394
    }

3395
    if (virNetworkSetAutostart(net, args->autostart) == -1) {
3396
        remoteDispatchConnError(rerr, conn);
3397
        virNetworkFree(net);
3398
        return -1;
3399 3400
    }
    virNetworkFree(net);
3401 3402 3403 3404
    return 0;
}

static int
3405 3406 3407 3408 3409 3410 3411
remoteDispatchNetworkUndefine(struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *rerr,
                              remote_network_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
3412 3413 3414
{
    virNetworkPtr net;

3415
    net = get_nonnull_network(conn, args->net);
3416
    if (net == NULL) {
3417
        remoteDispatchConnError(rerr, conn);
3418
        return -1;
3419 3420
    }

3421
    if (virNetworkUndefine(net) == -1) {
3422
        remoteDispatchConnError(rerr, conn);
3423
        virNetworkFree(net);
3424
        return -1;
3425 3426
    }
    virNetworkFree(net);
3427 3428 3429 3430
    return 0;
}

static int
3431 3432 3433 3434 3435 3436 3437
remoteDispatchNumOfDefinedNetworks(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_defined_networks_ret *ret)
3438 3439
{

3440
    ret->num = virConnectNumOfDefinedNetworks(conn);
3441
    if (ret->num == -1) {
3442
        remoteDispatchConnError(rerr, conn);
3443 3444
        return -1;
    }
3445 3446 3447 3448 3449

    return 0;
}

static int
3450 3451 3452 3453 3454 3455 3456
remoteDispatchNumOfDomains(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_domains_ret *ret)
3457 3458
{

3459
    ret->num = virConnectNumOfDomains(conn);
3460
    if (ret->num == -1) {
3461
        remoteDispatchConnError(rerr, conn);
3462 3463
        return -1;
    }
3464 3465 3466 3467 3468

    return 0;
}

static int
3469 3470 3471 3472 3473 3474 3475
remoteDispatchNumOfNetworks(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_networks_ret *ret)
3476 3477
{

3478
    ret->num = virConnectNumOfNetworks(conn);
3479
    if (ret->num == -1) {
3480
        remoteDispatchConnError(rerr, conn);
3481 3482
        return -1;
    }
3483 3484 3485 3486

    return 0;
}

3487

D
Daniel Veillard 已提交
3488 3489
/*-------------------------------------------------------------*/
static int
3490 3491 3492 3493 3494 3495 3496
remoteDispatchNumOfInterfaces(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_interfaces_ret *ret)
D
Daniel Veillard 已提交
3497 3498
{

3499
    ret->num = virConnectNumOfInterfaces(conn);
D
Daniel Veillard 已提交
3500 3501 3502 3503 3504 3505 3506 3507 3508
    if (ret->num == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

static int
3509 3510 3511 3512 3513 3514 3515
remoteDispatchListInterfaces(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_interfaces_args *args,
                             remote_list_interfaces_ret *ret)
D
Daniel Veillard 已提交
3516 3517 3518
{

    if (args->maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) {
3519
        remoteDispatchFormatError(rerr,
D
Daniel Veillard 已提交
3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530
                                   "%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 =
3531 3532
        virConnectListInterfaces(conn,
                                 ret->names.names_val, args->maxnames);
D
Daniel Veillard 已提交
3533 3534 3535 3536 3537 3538 3539 3540 3541
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

3542
static int
3543 3544 3545 3546 3547 3548 3549
remoteDispatchNumOfDefinedInterfaces(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_defined_interfaces_ret *ret)
3550 3551
{

3552
    ret->num = virConnectNumOfDefinedInterfaces(conn);
3553 3554 3555 3556 3557 3558 3559 3560 3561
    if (ret->num == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

static int
3562 3563 3564 3565 3566 3567 3568
remoteDispatchListDefinedInterfaces(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_defined_interfaces_args *args,
                                    remote_list_defined_interfaces_ret *ret)
3569 3570 3571
{

    if (args->maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) {
3572
        remoteDispatchFormatError(rerr,
3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583
                                   "%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 =
3584 3585
        virConnectListDefinedInterfaces(conn,
                                        ret->names.names_val, args->maxnames);
3586 3587 3588 3589 3590 3591 3592 3593 3594
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}

D
Daniel Veillard 已提交
3595
static int
3596 3597 3598 3599 3600 3601 3602
remoteDispatchInterfaceLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED,
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
                                    remote_error *rerr,
                                    remote_interface_lookup_by_name_args *args,
                                    remote_interface_lookup_by_name_ret *ret)
D
Daniel Veillard 已提交
3603
{
3604
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3605

3606
    iface = virInterfaceLookupByName(conn, args->name);
3607
    if (iface == NULL) {
D
Daniel Veillard 已提交
3608 3609 3610 3611
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3612
    make_nonnull_interface(&ret->iface, iface);
3613
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3614 3615 3616 3617
    return 0;
}

static int
3618 3619 3620 3621 3622 3623 3624
remoteDispatchInterfaceLookupByMacString(struct qemud_server *server ATTRIBUTE_UNUSED,
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
                                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                                         remote_error *rerr,
                                         remote_interface_lookup_by_mac_string_args *args,
                                         remote_interface_lookup_by_mac_string_ret *ret)
D
Daniel Veillard 已提交
3625
{
3626
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3627

3628
    iface = virInterfaceLookupByMACString(conn, args->mac);
3629
    if (iface == NULL) {
D
Daniel Veillard 已提交
3630 3631 3632 3633
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3634
    make_nonnull_interface(&ret->iface, iface);
3635
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3636 3637
    return 0;
}
3638 3639 3640 3641 3642 3643 3644 3645 3646

static int
remoteDispatchInterfaceGetXmlDesc(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_interface_get_xml_desc_args *args,
                                  remote_interface_get_xml_desc_ret *ret)
D
Daniel Veillard 已提交
3647
{
3648
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3649

3650
    iface = get_nonnull_interface(conn, args->iface);
3651
    if (iface == NULL) {
D
Daniel Veillard 已提交
3652 3653 3654 3655 3656
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* remoteDispatchClientRequest will free this. */
3657
    ret->xml = virInterfaceGetXMLDesc(iface, args->flags);
D
Daniel Veillard 已提交
3658 3659
    if (!ret->xml) {
        remoteDispatchConnError(rerr, conn);
3660
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3661 3662
        return -1;
    }
3663
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3664 3665 3666 3667
    return 0;
}

static int
3668 3669 3670 3671 3672 3673 3674
remoteDispatchInterfaceDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_interface_define_xml_args *args,
                                 remote_interface_define_xml_ret *ret)
D
Daniel Veillard 已提交
3675
{
3676
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3677

3678
    iface = virInterfaceDefineXML(conn, args->xml, args->flags);
3679
    if (iface == NULL) {
D
Daniel Veillard 已提交
3680 3681 3682 3683
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3684
    make_nonnull_interface(&ret->iface, iface);
3685
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3686 3687 3688 3689
    return 0;
}

static int
3690 3691 3692 3693 3694 3695 3696
remoteDispatchInterfaceUndefine(struct qemud_server *server ATTRIBUTE_UNUSED,
                                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 已提交
3697
{
3698
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3699

3700
    iface = get_nonnull_interface(conn, args->iface);
3701
    if (iface == NULL) {
D
Daniel Veillard 已提交
3702 3703 3704 3705
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3706
    if (virInterfaceUndefine(iface) == -1) {
D
Daniel Veillard 已提交
3707
        remoteDispatchConnError(rerr, conn);
3708
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3709 3710
        return -1;
    }
3711
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3712 3713 3714 3715
    return 0;
}

static int
3716 3717 3718 3719 3720 3721 3722
remoteDispatchInterfaceCreate(struct qemud_server *server ATTRIBUTE_UNUSED,
                              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 已提交
3723
{
3724
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3725

3726
    iface = get_nonnull_interface(conn, args->iface);
3727
    if (iface == NULL) {
D
Daniel Veillard 已提交
3728 3729 3730 3731
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3732
    if (virInterfaceCreate(iface, args->flags) == -1) {
D
Daniel Veillard 已提交
3733
        remoteDispatchConnError(rerr, conn);
3734
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3735 3736
        return -1;
    }
3737
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3738 3739 3740 3741
    return 0;
}

static int
3742 3743 3744 3745 3746 3747 3748
remoteDispatchInterfaceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED,
                               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 已提交
3749
{
3750
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3751

3752
    iface = get_nonnull_interface(conn, args->iface);
3753
    if (iface == NULL) {
D
Daniel Veillard 已提交
3754 3755 3756 3757
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3758
    if (virInterfaceDestroy(iface, args->flags) == -1) {
D
Daniel Veillard 已提交
3759
        remoteDispatchConnError(rerr, conn);
3760
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3761 3762
        return -1;
    }
3763
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3764 3765 3766 3767 3768
    return 0;
}

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

3769
static int
3770 3771 3772 3773 3774 3775 3776
remoteDispatchAuthList(struct qemud_server *server,
                       struct qemud_client *client,
                       virConnectPtr conn ATTRIBUTE_UNUSED,
                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                       remote_error *rerr,
                       void *args ATTRIBUTE_UNUSED,
                       remote_auth_list_ret *ret)
3777 3778
{
    ret->types.types_len = 1;
3779
    if (VIR_ALLOC_N(ret->types.types_val, ret->types.types_len) < 0) {
3780 3781
        remoteDispatchOOMError(rerr);
        return -1;
3782
    }
3783 3784 3785
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3786
    ret->types.types_val[0] = client->auth;
3787
    virMutexUnlock(&client->lock);
3788

3789 3790 3791 3792 3793 3794 3795
    return 0;
}


#if HAVE_SASL
/*
 * Initializes the SASL session in prepare for authentication
3796
 * and gives the client a list of allowed mechanisms to choose
3797 3798 3799 3800
 *
 * XXX callbacks for stuff like password verification ?
 */
static int
3801 3802 3803 3804 3805 3806 3807
remoteDispatchAuthSaslInit(struct qemud_server *server,
                           struct qemud_client *client,
                           virConnectPtr conn,
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                           remote_error *rerr,
                           void *args ATTRIBUTE_UNUSED,
                           remote_auth_sasl_init_ret *ret)
3808 3809
{
    const char *mechlist = NULL;
3810
    sasl_security_properties_t secprops;
3811
    int err;
3812
    virSocketAddr sa;
3813 3814
    char *localAddr, *remoteAddr;

3815 3816 3817
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3818

3819 3820 3821
    REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn != NULL) {
3822
        VIR_ERROR0(_("client tried invalid SASL init request"));
3823
        goto authfail;
3824 3825 3826
    }

    /* Get local address in form  IPADDR:PORT */
3827 3828
    sa.len = sizeof(sa.data.stor);
    if (getsockname(client->fd, &sa.data.sa, &sa.len) < 0) {
3829
        char ebuf[1024];
3830
        remoteDispatchFormatError(rerr,
3831
                                  _("failed to get sock address: %s"),
3832
                                  virStrerror(errno, ebuf, sizeof ebuf));
3833
        goto error;
3834
    }
3835 3836
    if ((localAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) {
        remoteDispatchConnError(rerr, conn);
3837
        goto error;
3838 3839 3840
    }

    /* Get remote address in form  IPADDR:PORT */
3841 3842
    sa.len = sizeof(sa.data.stor);
    if (getpeername(client->fd, &sa.data.sa, &sa.len) < 0) {
3843
        char ebuf[1024];
3844
        remoteDispatchFormatError(rerr, _("failed to get peer address: %s"),
3845
                                  virStrerror(errno, ebuf, sizeof ebuf));
3846
        VIR_FREE(localAddr);
3847
        goto error;
3848
    }
3849
    if ((remoteAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL) {
3850
        VIR_FREE(localAddr);
3851
        remoteDispatchConnError(rerr, conn);
3852
        goto error;
3853 3854 3855 3856 3857 3858 3859 3860 3861 3862
    }

    err = sasl_server_new("libvirt",
                          NULL, /* FQDN - just delegates to gethostname */
                          NULL, /* User realm */
                          localAddr,
                          remoteAddr,
                          NULL, /* XXX Callbacks */
                          SASL_SUCCESS_DATA,
                          &client->saslconn);
3863 3864
    VIR_FREE(localAddr);
    VIR_FREE(remoteAddr);
3865
    if (err != SASL_OK) {
3866 3867
        VIR_ERROR(_("sasl context setup failed %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3868
        client->saslconn = NULL;
3869
        goto authfail;
3870 3871
    }

3872 3873 3874 3875 3876 3877 3878
    /* 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 已提交
3879
            VIR_ERROR0(_("cannot get TLS cipher size"));
3880 3881
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
3882
            goto authfail;
3883 3884 3885 3886 3887
        }
        ssf *= 8; /* tls key size is bytes, sasl wants bits */

        err = sasl_setprop(client->saslconn, SASL_SSF_EXTERNAL, &ssf);
        if (err != SASL_OK) {
3888 3889
            VIR_ERROR(_("cannot set SASL external SSF %d (%s)"),
                      err, sasl_errstring(err, NULL, NULL));
3890 3891
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
3892
            goto authfail;
3893 3894 3895
        }
    }

3896
    memset(&secprops, 0, sizeof secprops);
3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915
    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) {
3916 3917
        VIR_ERROR(_("cannot set SASL security props %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3918 3919
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3920
        goto authfail;
3921 3922
    }

3923 3924 3925 3926 3927 3928 3929 3930 3931
    err = sasl_listmech(client->saslconn,
                        NULL, /* Don't need to set user */
                        "", /* Prefix */
                        ",", /* Separator */
                        "", /* Suffix */
                        &mechlist,
                        NULL,
                        NULL);
    if (err != SASL_OK) {
3932 3933
        VIR_ERROR(_("cannot list SASL mechanisms %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3934 3935
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3936
        goto authfail;
3937 3938 3939 3940
    }
    REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist);
    ret->mechlist = strdup(mechlist);
    if (!ret->mechlist) {
3941
        VIR_ERROR0(_("cannot allocate mechlist"));
3942 3943
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3944
        goto authfail;
3945 3946
    }

3947
    virMutexUnlock(&client->lock);
3948
    return 0;
3949 3950 3951 3952

authfail:
    remoteDispatchAuthError(rerr);
error:
3953
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_SASL);
3954
    virMutexUnlock(&client->lock);
3955
    return -1;
3956 3957 3958
}


3959
/* We asked for an SSF layer, so sanity check that we actually
3960 3961 3962
 * got what we asked for
 * Returns 0 if ok, -1 on error, -2 if rejected
 */
3963
static int
3964 3965
remoteSASLCheckSSF(struct qemud_client *client,
                   remote_error *rerr) {
3966 3967 3968 3969 3970 3971 3972 3973 3974
    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) {
3975 3976
        VIR_ERROR(_("cannot query SASL ssf on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3977
        remoteDispatchAuthError(rerr);
3978 3979 3980 3981 3982 3983 3984
        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 */
3985
        VIR_ERROR(_("negotiated SSF %d was not strong enough"), ssf);
3986
        remoteDispatchAuthError(rerr);
3987 3988
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3989
        return -2;
3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003
    }

    /* 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;
}

4004 4005 4006
/*
 * Returns 0 if ok, -1 on error, -2 if rejected
 */
4007
static int
4008 4009 4010
remoteSASLCheckAccess(struct qemud_server *server,
                      struct qemud_client *client,
                      remote_error *rerr) {
4011 4012 4013 4014 4015 4016
    const void *val;
    int err;
    char **wildcards;

    err = sasl_getprop(client->saslconn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
4017 4018
        VIR_ERROR(_("cannot query SASL username on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
4019
        remoteDispatchAuthError(rerr);
4020 4021 4022 4023 4024
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    if (val == NULL) {
4025
        VIR_ERROR0(_("no client username was found"));
4026
        remoteDispatchAuthError(rerr);
4027 4028 4029 4030 4031 4032 4033 4034
        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) {
4035
        VIR_ERROR0(_("out of memory copying username"));
4036
        remoteDispatchAuthError(rerr);
4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047
        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) {
4048
        if (fnmatch(*wildcards, client->saslUsername, 0) == 0)
4049 4050 4051 4052 4053
            return 0; /* Allowed */
        wildcards++;
    }

    /* Denied */
4054
    VIR_ERROR(_("SASL client %s not allowed in whitelist"), client->saslUsername);
4055
    remoteDispatchAuthError(rerr);
4056 4057
    sasl_dispose(&client->saslconn);
    client->saslconn = NULL;
4058
    return -2;
4059 4060 4061
}


4062 4063 4064 4065
/*
 * This starts the SASL authentication negotiation.
 */
static int
4066 4067 4068 4069 4070 4071 4072
remoteDispatchAuthSaslStart(struct qemud_server *server,
                            struct qemud_client *client,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                            remote_error *rerr,
                            remote_auth_sasl_start_args *args,
                            remote_auth_sasl_start_ret *ret)
4073 4074 4075 4076 4077
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

4078 4079 4080
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
4081

4082 4083 4084
    REMOTE_DEBUG("Start SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
4085
        VIR_ERROR0(_("client tried invalid SASL start request"));
4086
        goto authfail;
4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099
    }

    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) {
4100 4101
        VIR_ERROR(_("sasl start failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
4102 4103
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
4104
        goto authfail;
4105 4106
    }
    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
4107
        VIR_ERROR(_("sasl start reply data too long %d"), serveroutlen);
4108 4109
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
4110
        goto authfail;
4111 4112 4113 4114
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
4115
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
4116
            remoteDispatchOOMError(rerr);
4117
            goto error;
4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129
        }
        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 {
4130
        /* Check username whitelist ACL */
4131 4132 4133 4134 4135 4136 4137
        if ((err = remoteSASLCheckAccess(server, client, rerr)) < 0 ||
            (err = remoteSASLCheckSSF(client, rerr)) < 0) {
            if (err == -2)
                goto authdeny;
            else
                goto authfail;
        }
4138

4139
        REMOTE_DEBUG("Authentication successful %d", client->fd);
4140 4141
        PROBE(CLIENT_AUTH_ALLOW, "fd=%d, auth=%d, username=%s",
              client->fd, REMOTE_AUTH_SASL, client->saslUsername);
4142 4143 4144 4145
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

4146
    virMutexUnlock(&client->lock);
4147
    return 0;
4148 4149

authfail:
4150
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_SASL);
4151
    remoteDispatchAuthError(rerr);
4152 4153 4154
    goto error;

authdeny:
4155 4156
    PROBE(CLIENT_AUTH_DENY, "fd=%d, auth=%d, username=%s",
          client->fd, REMOTE_AUTH_SASL, client->saslUsername);
4157 4158
    goto error;

4159
error:
4160
    virMutexUnlock(&client->lock);
4161
    return -1;
4162 4163 4164 4165
}


static int
4166 4167 4168 4169 4170 4171 4172
remoteDispatchAuthSaslStep(struct qemud_server *server,
                           struct qemud_client *client,
                           virConnectPtr conn ATTRIBUTE_UNUSED,
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                           remote_error *rerr,
                           remote_auth_sasl_step_args *args,
                           remote_auth_sasl_step_ret *ret)
4173 4174 4175 4176 4177
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

4178 4179 4180
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
4181

4182 4183 4184
    REMOTE_DEBUG("Step SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
4185
        VIR_ERROR0(_("client tried invalid SASL start request"));
4186
        goto authfail;
4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198
    }

    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) {
4199 4200
        VIR_ERROR(_("sasl step failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
4201 4202
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
4203
        goto authfail;
4204 4205 4206
    }

    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
4207 4208
        VIR_ERROR(_("sasl step reply data too long %d"),
                  serveroutlen);
4209 4210
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
4211
        goto authfail;
4212 4213 4214 4215
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
4216
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
4217
            remoteDispatchOOMError(rerr);
4218
            goto error;
4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230
        }
        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 {
4231
        /* Check username whitelist ACL */
4232 4233 4234 4235 4236 4237 4238
        if ((err = remoteSASLCheckAccess(server, client, rerr)) < 0 ||
            (err = remoteSASLCheckSSF(client, rerr)) < 0) {
            if (err == -2)
                goto authdeny;
            else
                goto authfail;
        }
4239

4240
        REMOTE_DEBUG("Authentication successful %d", client->fd);
4241 4242
        PROBE(CLIENT_AUTH_ALLOW, "fd=%d, auth=%d, username=%s",
              client->fd, REMOTE_AUTH_SASL, client->saslUsername);
4243 4244 4245 4246
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

4247
    virMutexUnlock(&client->lock);
4248
    return 0;
4249 4250

authfail:
4251
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_SASL);
4252
    remoteDispatchAuthError(rerr);
4253 4254 4255
    goto error;

authdeny:
4256 4257
    PROBE(CLIENT_AUTH_DENY, "fd=%d, auth=%d, username=%s",
          client->fd, REMOTE_AUTH_SASL, client->saslUsername);
4258 4259
    goto error;

4260
error:
4261
    virMutexUnlock(&client->lock);
4262
    return -1;
4263 4264 4265 4266 4267
}


#else /* HAVE_SASL */
static int
4268 4269 4270 4271 4272 4273 4274
remoteDispatchAuthSaslInit(struct qemud_server *server ATTRIBUTE_UNUSED,
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn ATTRIBUTE_UNUSED,
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                           remote_error *rerr,
                           void *args ATTRIBUTE_UNUSED,
                           remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED)
4275
{
4276
    VIR_ERROR0(_("client tried unsupported SASL init request"));
4277
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_SASL);
4278
    remoteDispatchAuthError(rerr);
4279 4280 4281 4282
    return -1;
}

static int
4283 4284 4285 4286 4287 4288 4289
remoteDispatchAuthSaslStart(struct qemud_server *server ATTRIBUTE_UNUSED,
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                            remote_error *rerr,
                            remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED)
4290
{
4291
    VIR_ERROR0(_("client tried unsupported SASL start request"));
4292
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_SASL);
4293
    remoteDispatchAuthError(rerr);
4294 4295 4296 4297
    return -1;
}

static int
4298 4299 4300 4301 4302 4303 4304
remoteDispatchAuthSaslStep(struct qemud_server *server ATTRIBUTE_UNUSED,
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn ATTRIBUTE_UNUSED,
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                           remote_error *rerr,
                           remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED,
                           remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED)
4305
{
4306
    VIR_ERROR0(_("client tried unsupported SASL step request"));
4307
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_SASL);
4308
    remoteDispatchAuthError(rerr);
4309 4310 4311 4312 4313
    return -1;
}
#endif /* HAVE_SASL */


4314 4315
#if HAVE_POLKIT1
static int
4316 4317 4318 4319 4320 4321 4322
remoteDispatchAuthPolkit(struct qemud_server *server,
                         struct qemud_client *client,
                         virConnectPtr conn ATTRIBUTE_UNUSED,
                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                         remote_error *rerr,
                         void *args ATTRIBUTE_UNUSED,
                         remote_auth_polkit_ret *ret)
4323
{
4324 4325
    pid_t callerPid = -1;
    uid_t callerUid = -1;
4326 4327 4328
    const char *action;
    int status = -1;
    char pidbuf[50];
4329
    char ident[100];
4330 4331
    int rv;

4332 4333
    memset(ident, 0, sizeof ident);

4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365
    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);
4366
        goto authfail;
4367 4368
    }

4369 4370 4371 4372 4373 4374
    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;
    }

4375
    if (virRun(pkcheck, &status) < 0) {
4376
        VIR_ERROR(_("Cannot invoke %s"), PKCHECK_PATH);
4377
        goto authfail;
4378 4379
    }
    if (status != 0) {
4380 4381 4382 4383
        char *tmp = virCommandTranslateStatus(status);
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d: %s"),
                  action, callerPid, callerUid, NULLSTR(tmp));
        VIR_FREE(tmp);
4384
        goto authdeny;
4385
    }
4386
    PROBE(CLIENT_AUTH_ALLOW, "fd=%d, auth=%d, username=%s",
M
Matthias Bolte 已提交
4387
          client->fd, REMOTE_AUTH_POLKIT, (char *)ident);
4388 4389 4390 4391 4392 4393 4394 4395 4396
    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:
4397
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_POLKIT);
4398 4399 4400
    goto error;

authdeny:
4401
    PROBE(CLIENT_AUTH_DENY, "fd=%d, auth=%d, username=%s",
M
Matthias Bolte 已提交
4402
          client->fd, REMOTE_AUTH_POLKIT, (char *)ident);
4403 4404 4405
    goto error;

error:
4406 4407 4408 4409 4410
    remoteDispatchAuthError(rerr);
    virMutexUnlock(&client->lock);
    return -1;
}
#elif HAVE_POLKIT0
4411
static int
4412 4413 4414 4415 4416 4417 4418
remoteDispatchAuthPolkit(struct qemud_server *server,
                         struct qemud_client *client,
                         virConnectPtr conn ATTRIBUTE_UNUSED,
                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                         remote_error *rerr,
                         void *args ATTRIBUTE_UNUSED,
                         remote_auth_polkit_ret *ret)
4419 4420 4421
{
    pid_t callerPid;
    uid_t callerUid;
4422 4423 4424 4425 4426 4427
    PolKitCaller *pkcaller = NULL;
    PolKitAction *pkaction = NULL;
    PolKitContext *pkcontext = NULL;
    PolKitError *pkerr = NULL;
    PolKitResult pkresult;
    DBusError err;
4428
    const char *action;
4429
    char ident[100];
J
Jim Fehlig 已提交
4430
    int rv;
4431 4432

    memset(ident, 0, sizeof ident);
4433

4434 4435 4436
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
4437 4438

    action = client->readonly ?
4439 4440
        "org.libvirt.unix.monitor" :
        "org.libvirt.unix.manage";
4441 4442 4443

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

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

4453 4454 4455 4456 4457 4458
    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;
    }

4459
    VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
4460 4461 4462
    dbus_error_init(&err);
    if (!(pkcaller = polkit_caller_new_from_pid(server->sysbus,
                                                callerPid, &err))) {
4463
        VIR_ERROR(_("Failed to lookup policy kit caller: %s"), err.message);
4464
        dbus_error_free(&err);
4465
        goto authfail;
4466
    }
4467

4468
    if (!(pkaction = polkit_action_new())) {
4469
        char ebuf[1024];
4470
        VIR_ERROR(_("Failed to create polkit action %s"),
4471
                  virStrerror(errno, ebuf, sizeof ebuf));
4472
        polkit_caller_unref(pkcaller);
4473
        goto authfail;
4474 4475 4476 4477 4478
    }
    polkit_action_set_action_id(pkaction, action);

    if (!(pkcontext = polkit_context_new()) ||
        !polkit_context_init(pkcontext, &pkerr)) {
4479
        char ebuf[1024];
4480
        VIR_ERROR(_("Failed to create polkit context %s"),
4481
                  (pkerr ? polkit_error_get_error_message(pkerr)
4482
                   : virStrerror(errno, ebuf, sizeof ebuf)));
4483 4484 4485 4486 4487
        if (pkerr)
            polkit_error_free(pkerr);
        polkit_caller_unref(pkcaller);
        polkit_action_unref(pkaction);
        dbus_error_free(&err);
4488
        goto authfail;
4489
    }
4490

4491
# if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
4492 4493 4494 4495 4496 4497
    pkresult = polkit_context_is_caller_authorized(pkcontext,
                                                   pkaction,
                                                   pkcaller,
                                                   0,
                                                   &pkerr);
    if (pkerr && polkit_error_is_set(pkerr)) {
4498 4499 4500
        VIR_ERROR(_("Policy kit failed to check authorization %d %s"),
                  polkit_error_get_error_code(pkerr),
                  polkit_error_get_error_message(pkerr));
4501
        goto authfail;
4502
    }
4503
# else
4504 4505 4506
    pkresult = polkit_context_can_caller_do_action(pkcontext,
                                                   pkaction,
                                                   pkcaller);
4507
# endif
4508 4509 4510 4511
    polkit_context_unref(pkcontext);
    polkit_caller_unref(pkcaller);
    polkit_action_unref(pkaction);
    if (pkresult != POLKIT_RESULT_YES) {
4512
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %s"),
4513 4514
                  action, callerPid, callerUid,
                  polkit_result_to_string_representation(pkresult));
4515
        goto authdeny;
4516
    }
4517 4518
    PROBE(CLIENT_AUTH_ALLOW, "fd=%d, auth=%d, username=%s",
          client->fd, REMOTE_AUTH_POLKIT, ident);
4519
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d, result %s"),
4520 4521 4522 4523
             action, callerPid, callerUid,
             polkit_result_to_string_representation(pkresult));
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;
4524

4525
    virMutexUnlock(&client->lock);
4526
    return 0;
4527 4528

authfail:
4529
    PROBE(CLIENT_AUTH_FAIL, "fd=%d, auth=%d", client->fd, REMOTE_AUTH_POLKIT);
4530 4531 4532
    goto error;

authdeny:
4533 4534
    PROBE(CLIENT_AUTH_DENY, "fd=%d, auth=%d, username=%s",
          client->fd, REMOTE_AUTH_POLKIT, ident);
4535 4536 4537
    goto error;

error:
4538
    remoteDispatchAuthError(rerr);
4539
    virMutexUnlock(&client->lock);
4540
    return -1;
4541 4542
}

4543
#else /* !HAVE_POLKIT0 & !HAVE_POLKIT1*/
4544 4545

static int
4546 4547 4548 4549 4550 4551 4552
remoteDispatchAuthPolkit(struct qemud_server *server ATTRIBUTE_UNUSED,
                         struct qemud_client *client ATTRIBUTE_UNUSED,
                         virConnectPtr conn ATTRIBUTE_UNUSED,
                         remote_message_header *hdr ATTRIBUTE_UNUSED,
                         remote_error *rerr,
                         void *args ATTRIBUTE_UNUSED,
                         remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED)
4553
{
4554
    VIR_ERROR0(_("client tried unsupported PolicyKit init request"));
4555
    remoteDispatchAuthError(rerr);
4556 4557
    return -1;
}
4558
#endif /* HAVE_POLKIT1 */
4559

4560 4561 4562 4563 4564 4565 4566

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


static int
4567 4568 4569 4570 4571 4572 4573
remoteDispatchListDefinedStoragePools(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_defined_storage_pools_args *args,
                                      remote_list_defined_storage_pools_ret *ret)
4574 4575 4576
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
4577
        remoteDispatchFormatError(rerr, "%s",
4578
                            _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
4579
        return -1;
4580 4581 4582
    }

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

    ret->names.names_len =
4589 4590
        virConnectListDefinedStoragePools(conn,
                                          ret->names.names_val, args->maxnames);
4591 4592
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
4593
        remoteDispatchConnError(rerr, conn);
4594 4595
        return -1;
    }
4596 4597 4598 4599 4600

    return 0;
}

static int
4601 4602 4603 4604 4605 4606 4607
remoteDispatchListStoragePools(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_storage_pools_args *args,
                               remote_list_storage_pools_ret *ret)
4608 4609 4610
{

    if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
4611
        remoteDispatchFormatError(rerr,
4612 4613
                                   "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX"));
        return -1;
4614 4615 4616
    }

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

    ret->names.names_len =
4623 4624
        virConnectListStoragePools(conn,
                                   ret->names.names_val, args->maxnames);
4625 4626
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
4627
        remoteDispatchConnError(rerr, conn);
4628 4629
        return -1;
    }
4630 4631 4632 4633

    return 0;
}

4634
static int
4635 4636 4637 4638 4639 4640 4641
remoteDispatchFindStoragePoolSources(struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
                                     remote_error *rerr,
                                     remote_find_storage_pool_sources_args *args,
                                     remote_find_storage_pool_sources_ret *ret)
4642 4643
{
    ret->xml =
4644 4645 4646 4647
        virConnectFindStoragePoolSources(conn,
                                         args->type,
                                         args->srcSpec ? *args->srcSpec : NULL,
                                         args->flags);
4648
    if (ret->xml == NULL) {
4649
        remoteDispatchConnError(rerr, conn);
4650
        return -1;
4651
    }
4652 4653 4654 4655 4656

    return 0;
}


4657
static int
4658 4659 4660 4661 4662 4663 4664
remoteDispatchStoragePoolCreate(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_pool_create_args *args,
                                void *ret ATTRIBUTE_UNUSED)
4665 4666 4667
{
    virStoragePoolPtr pool;

4668
    pool = get_nonnull_storage_pool(conn, args->pool);
4669
    if (pool == NULL) {
4670
        remoteDispatchConnError(rerr, conn);
4671
        return -1;
4672 4673
    }

4674
    if (virStoragePoolCreate(pool, args->flags) == -1) {
4675
        remoteDispatchConnError(rerr, conn);
4676
        virStoragePoolFree(pool);
4677 4678 4679 4680 4681 4682 4683
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
4684 4685 4686 4687 4688 4689 4690
remoteDispatchStoragePoolCreateXml(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_pool_create_xml_args *args,
                                   remote_storage_pool_create_xml_ret *ret)
4691 4692 4693
{
    virStoragePoolPtr pool;

4694
    pool = virStoragePoolCreateXML(conn, args->xml, args->flags);
4695
    if (pool == NULL) {
4696
        remoteDispatchConnError(rerr, conn);
4697 4698
        return -1;
    }
4699

4700
    make_nonnull_storage_pool(&ret->pool, pool);
4701 4702 4703 4704 4705
    virStoragePoolFree(pool);
    return 0;
}

static int
4706 4707 4708 4709 4710 4711 4712
remoteDispatchStoragePoolDefineXml(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_pool_define_xml_args *args,
                                   remote_storage_pool_define_xml_ret *ret)
4713 4714 4715
{
    virStoragePoolPtr pool;

4716
    pool = virStoragePoolDefineXML(conn, args->xml, args->flags);
4717
    if (pool == NULL) {
4718
        remoteDispatchConnError(rerr, conn);
4719 4720
        return -1;
    }
4721

4722
    make_nonnull_storage_pool(&ret->pool, pool);
4723 4724 4725 4726 4727
    virStoragePoolFree(pool);
    return 0;
}

static int
4728 4729 4730 4731 4732 4733 4734
remoteDispatchStoragePoolBuild(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_pool_build_args *args,
                               void *ret ATTRIBUTE_UNUSED)
4735 4736 4737
{
    virStoragePoolPtr pool;

4738
    pool = get_nonnull_storage_pool(conn, args->pool);
4739
    if (pool == NULL) {
4740
        remoteDispatchConnError(rerr, conn);
4741
        return -1;
4742 4743
    }

4744
    if (virStoragePoolBuild(pool, args->flags) == -1) {
4745
        remoteDispatchConnError(rerr, conn);
4746
        virStoragePoolFree(pool);
4747 4748 4749 4750 4751 4752 4753 4754
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
4755 4756 4757 4758 4759 4760 4761
remoteDispatchStoragePoolDestroy(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_pool_destroy_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
4762 4763 4764
{
    virStoragePoolPtr pool;

4765
    pool = get_nonnull_storage_pool(conn, args->pool);
4766
    if (pool == NULL) {
4767
        remoteDispatchConnError(rerr, conn);
4768
        return -1;
4769 4770
    }

4771
    if (virStoragePoolDestroy(pool) == -1) {
4772
        remoteDispatchConnError(rerr, conn);
4773
        virStoragePoolFree(pool);
4774 4775 4776 4777 4778 4779 4780
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
4781 4782 4783 4784 4785 4786 4787
remoteDispatchStoragePoolDelete(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_pool_delete_args *args,
                                void *ret ATTRIBUTE_UNUSED)
4788 4789 4790
{
    virStoragePoolPtr pool;

4791
    pool = get_nonnull_storage_pool(conn, args->pool);
4792
    if (pool == NULL) {
4793
        remoteDispatchConnError(rerr, conn);
4794
        return -1;
4795 4796
    }

4797
    if (virStoragePoolDelete(pool, args->flags) == -1) {
4798
        remoteDispatchConnError(rerr, conn);
4799
        virStoragePoolFree(pool);
4800 4801 4802 4803 4804 4805 4806
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
4807 4808 4809 4810 4811 4812 4813
remoteDispatchStoragePoolRefresh(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_pool_refresh_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
4814 4815 4816
{
    virStoragePoolPtr pool;

4817
    pool = get_nonnull_storage_pool(conn, args->pool);
4818
    if (pool == NULL) {
4819
        remoteDispatchConnError(rerr, conn);
4820
        return -1;
4821 4822
    }

4823
    if (virStoragePoolRefresh(pool, args->flags) == -1) {
4824
        remoteDispatchConnError(rerr, conn);
4825
        virStoragePoolFree(pool);
4826 4827 4828 4829 4830 4831 4832
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
4833 4834 4835 4836 4837 4838 4839
remoteDispatchStoragePoolGetInfo(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_pool_get_info_args *args,
                                 remote_storage_pool_get_info_ret *ret)
4840 4841 4842 4843
{
    virStoragePoolPtr pool;
    virStoragePoolInfo info;

4844
    pool = get_nonnull_storage_pool(conn, args->pool);
4845
    if (pool == NULL) {
4846
        remoteDispatchConnError(rerr, conn);
4847
        return -1;
4848 4849
    }

4850
    if (virStoragePoolGetInfo(pool, &info) == -1) {
4851
        remoteDispatchConnError(rerr, conn);
4852
        virStoragePoolFree(pool);
4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866
        return -1;
    }

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

    virStoragePoolFree(pool);

    return 0;
}

static int
4867 4868 4869 4870 4871 4872 4873
remoteDispatchStoragePoolDumpXml(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_pool_dump_xml_args *args,
                                 remote_storage_pool_dump_xml_ret *ret)
4874 4875 4876
{
    virStoragePoolPtr pool;

4877
    pool = get_nonnull_storage_pool(conn, args->pool);
4878
    if (pool == NULL) {
4879
        remoteDispatchConnError(rerr, conn);
4880
        return -1;
4881 4882 4883
    }

    /* remoteDispatchClientRequest will free this. */
4884
    ret->xml = virStoragePoolGetXMLDesc(pool, args->flags);
4885
    if (!ret->xml) {
4886
        remoteDispatchConnError(rerr, conn);
4887
        virStoragePoolFree(pool);
4888 4889 4890 4891 4892 4893 4894
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
4895 4896 4897 4898 4899 4900 4901
remoteDispatchStoragePoolGetAutostart(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_pool_get_autostart_args *args,
                                      remote_storage_pool_get_autostart_ret *ret)
4902 4903 4904
{
    virStoragePoolPtr pool;

4905
    pool = get_nonnull_storage_pool(conn, args->pool);
4906
    if (pool == NULL) {
4907
        remoteDispatchConnError(rerr, conn);
4908
        return -1;
4909 4910
    }

4911
    if (virStoragePoolGetAutostart(pool, &ret->autostart) == -1) {
4912
        remoteDispatchConnError(rerr, conn);
4913
        virStoragePoolFree(pool);
4914 4915 4916 4917 4918 4919 4920 4921
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
4922 4923 4924 4925 4926 4927 4928
remoteDispatchStoragePoolLookupByName(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_pool_lookup_by_name_args *args,
                                      remote_storage_pool_lookup_by_name_ret *ret)
4929 4930 4931
{
    virStoragePoolPtr pool;

4932
    pool = virStoragePoolLookupByName(conn, args->name);
4933
    if (pool == NULL) {
4934
        remoteDispatchConnError(rerr, conn);
4935 4936
        return -1;
    }
4937

4938
    make_nonnull_storage_pool(&ret->pool, pool);
4939 4940 4941 4942 4943
    virStoragePoolFree(pool);
    return 0;
}

static int
4944 4945 4946 4947 4948 4949 4950
remoteDispatchStoragePoolLookupByUuid(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_pool_lookup_by_uuid_args *args,
                                      remote_storage_pool_lookup_by_uuid_ret *ret)
4951 4952 4953
{
    virStoragePoolPtr pool;

4954
    pool = virStoragePoolLookupByUUID(conn, (unsigned char *) args->uuid);
4955
    if (pool == NULL) {
4956
        remoteDispatchConnError(rerr, conn);
4957 4958
        return -1;
    }
4959

4960
    make_nonnull_storage_pool(&ret->pool, pool);
4961 4962 4963 4964 4965
    virStoragePoolFree(pool);
    return 0;
}

static int
4966 4967 4968 4969 4970 4971 4972
remoteDispatchStoragePoolLookupByVolume(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_pool_lookup_by_volume_args *args,
                                        remote_storage_pool_lookup_by_volume_ret *ret)
4973 4974 4975 4976
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4977
    vol = get_nonnull_storage_vol(conn, args->vol);
4978
    if (vol == NULL) {
4979
        remoteDispatchConnError(rerr, conn);
4980 4981
        return -1;
    }
4982

4983
    pool = virStoragePoolLookupByVolume(vol);
4984
    if (pool == NULL) {
4985
        remoteDispatchConnError(rerr, conn);
4986
        virStorageVolFree(vol);
4987 4988
        return -1;
    }
4989
    virStorageVolFree(vol);
4990

4991
    make_nonnull_storage_pool(&ret->pool, pool);
4992 4993 4994 4995 4996
    virStoragePoolFree(pool);
    return 0;
}

static int
4997 4998 4999 5000 5001 5002 5003
remoteDispatchStoragePoolSetAutostart(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_pool_set_autostart_args *args,
                                      void *ret ATTRIBUTE_UNUSED)
5004 5005 5006
{
    virStoragePoolPtr pool;

5007
    pool = get_nonnull_storage_pool(conn, args->pool);
5008
    if (pool == NULL) {
5009
        remoteDispatchConnError(rerr, conn);
5010
        return -1;
5011 5012
    }

5013
    if (virStoragePoolSetAutostart(pool, args->autostart) == -1) {
5014
        remoteDispatchConnError(rerr, conn);
5015
        virStoragePoolFree(pool);
5016 5017 5018 5019 5020 5021 5022
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
5023 5024 5025 5026 5027 5028 5029
remoteDispatchStoragePoolUndefine(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_pool_undefine_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
5030 5031 5032
{
    virStoragePoolPtr pool;

5033
    pool = get_nonnull_storage_pool(conn, args->pool);
5034
    if (pool == NULL) {
5035
        remoteDispatchConnError(rerr, conn);
5036
        return -1;
5037 5038
    }

5039
    if (virStoragePoolUndefine(pool) == -1) {
5040
        remoteDispatchConnError(rerr, conn);
5041
        virStoragePoolFree(pool);
5042 5043 5044 5045 5046 5047 5048
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
5049 5050 5051 5052 5053 5054 5055
remoteDispatchNumOfStoragePools(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_storage_pools_ret *ret)
5056 5057
{

5058
    ret->num = virConnectNumOfStoragePools(conn);
5059
    if (ret->num == -1) {
5060
        remoteDispatchConnError(rerr, conn);
5061 5062
        return -1;
    }
5063 5064 5065 5066 5067

    return 0;
}

static int
5068 5069 5070 5071 5072 5073 5074
remoteDispatchNumOfDefinedStoragePools(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_defined_storage_pools_ret *ret)
5075 5076
{

5077
    ret->num = virConnectNumOfDefinedStoragePools(conn);
5078
    if (ret->num == -1) {
5079
        remoteDispatchConnError(rerr, conn);
5080 5081
        return -1;
    }
5082 5083 5084 5085 5086

    return 0;
}

static int
5087 5088 5089 5090 5091 5092 5093
remoteDispatchStoragePoolListVolumes(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_pool_list_volumes_args *args,
                                     remote_storage_pool_list_volumes_ret *ret)
5094 5095 5096 5097
{
    virStoragePoolPtr pool;

    if (args->maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) {
5098
        remoteDispatchFormatError(rerr,
5099 5100
                                   "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX"));
        return -1;
5101 5102
    }

5103
    pool = get_nonnull_storage_pool(conn, args->pool);
5104
    if (pool == NULL) {
5105
        remoteDispatchConnError(rerr, conn);
5106
        return -1;
5107 5108 5109
    }

    /* Allocate return buffer. */
5110 5111
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        virStoragePoolFree(pool);
5112 5113
        remoteDispatchOOMError(rerr);
        return -1;
5114
    }
5115 5116

    ret->names.names_len =
5117 5118
        virStoragePoolListVolumes(pool,
                                  ret->names.names_val, args->maxnames);
5119 5120
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
5121
        remoteDispatchConnError(rerr, conn);
5122
        virStoragePoolFree(pool);
5123 5124
        return -1;
    }
5125
    virStoragePoolFree(pool);
5126 5127 5128 5129 5130 5131

    return 0;
}


static int
5132 5133 5134 5135 5136 5137 5138
remoteDispatchStoragePoolNumOfVolumes(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_pool_num_of_volumes_args *args,
                                      remote_storage_pool_num_of_volumes_ret *ret)
5139 5140 5141
{
    virStoragePoolPtr pool;

5142
    pool = get_nonnull_storage_pool(conn, args->pool);
5143
    if (pool == NULL) {
5144
        remoteDispatchConnError(rerr, conn);
5145
        return -1;
5146 5147
    }

5148
    ret->num = virStoragePoolNumOfVolumes(pool);
5149
    if (ret->num == -1) {
5150
        remoteDispatchConnError(rerr, conn);
5151
        virStoragePoolFree(pool);
5152 5153
        return -1;
    }
5154
    virStoragePoolFree(pool);
5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166

    return 0;
}


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



static int
5167 5168 5169 5170 5171 5172 5173
remoteDispatchStorageVolCreateXml(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_create_xml_args *args,
                                  remote_storage_vol_create_xml_ret *ret)
5174 5175 5176 5177
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

5178
    pool = get_nonnull_storage_pool(conn, args->pool);
5179
    if (pool == NULL) {
5180
        remoteDispatchConnError(rerr, conn);
5181
        return -1;
5182 5183
    }

5184
    vol = virStorageVolCreateXML(pool, args->xml, args->flags);
5185
    if (vol == NULL) {
5186
        remoteDispatchConnError(rerr, conn);
5187
        virStoragePoolFree(pool);
5188 5189
        return -1;
    }
5190
    virStoragePoolFree(pool);
5191

5192
    make_nonnull_storage_vol(&ret->vol, vol);
5193 5194 5195 5196
    virStorageVolFree(vol);
    return 0;
}

5197
static int
5198 5199 5200 5201 5202 5203 5204
remoteDispatchStorageVolCreateXmlFrom(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_create_xml_from_args *args,
                                      remote_storage_vol_create_xml_from_ret *ret)
5205 5206 5207 5208
{
    virStoragePoolPtr pool;
    virStorageVolPtr clonevol, newvol;

5209
    pool = get_nonnull_storage_pool(conn, args->pool);
5210 5211 5212 5213 5214
    if (pool == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

5215
    clonevol = get_nonnull_storage_vol(conn, args->clonevol);
5216 5217
    if (clonevol == NULL) {
        remoteDispatchConnError(rerr, conn);
5218
        virStoragePoolFree(pool);
5219 5220 5221
        return -1;
    }

5222 5223
    newvol = virStorageVolCreateXMLFrom(pool, args->xml, clonevol,
                                        args->flags);
5224 5225
    if (newvol == NULL) {
        remoteDispatchConnError(rerr, conn);
5226 5227
        virStorageVolFree(clonevol);
        virStoragePoolFree(pool);
5228 5229
        return -1;
    }
5230 5231
    virStorageVolFree(clonevol);
    virStoragePoolFree(pool);
5232

5233
    make_nonnull_storage_vol(&ret->vol, newvol);
5234 5235 5236
    virStorageVolFree(newvol);
    return 0;
}
5237 5238

static int
5239 5240 5241 5242 5243 5244 5245
remoteDispatchStorageVolDelete(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_delete_args *args,
                               void *ret ATTRIBUTE_UNUSED)
5246 5247 5248
{
    virStorageVolPtr vol;

5249
    vol = get_nonnull_storage_vol(conn, args->vol);
5250
    if (vol == NULL) {
5251
        remoteDispatchConnError(rerr, conn);
5252
        return -1;
5253 5254
    }

5255
    if (virStorageVolDelete(vol, args->flags) == -1) {
5256
        remoteDispatchConnError(rerr, conn);
5257
        virStorageVolFree(vol);
5258 5259 5260 5261 5262 5263
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}

5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295
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;
}

5296
static int
5297 5298 5299 5300 5301 5302 5303
remoteDispatchStorageVolGetInfo(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_get_info_args *args,
                                remote_storage_vol_get_info_ret *ret)
5304 5305 5306 5307
{
    virStorageVolPtr vol;
    virStorageVolInfo info;

5308
    vol = get_nonnull_storage_vol(conn, args->vol);
5309
    if (vol == NULL) {
5310
        remoteDispatchConnError(rerr, conn);
5311
        return -1;
5312 5313
    }

5314
    if (virStorageVolGetInfo(vol, &info) == -1) {
5315
        remoteDispatchConnError(rerr, conn);
5316
        virStorageVolFree(vol);
5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329
        return -1;
    }

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

    virStorageVolFree(vol);

    return 0;
}

static int
5330 5331 5332 5333 5334 5335 5336
remoteDispatchStorageVolDumpXml(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_dump_xml_args *args,
                                remote_storage_vol_dump_xml_ret *ret)
5337 5338 5339
{
    virStorageVolPtr vol;

5340
    vol = get_nonnull_storage_vol(conn, args->vol);
5341
    if (vol == NULL) {
5342
        remoteDispatchConnError(rerr, conn);
5343
        return -1;
5344 5345 5346
    }

    /* remoteDispatchClientRequest will free this. */
5347
    ret->xml = virStorageVolGetXMLDesc(vol, args->flags);
5348
    if (!ret->xml) {
5349
        remoteDispatchConnError(rerr, conn);
5350
        virStorageVolFree(vol);
5351 5352 5353 5354 5355 5356 5357 5358
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
5359 5360 5361 5362 5363 5364 5365
remoteDispatchStorageVolGetPath(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_get_path_args *args,
                                remote_storage_vol_get_path_ret *ret)
5366 5367 5368
{
    virStorageVolPtr vol;

5369
    vol = get_nonnull_storage_vol(conn, args->vol);
5370
    if (vol == NULL) {
5371
        remoteDispatchConnError(rerr, conn);
5372
        return -1;
5373 5374 5375
    }

    /* remoteDispatchClientRequest will free this. */
5376
    ret->name = virStorageVolGetPath(vol);
5377
    if (!ret->name) {
5378
        remoteDispatchConnError(rerr, conn);
5379
        virStorageVolFree(vol);
5380 5381 5382 5383 5384 5385 5386 5387
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
5388 5389 5390 5391 5392 5393 5394
remoteDispatchStorageVolLookupByName(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_lookup_by_name_args *args,
                                     remote_storage_vol_lookup_by_name_ret *ret)
5395 5396 5397 5398
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

5399
    pool = get_nonnull_storage_pool(conn, args->pool);
5400
    if (pool == NULL) {
5401
        remoteDispatchConnError(rerr, conn);
5402
        return -1;
5403 5404
    }

5405
    vol = virStorageVolLookupByName(pool, args->name);
5406
    if (vol == NULL) {
5407
        remoteDispatchConnError(rerr, conn);
5408
        virStoragePoolFree(pool);
5409 5410
        return -1;
    }
5411
    virStoragePoolFree(pool);
5412

5413
    make_nonnull_storage_vol(&ret->vol, vol);
5414 5415 5416 5417 5418
    virStorageVolFree(vol);
    return 0;
}

static int
5419 5420 5421 5422 5423 5424 5425
remoteDispatchStorageVolLookupByKey(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_lookup_by_key_args *args,
                                    remote_storage_vol_lookup_by_key_ret *ret)
5426 5427 5428
{
    virStorageVolPtr vol;

5429
    vol = virStorageVolLookupByKey(conn, args->key);
5430
    if (vol == NULL) {
5431
        remoteDispatchConnError(rerr, conn);
5432 5433
        return -1;
    }
5434

5435
    make_nonnull_storage_vol(&ret->vol, vol);
5436 5437 5438 5439 5440 5441
    virStorageVolFree(vol);
    return 0;
}


static int
5442 5443 5444 5445 5446 5447 5448
remoteDispatchStorageVolLookupByPath(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_lookup_by_path_args *args,
                                     remote_storage_vol_lookup_by_path_ret *ret)
5449 5450 5451
{
    virStorageVolPtr vol;

5452
    vol = virStorageVolLookupByPath(conn, args->path);
5453
    if (vol == NULL) {
5454
        remoteDispatchConnError(rerr, conn);
5455 5456
        return -1;
    }
5457

5458
    make_nonnull_storage_vol(&ret->vol, vol);
5459 5460 5461 5462 5463
    virStorageVolFree(vol);
    return 0;
}


5464 5465 5466 5467 5468
/***************************************************************
 *     NODE INFO APIS
 **************************************************************/

static int
5469 5470 5471 5472 5473 5474 5475
remoteDispatchNodeNumOfDevices(struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *rerr,
                               remote_node_num_of_devices_args *args,
                               remote_node_num_of_devices_ret *ret)
5476 5477 5478
{
    CHECK_CONN(client);

5479 5480 5481
    ret->num = virNodeNumOfDevices(conn,
                                   args->cap ? *args->cap : NULL,
                                   args->flags);
5482
    if (ret->num == -1) {
5483
        remoteDispatchConnError(rerr, conn);
5484 5485
        return -1;
    }
5486 5487 5488 5489 5490 5491

    return 0;
}


static int
5492 5493 5494 5495 5496 5497 5498
remoteDispatchNodeListDevices(struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *rerr,
                              remote_node_list_devices_args *args,
                              remote_node_list_devices_ret *ret)
5499 5500 5501 5502
{
    CHECK_CONN(client);

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
5503 5504 5505
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
5506 5507 5508 5509
    }

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

    ret->names.names_len =
5515 5516 5517
        virNodeListDevices(conn,
                           args->cap ? *args->cap : NULL,
                           ret->names.names_val, args->maxnames, args->flags);
5518
    if (ret->names.names_len == -1) {
5519
        remoteDispatchConnError(rerr, conn);
5520 5521 5522 5523 5524 5525 5526 5527 5528
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


static int
5529 5530 5531 5532 5533 5534 5535
remoteDispatchNodeDeviceLookupByName(struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
                                     remote_error *rerr,
                                     remote_node_device_lookup_by_name_args *args,
                                     remote_node_device_lookup_by_name_ret *ret)
5536 5537 5538 5539 5540
{
    virNodeDevicePtr dev;

    CHECK_CONN(client);

5541
    dev = virNodeDeviceLookupByName(conn, args->name);
5542
    if (dev == NULL) {
5543
        remoteDispatchConnError(rerr, conn);
5544 5545
        return -1;
    }
5546

5547
    make_nonnull_node_device(&ret->dev, dev);
5548 5549 5550 5551 5552 5553
    virNodeDeviceFree(dev);
    return 0;
}


static int
5554 5555 5556 5557 5558 5559 5560
remoteDispatchNodeDeviceDumpXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *rerr,
                                remote_node_device_dump_xml_args *args,
                                remote_node_device_dump_xml_ret *ret)
5561 5562 5563 5564
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

5565
    dev = virNodeDeviceLookupByName(conn, args->name);
5566
    if (dev == NULL) {
5567
        remoteDispatchConnError(rerr, conn);
5568
        return -1;
5569 5570 5571
    }

    /* remoteDispatchClientRequest will free this. */
5572
    ret->xml = virNodeDeviceGetXMLDesc(dev, args->flags);
5573
    if (!ret->xml) {
5574
        remoteDispatchConnError(rerr, conn);
5575 5576 5577 5578 5579 5580 5581 5582 5583
        virNodeDeviceFree(dev);
        return -1;
    }
    virNodeDeviceFree(dev);
    return 0;
}


static int
5584 5585 5586 5587 5588 5589 5590
remoteDispatchNodeDeviceGetParent(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_node_device_get_parent_args *args,
                                  remote_node_device_get_parent_ret *ret)
5591 5592 5593 5594 5595
{
    virNodeDevicePtr dev;
    const char *parent;
    CHECK_CONN(client);

5596
    dev = virNodeDeviceLookupByName(conn, args->name);
5597
    if (dev == NULL) {
5598
        remoteDispatchConnError(rerr, conn);
5599
        return -1;
5600 5601 5602 5603 5604 5605 5606 5607 5608 5609
    }

    parent = virNodeDeviceGetParent(dev);

    if (parent == NULL) {
        ret->parent = NULL;
    } else {
        /* remoteDispatchClientRequest will free this. */
        char **parent_p;
        if (VIR_ALLOC(parent_p) < 0) {
5610
            virNodeDeviceFree(dev);
5611 5612
            remoteDispatchOOMError(rerr);
            return -1;
5613 5614 5615
        }
        *parent_p = strdup(parent);
        if (*parent_p == NULL) {
5616
            virNodeDeviceFree(dev);
5617 5618
            remoteDispatchOOMError(rerr);
            return -1;
5619 5620 5621 5622 5623 5624 5625 5626 5627 5628
        }
        ret->parent = parent_p;
    }

    virNodeDeviceFree(dev);
    return 0;
}


static int
5629 5630 5631 5632 5633 5634 5635
remoteDispatchNodeDeviceNumOfCaps(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *rerr,
                                  remote_node_device_num_of_caps_args *args,
                                  remote_node_device_num_of_caps_ret *ret)
5636 5637 5638 5639
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

5640
    dev = virNodeDeviceLookupByName(conn, args->name);
5641
    if (dev == NULL) {
5642
        remoteDispatchConnError(rerr, conn);
5643
        return -1;
5644 5645 5646
    }

    ret->num = virNodeDeviceNumOfCaps(dev);
5647
    if (ret->num < 0) {
5648
        remoteDispatchConnError(rerr, conn);
5649
        virNodeDeviceFree(dev);
5650 5651
        return -1;
    }
5652 5653 5654 5655 5656 5657 5658

    virNodeDeviceFree(dev);
    return 0;
}


static int
5659 5660 5661 5662 5663 5664 5665
remoteDispatchNodeDeviceListCaps(struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_node_device_list_caps_args *args,
                                 remote_node_device_list_caps_ret *ret)
5666 5667 5668 5669
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

5670
    dev = virNodeDeviceLookupByName(conn, args->name);
5671
    if (dev == NULL) {
5672
        remoteDispatchConnError(rerr, conn);
5673
        return -1;
5674 5675 5676
    }

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
5677
        virNodeDeviceFree(dev);
5678 5679 5680
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
5681 5682 5683 5684
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
5685
        virNodeDeviceFree(dev);
5686 5687
        remoteDispatchOOMError(rerr);
        return -1;
5688 5689 5690
    }

    ret->names.names_len =
5691 5692
        virNodeDeviceListCaps(dev, ret->names.names_val,
                              args->maxnames);
5693
    if (ret->names.names_len == -1) {
5694
        remoteDispatchConnError(rerr, conn);
5695
        virNodeDeviceFree(dev);
5696 5697 5698 5699
        VIR_FREE(ret->names.names_val);
        return -1;
    }

5700
    virNodeDeviceFree(dev);
5701 5702 5703 5704
    return 0;
}


5705
static int
5706 5707 5708 5709 5710 5711 5712
remoteDispatchNodeDeviceDettach(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *rerr,
                                remote_node_device_dettach_args *args,
                                void *ret ATTRIBUTE_UNUSED)
5713 5714 5715 5716 5717 5718
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5719
        remoteDispatchConnError(rerr, conn);
5720 5721 5722 5723 5724
        return -1;
    }

    if (virNodeDeviceDettach(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
5725
        virNodeDeviceFree(dev);
5726 5727 5728
        return -1;
    }

5729
    virNodeDeviceFree(dev);
5730 5731 5732 5733 5734
    return 0;
}


static int
5735 5736 5737 5738 5739 5740 5741
remoteDispatchNodeDeviceReAttach(struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_node_device_re_attach_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
5742 5743 5744 5745 5746 5747
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5748
        remoteDispatchConnError(rerr, conn);
5749 5750 5751 5752 5753
        return -1;
    }

    if (virNodeDeviceReAttach(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
5754
        virNodeDeviceFree(dev);
5755 5756 5757
        return -1;
    }

5758
    virNodeDeviceFree(dev);
5759 5760 5761 5762 5763
    return 0;
}


static int
5764 5765 5766 5767 5768 5769 5770
remoteDispatchNodeDeviceReset(struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *rerr,
                              remote_node_device_reset_args *args,
                              void *ret ATTRIBUTE_UNUSED)
5771 5772 5773 5774 5775 5776
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5777
        remoteDispatchConnError(rerr, conn);
5778 5779 5780 5781 5782
        return -1;
    }

    if (virNodeDeviceReset(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
5783
        virNodeDeviceFree(dev);
5784 5785 5786
        return -1;
    }

5787
    virNodeDeviceFree(dev);
5788 5789 5790 5791
    return 0;
}


5792 5793 5794 5795
static int
remoteDispatchNodeDeviceCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
5796
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
5797 5798 5799 5800 5801 5802
                                  remote_error *rerr,
                                  remote_node_device_create_xml_args *args,
                                  remote_node_device_create_xml_ret *ret)
{
    virNodeDevicePtr dev;

5803
    dev = virNodeDeviceCreateXML(conn, args->xml_desc, args->flags);
5804 5805 5806 5807 5808
    if (dev == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

5809
    make_nonnull_node_device(&ret->dev, dev);
5810 5811 5812 5813 5814 5815 5816 5817 5818 5819
    virNodeDeviceFree(dev);

    return 0;
}


static int
remoteDispatchNodeDeviceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
5820
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
5821 5822 5823 5824 5825 5826 5827 5828
                                remote_error *rerr,
                                remote_node_device_destroy_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5829
        remoteDispatchConnError(rerr, conn);
5830 5831 5832 5833 5834
        return -1;
    }

    if (virNodeDeviceDestroy(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
5835
        virNodeDeviceFree(dev);
5836 5837 5838
        return -1;
    }

5839
    virNodeDeviceFree(dev);
5840 5841
    return 0;
}
5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887
static int remoteDispatchStorageVolUpload(struct qemud_server *server ATTRIBUTE_UNUSED,
                                          struct qemud_client *client,
                                          virConnectPtr conn,
                                          remote_message_header *hdr,
                                          remote_error *rerr,
                                          remote_storage_vol_upload_args *args,
                                          void *ret ATTRIBUTE_UNUSED)
{
    int rv = -1;
    struct qemud_client_stream *stream = NULL;
    virStorageVolPtr vol;

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

    stream = remoteCreateClientStream(conn, hdr);
    if (!stream) {
        remoteDispatchConnError(rerr, conn);
        goto cleanup;
    }

    if (virStorageVolUpload(vol, stream->st,
                            args->offset, args->length,
                            args->flags) < 0) {
        remoteDispatchConnError(rerr, conn);
        goto cleanup;
    }

    if (remoteAddClientStream(client, stream, 0) < 0) {
        remoteDispatchConnError(rerr, conn);
        virStreamAbort(stream->st);
        goto cleanup;
    }

    rv = 0;

cleanup:
    if (vol)
        virStorageVolFree(vol);
    if (stream && rv != 0)
        remoteFreeClientStream(client, stream);
    return rv;
}
5888

5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900
static int remoteDispatchStorageVolDownload(struct qemud_server *server ATTRIBUTE_UNUSED,
                                            struct qemud_client *client,
                                            virConnectPtr conn,
                                            remote_message_header *hdr,
                                            remote_error *rerr,
                                            remote_storage_vol_download_args *args,
                                            void *ret ATTRIBUTE_UNUSED)
{
    int rv = -1;
    struct qemud_client_stream *stream = NULL;
    virStorageVolPtr vol;

5901
    vol = get_nonnull_storage_vol(conn, args->vol);
5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934
    if (vol == NULL) {
        remoteDispatchConnError(rerr, conn);
        goto cleanup;
    }

    stream = remoteCreateClientStream(conn, hdr);
    if (!stream) {
        remoteDispatchConnError(rerr, conn);
        goto cleanup;
    }

    if (virStorageVolDownload(vol, stream->st,
                              args->offset, args->length,
                              args->flags) < 0) {
        remoteDispatchConnError(rerr, conn);
        goto cleanup;
    }

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

    rv = 0;

cleanup:
    if (vol)
        virStorageVolFree(vol);
    if (stream && rv != 0)
        remoteFreeClientStream(client, stream);
    return rv;
}
5935

5936 5937 5938 5939 5940

/***************************
 * Register / deregister events
 ***************************/
static int
5941 5942 5943 5944 5945 5946 5947
remoteDispatchDomainEventsRegister(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,
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_domain_events_register_ret *ret ATTRIBUTE_UNUSED)
5948 5949
{
    CHECK_CONN(client);
5950 5951 5952 5953 5954 5955
    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;
    }
5956

5957 5958 5959 5960 5961
    if ((callbackID = virConnectDomainEventRegisterAny(conn,
                                                       NULL,
                                                       VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                                       VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
                                                       client, NULL)) < 0) {
5962 5963 5964
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
5965

5966
    client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = callbackID;
5967

5968 5969 5970 5971
    return 0;
}

static int
5972 5973 5974 5975 5976 5977 5978
remoteDispatchDomainEventsDeregister(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,
                                     void *args ATTRIBUTE_UNUSED,
                                     remote_domain_events_deregister_ret *ret ATTRIBUTE_UNUSED)
5979 5980 5981
{
    CHECK_CONN(client);

5982 5983
    if (client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] == -1) {
        remoteDispatchFormatError(rerr, _("domain event %d not registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE);
5984 5985
        return -1;
    }
5986

5987 5988 5989 5990 5991
    if (virConnectDomainEventDeregisterAny(conn,
                                           client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE]) < 0) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
5992

5993
    client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = -1;
5994 5995 5996 5997
    return 0;
}

static void
5998 5999 6000 6001
remoteDispatchDomainEventSend(struct qemud_client *client,
                              int procnr,
                              xdrproc_t proc,
                              void *data)
6002
{
6003
    struct qemud_client_message *msg = NULL;
6004
    XDR xdr;
6005
    unsigned int len;
6006

6007
    if (VIR_ALLOC(msg) < 0)
6008 6009
        return;

6010 6011
    msg->hdr.prog = REMOTE_PROGRAM;
    msg->hdr.vers = REMOTE_PROTOCOL_VERSION;
6012
    msg->hdr.proc = procnr;
6013
    msg->hdr.type = REMOTE_MESSAGE;
6014 6015
    msg->hdr.serial = 1;
    msg->hdr.status = REMOTE_OK;
6016

6017 6018
    if (remoteEncodeClientMessageHeader(msg) < 0)
        goto error;
6019

6020
    /* Serialise the return header and event. */
6021 6022 6023 6024
    xdrmem_create(&xdr,
                  msg->buffer,
                  msg->bufferLength,
                  XDR_ENCODE);
6025

6026
    /* Skip over the header we just wrote */
6027
    if (xdr_setpos(&xdr, msg->bufferOffset) == 0)
6028
        goto xdr_error;
6029

6030 6031
    if (!(proc)(&xdr, data)) {
        VIR_WARN("Failed to serialize domain event %d", procnr);
6032
        goto xdr_error;
6033
    }
6034

6035
    /* Update length word to include payload*/
6036 6037
    len = msg->bufferOffset = xdr_getpos(&xdr);
    if (xdr_setpos(&xdr, 0) == 0)
6038
        goto xdr_error;
6039

6040
    if (!xdr_u_int(&xdr, &len))
6041
        goto xdr_error;
6042 6043

    /* Send it. */
6044 6045 6046
    msg->async = 1;
    msg->bufferLength = len;
    msg->bufferOffset = 0;
6047 6048

    VIR_DEBUG("Queue event %d %d", procnr, msg->bufferLength);
6049
    qemudClientMessageQueuePush(&client->tx, msg);
6050
    qemudUpdateClientEvent(client);
6051

6052
    xdr_destroy(&xdr);
6053 6054 6055 6056 6057 6058
    return;

xdr_error:
    xdr_destroy(&xdr);
error:
    VIR_FREE(msg);
6059
}
6060

6061
static int
6062 6063 6064 6065 6066 6067 6068
remoteDispatchNumOfSecrets(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_num_of_secrets_ret *ret)
6069
{
6070
    ret->num = virConnectNumOfSecrets(conn);
6071
    if (ret->num == -1) {
6072
        remoteDispatchConnError(err, conn);
6073 6074 6075 6076 6077 6078 6079
        return -1;
    }

    return 0;
}

static int
6080 6081 6082 6083 6084 6085 6086
remoteDispatchListSecrets(struct qemud_server *server ATTRIBUTE_UNUSED,
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
                          remote_error *err,
                          remote_list_secrets_args *args,
                          remote_list_secrets_ret *ret)
6087 6088
{
    if (args->maxuuids > REMOTE_SECRET_UUID_LIST_MAX) {
6089
        remoteDispatchFormatError(err, "%s",
6090 6091 6092 6093
                                   _("maxuuids > REMOTE_SECRET_UUID_LIST_MAX"));
        return -1;
    }

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

6099 6100
    ret->uuids.uuids_len = virConnectListSecrets(conn, ret->uuids.uuids_val,
                                                 args->maxuuids);
6101
    if (ret->uuids.uuids_len == -1) {
6102 6103
        VIR_FREE(ret->uuids.uuids_val);
        remoteDispatchConnError(err, conn);
6104 6105 6106 6107 6108 6109 6110
        return -1;
    }

    return 0;
}

static int
6111 6112 6113 6114 6115 6116 6117
remoteDispatchSecretDefineXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
                              remote_secret_define_xml_args *args,
                              remote_secret_define_xml_ret *ret)
6118 6119 6120
{
    virSecretPtr secret;

6121
    secret = virSecretDefineXML(conn, args->xml, args->flags);
6122
    if (secret == NULL) {
6123
        remoteDispatchConnError(err, conn);
6124 6125 6126
        return -1;
    }

6127 6128
    make_nonnull_secret(&ret->secret, secret);
    virSecretFree(secret);
6129 6130 6131 6132
    return 0;
}

static int
6133 6134 6135 6136 6137 6138 6139
remoteDispatchSecretGetValue(struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *err,
                             remote_secret_get_value_args *args,
                             remote_secret_get_value_ret *ret)
6140 6141 6142 6143 6144
{
    virSecretPtr secret;
    size_t value_size;
    unsigned char *value;

6145
    secret = get_nonnull_secret(conn, args->secret);
6146
    if (secret == NULL) {
6147
        remoteDispatchConnError(err, conn);
6148 6149 6150
        return -1;
    }

6151
    value = virSecretGetValue(secret, &value_size, args->flags);
6152
    if (value == NULL) {
6153
        remoteDispatchConnError(err, conn);
6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164
        virSecretFree(secret);
        return -1;
    }

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

static int
6165 6166 6167 6168 6169 6170 6171
remoteDispatchSecretGetXmlDesc(struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *err,
                               remote_secret_get_xml_desc_args *args,
                               remote_secret_get_xml_desc_ret *ret)
6172 6173 6174
{
    virSecretPtr secret;

6175
    secret = get_nonnull_secret(conn, args->secret);
6176
    if (secret == NULL) {
6177
        remoteDispatchConnError(err, conn);
6178 6179
        return -1;
    }
6180
    ret->xml = virSecretGetXMLDesc(secret, args->flags);
6181
    if (ret->xml == NULL) {
6182
        remoteDispatchConnError(err, conn);
6183 6184 6185 6186 6187 6188 6189 6190
        virSecretFree(secret);
        return -1;
    }
    virSecretFree(secret);
    return 0;
}

static int
6191 6192 6193 6194 6195 6196 6197
remoteDispatchSecretLookupByUuid(struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *err,
                                 remote_secret_lookup_by_uuid_args *args,
                                 remote_secret_lookup_by_uuid_ret *ret)
6198 6199 6200
{
    virSecretPtr secret;

6201
    secret = virSecretLookupByUUID(conn, (unsigned char *)args->uuid);
6202
    if (secret == NULL) {
6203
        remoteDispatchConnError(err, conn);
6204 6205 6206
        return -1;
    }

6207 6208
    make_nonnull_secret(&ret->secret, secret);
    virSecretFree(secret);
6209 6210 6211 6212
    return 0;
}

static int
6213 6214 6215 6216 6217 6218 6219
remoteDispatchSecretSetValue(struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *err,
                             remote_secret_set_value_args *args,
                             void *ret ATTRIBUTE_UNUSED)
6220 6221 6222
{
    virSecretPtr secret;

6223
    secret = get_nonnull_secret(conn, args->secret);
6224
    if (secret == NULL) {
6225
        remoteDispatchConnError(err, conn);
6226 6227
        return -1;
    }
6228 6229 6230
    if (virSecretSetValue(secret, (const unsigned char *)args->value.value_val,
                          args->value.value_len, args->flags) < 0) {
        remoteDispatchConnError(err, conn);
6231 6232 6233 6234 6235 6236 6237 6238 6239
        virSecretFree(secret);
        return -1;
    }

    virSecretFree(secret);
    return 0;
}

static int
6240 6241 6242 6243 6244 6245 6246
remoteDispatchSecretUndefine(struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *err,
                             remote_secret_undefine_args *args,
                             void *ret ATTRIBUTE_UNUSED)
6247 6248 6249
{
    virSecretPtr secret;

6250
    secret = get_nonnull_secret(conn, args->secret);
6251
    if (secret == NULL) {
6252
        remoteDispatchConnError(err, conn);
6253 6254
        return -1;
    }
6255 6256
    if (virSecretUndefine(secret) < 0) {
        remoteDispatchConnError(err, conn);
6257 6258 6259 6260 6261 6262 6263 6264
        virSecretFree(secret);
        return -1;
    }

    virSecretFree(secret);
    return 0;
}

6265
static int
6266 6267 6268 6269 6270 6271 6272
remoteDispatchSecretLookupByUsage(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *err,
                                  remote_secret_lookup_by_usage_args *args,
                                  remote_secret_lookup_by_usage_ret *ret)
6273 6274 6275
{
    virSecretPtr secret;

6276
    secret = virSecretLookupByUsage(conn, args->usageType, args->usageID);
6277
    if (secret == NULL) {
6278
        remoteDispatchConnError(err, conn);
6279 6280 6281
        return -1;
    }

6282 6283
    make_nonnull_secret(&ret->secret, secret);
    virSecretFree(secret);
6284 6285 6286
    return 0;
}

6287

6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307
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) {
        remoteDispatchConnError(err, conn);
6308
        virDomainFree(domain);
6309 6310 6311
        return -1;
    }

6312
    virDomainFree(domain);
6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335
    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) {
        remoteDispatchConnError(err, conn);
6336
        virDomainFree(domain);
6337 6338 6339
        return -1;
    }

6340
    virDomainFree(domain);
6341 6342 6343
    return 0;
}

O
Osier Yang 已提交
6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363
static int remoteDispatchDomainIsUpdated(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_updated_args *args,
                                            remote_domain_is_updated_ret *ret)
{
    virDomainPtr domain;

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

    ret->updated = virDomainIsUpdated(domain);

    if (ret->updated < 0) {
        remoteDispatchConnError(err, conn);
6364
        virDomainFree(domain);
O
Osier Yang 已提交
6365 6366 6367 6368 6369 6370 6371
        return -1;
    }

    virDomainFree(domain);
    return 0;
}

6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391
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) {
        remoteDispatchConnError(err, conn);
6392
        virInterfaceFree(iface);
6393 6394 6395
        return -1;
    }

6396
    virInterfaceFree(iface);
6397 6398 6399 6400 6401 6402 6403 6404 6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419
    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) {
        remoteDispatchConnError(err, conn);
6420
        virNetworkFree(network);
6421 6422 6423
        return -1;
    }

6424
    virNetworkFree(network);
6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447
    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) {
        remoteDispatchConnError(err, conn);
6448
        virNetworkFree(network);
6449 6450 6451
        return -1;
    }

6452
    virNetworkFree(network);
6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475
    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) {
        remoteDispatchConnError(err, conn);
6476
        virStoragePoolFree(pool);
6477 6478 6479
        return -1;
    }

6480
    virStoragePoolFree(pool);
6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503
    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) {
        remoteDispatchConnError(err, conn);
6504
        virStoragePoolFree(pool);
6505 6506 6507
        return -1;
    }

6508
    virStoragePoolFree(pool);
6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531
    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;
}


6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553
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;
}


6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574
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;
6575 6576 6577 6578 6579 6580

    return 0;
}


static int
6581 6582 6583 6584 6585 6586 6587
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)
6588 6589 6590 6591
{
    virDomainPtr dom;
    virDomainJobInfo info;

6592
    dom = get_nonnull_domain(conn, args->dom);
6593 6594 6595 6596 6597
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

6598
    if (virDomainGetJobInfo(dom, &info) == -1) {
6599
        remoteDispatchConnError(rerr, conn);
6600
        virDomainFree(dom);
6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618
        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);

6619 6620 6621 6622
    return 0;
}


6623
static int
6624 6625 6626 6627 6628 6629 6630
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)
6631 6632 6633
{
    virDomainPtr dom;

6634
    dom = get_nonnull_domain(conn, args->dom);
6635 6636 6637 6638 6639
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

6640
    if (virDomainAbortJob(dom) == -1) {
6641
        remoteDispatchConnError(rerr, conn);
6642
        virDomainFree(dom);
6643 6644 6645 6646 6647 6648 6649 6650 6651
        return -1;
    }

    virDomainFree(dom);

    return 0;
}


6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670
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) {
        remoteDispatchConnError(rerr, conn);
6671
        virDomainFree(dom);
6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698
        return -1;
    }

    virDomainFree(dom);

    return 0;
}

static int
remoteDispatchDomainMigrateSetMaxSpeed(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_speed_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

    if (virDomainMigrateSetMaxSpeed(dom, args->bandwidth, args->flags) == -1) {
        remoteDispatchConnError(rerr, conn);
6699
        virDomainFree(dom);
6700 6701 6702 6703 6704 6705 6706 6707
        return -1;
    }

    virDomainFree(dom);

    return 0;
}

C
Chris Lalancette 已提交
6708
static int
6709 6710 6711 6712 6713 6714 6715
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)
C
Chris Lalancette 已提交
6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728
{
    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) {
        remoteDispatchConnError(rerr, conn);
6729
        virDomainFree(domain);
C
Chris Lalancette 已提交
6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741
        return -1;
    }

    make_nonnull_domain_snapshot(&ret->snap, snapshot);

    virDomainSnapshotFree(snapshot);
    virDomainFree(domain);

    return 0;
}

static int
6742 6743 6744 6745 6746 6747 6748
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)
C
Chris Lalancette 已提交
6749
{
6750 6751 6752
    virDomainPtr domain = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    int rc = -1;
C
Chris Lalancette 已提交
6753

6754 6755 6756 6757 6758 6759 6760
    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 已提交
6761 6762 6763

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virDomainSnapshotGetXMLDesc(snapshot, args->flags);
6764 6765 6766 6767 6768 6769
    if (!ret->xml)
        goto cleanup;

    rc = 0;

cleanup:
6770 6771
    if (rc < 0)
        remoteDispatchConnError(rerr, conn);
6772
    if (snapshot)
C
Chris Lalancette 已提交
6773
        virDomainSnapshotFree(snapshot);
6774 6775
    if (domain)
        virDomainFree(domain);
C
Chris Lalancette 已提交
6776

6777
    return rc;
C
Chris Lalancette 已提交
6778 6779 6780
}

static int
6781 6782 6783 6784 6785 6786 6787
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)
C
Chris Lalancette 已提交
6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799
{
    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) {
        remoteDispatchConnError(rerr, conn);
6800
        virDomainFree(domain);
C
Chris Lalancette 已提交
6801 6802 6803 6804 6805 6806 6807 6808 6809
        return -1;
    }

    virDomainFree(domain);

    return 0;
}

static int
6810 6811 6812 6813 6814 6815 6816
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)
C
Chris Lalancette 已提交
6817 6818 6819 6820
{
    virDomainPtr domain;

    if (args->nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) {
6821
        remoteDispatchFormatError(rerr, "%s",
C
Chris Lalancette 已提交
6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843
                                   _("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) {
6844
        remoteDispatchConnError(rerr, conn);
C
Chris Lalancette 已提交
6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855
        virDomainFree(domain);
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    virDomainFree(domain);

    return 0;
}

static int
6856 6857 6858 6859 6860 6861 6862
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)
C
Chris Lalancette 已提交
6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875
{
    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) {
        remoteDispatchConnError(rerr, conn);
6876
        virDomainFree(domain);
C
Chris Lalancette 已提交
6877 6878 6879
        return -1;
    }

6880
    make_nonnull_domain_snapshot(&ret->snap, snapshot);
C
Chris Lalancette 已提交
6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908

    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) {
        remoteDispatchConnError(rerr, conn);
6909
        virDomainFree(domain);
C
Chris Lalancette 已提交
6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940
        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) {
        remoteDispatchConnError(rerr, conn);
6941
        virDomainFree(domain);
C
Chris Lalancette 已提交
6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953
        return -1;
    }

    make_nonnull_domain_snapshot(&ret->snap, snapshot);

    virDomainSnapshotFree(snapshot);
    virDomainFree(domain);

    return 0;
}

static int
6954 6955 6956 6957 6958 6959 6960
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)
C
Chris Lalancette 已提交
6961
{
6962 6963 6964
    virDomainPtr domain = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    int rc = -1;
C
Chris Lalancette 已提交
6965

6966 6967 6968 6969 6970 6971 6972
    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 已提交
6973

6974 6975 6976 6977 6978 6979
    if (virDomainRevertToSnapshot(snapshot, args->flags) == -1)
        goto cleanup;

    rc = 0;

cleanup:
6980 6981
    if (rc < 0)
        remoteDispatchConnError(rerr, conn);
6982
    if (snapshot)
C
Chris Lalancette 已提交
6983
        virDomainSnapshotFree(snapshot);
6984 6985
    if (domain)
        virDomainFree(domain);
C
Chris Lalancette 已提交
6986

6987
    return rc;
C
Chris Lalancette 已提交
6988 6989 6990
}

static int
6991 6992 6993 6994 6995 6996 6997
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)
C
Chris Lalancette 已提交
6998
{
6999 7000 7001
    virDomainPtr domain = NULL;
    virDomainSnapshotPtr snapshot = NULL;
    int rc = -1;
C
Chris Lalancette 已提交
7002

7003 7004 7005 7006 7007 7008 7009
    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 已提交
7010

7011 7012 7013 7014 7015 7016
    if (virDomainSnapshotDelete(snapshot, args->flags) == -1)
        goto cleanup;

    rc = 0;

cleanup:
7017 7018
    if (rc < 0)
        remoteDispatchConnError(rerr, conn);
7019
    if (snapshot)
C
Chris Lalancette 已提交
7020
        virDomainSnapshotFree(snapshot);
7021 7022
    if (domain)
        virDomainFree(domain);
C
Chris Lalancette 已提交
7023

7024
    return rc;
C
Chris Lalancette 已提交
7025 7026
}

7027

7028
static int
7029 7030 7031 7032 7033 7034 7035
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)
7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066
{
    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
7067 7068 7069 7070 7071 7072 7073
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)
7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099
{
    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;
}


7100 7101

static int
7102 7103 7104 7105 7106 7107 7108
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)
7109 7110 7111
{
    virNWFilterPtr nwfilter;

7112
    nwfilter = virNWFilterLookupByName(conn, args->name);
7113 7114 7115 7116 7117
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

7118
    make_nonnull_nwfilter(&ret->nwfilter, nwfilter);
7119 7120 7121 7122 7123
    virNWFilterFree(nwfilter);
    return 0;
}

static int
7124 7125 7126 7127 7128 7129 7130
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)
7131 7132 7133
{
    virNWFilterPtr nwfilter;

7134
    nwfilter = virNWFilterLookupByUUID(conn, (unsigned char *) args->uuid);
7135 7136 7137 7138 7139
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

7140
    make_nonnull_nwfilter(&ret->nwfilter, nwfilter);
7141 7142 7143 7144 7145 7146
    virNWFilterFree(nwfilter);
    return 0;
}


static int
7147 7148 7149 7150 7151 7152 7153
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)
7154 7155 7156
{
    virNWFilterPtr nwfilter;

7157
    nwfilter = virNWFilterDefineXML(conn, args->xml);
7158 7159 7160 7161 7162
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

7163
    make_nonnull_nwfilter(&ret->nwfilter, nwfilter);
7164 7165 7166 7167 7168 7169
    virNWFilterFree(nwfilter);
    return 0;
}


static int
7170 7171 7172 7173 7174 7175 7176
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)
7177 7178 7179
{
    virNWFilterPtr nwfilter;

7180
    nwfilter = get_nonnull_nwfilter(conn, args->nwfilter);
7181 7182 7183 7184 7185
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

7186
    if (virNWFilterUndefine(nwfilter) == -1) {
7187
        remoteDispatchConnError(rerr, conn);
7188
        virNWFilterFree(nwfilter);
7189 7190 7191 7192 7193 7194 7195
        return -1;
    }
    virNWFilterFree(nwfilter);
    return 0;
}

static int
7196 7197 7198 7199 7200 7201 7202
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)
7203 7204 7205
{

    if (args->maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) {
7206
        remoteDispatchFormatError(rerr,
7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217
                                   "%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 =
7218 7219
        virConnectListNWFilters(conn,
                                ret->names.names_val, args->maxnames);
7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


static int
7231 7232 7233 7234 7235 7236 7237
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)
7238 7239 7240
{
    virNWFilterPtr nwfilter;

7241
    nwfilter = get_nonnull_nwfilter(conn, args->nwfilter);
7242 7243 7244 7245 7246 7247
    if (nwfilter == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* remoteDispatchClientRequest will free this. */
7248
    ret->xml = virNWFilterGetXMLDesc(nwfilter, args->flags);
7249 7250
    if (!ret->xml) {
        remoteDispatchConnError(rerr, conn);
7251
        virNWFilterFree(nwfilter);
7252 7253 7254 7255 7256 7257 7258 7259
        return -1;
    }
    virNWFilterFree(nwfilter);
    return 0;
}


static int
7260 7261 7262 7263 7264 7265 7266
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)
7267 7268
{

7269
    ret->num = virConnectNumOfNWFilters(conn);
7270 7271 7272 7273 7274 7275 7276 7277 7278
    if (ret->num == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


7279
static int
7280 7281 7282 7283 7284 7285 7286
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)
7287 7288 7289 7290
{
    virDomainPtr dom;
    virDomainBlockInfo info;

7291
    dom = get_nonnull_domain(conn, args->dom);
7292 7293 7294 7295 7296
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

7297
    if (virDomainGetBlockInfo(dom, args->path, &info, args->flags) == -1) {
7298
        remoteDispatchConnError(rerr, conn);
7299
        virDomainFree(dom);
7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311
        return -1;
    }

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

    virDomainFree(dom);

    return 0;
}

C
Chris Lalancette 已提交
7312
static int
7313 7314 7315 7316 7317 7318 7319
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)
C
Chris Lalancette 已提交
7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331
{
    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) {
        remoteDispatchConnError(rerr, conn);
7332
        virDomainFree(domain);
C
Chris Lalancette 已提交
7333 7334 7335 7336 7337 7338 7339 7340
        return -1;
    }

    virDomainFree(domain);

    return 0;
}

7341

7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356
static int
remoteDispatchDomainOpenConsole(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client,
                                virConnectPtr conn,
                                remote_message_header *hdr,
                                remote_error *rerr,
                                remote_domain_open_console_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    int r;
    struct qemud_client_stream *stream;
    virDomainPtr dom;

    CHECK_CONN (client);

7357
    dom = get_nonnull_domain(conn, args->domain);
7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371 7372 7373 7374
    if (dom == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

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

    r = virDomainOpenConsole(dom,
                             args->devname ? *args->devname : NULL,
                             stream->st,
                             args->flags);
    if (r == -1) {
7375
        remoteDispatchConnError(rerr, conn);
7376 7377 7378 7379 7380 7381 7382
        virDomainFree(dom);
        remoteFreeClientStream(client, stream);
        return -1;
    }

    if (remoteAddClientStream(client, stream, 1) < 0) {
        remoteDispatchConnError(rerr, conn);
7383
        virDomainFree(dom);
7384 7385 7386 7387 7388 7389 7390 7391 7392 7393
        virStreamAbort(stream->st);
        remoteFreeClientStream(client, stream);
        return -1;
    }

    virDomainFree(dom);
    return 0;
}


7394 7395 7396 7397 7398 7399 7400 7401 7402
/*----- 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
7403
get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain)
7404 7405
{
    virDomainPtr dom;
7406
    dom = virGetDomain(conn, domain.name, BAD_CAST domain.uuid);
7407 7408 7409 7410 7411 7412 7413 7414
    /* 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
7415
get_nonnull_network(virConnectPtr conn, remote_nonnull_network network)
7416
{
7417
    return virGetNetwork(conn, network.name, BAD_CAST network.uuid);
7418 7419
}

D
Daniel Veillard 已提交
7420
static virInterfacePtr
7421
get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface)
D
Daniel Veillard 已提交
7422
{
7423
    return virGetInterface(conn, iface.name, iface.mac);
D
Daniel Veillard 已提交
7424 7425
}

7426
static virStoragePoolPtr
7427
get_nonnull_storage_pool(virConnectPtr conn, remote_nonnull_storage_pool pool)
7428
{
7429
    return virGetStoragePool(conn, pool.name, BAD_CAST pool.uuid);
7430 7431 7432
}

static virStorageVolPtr
7433
get_nonnull_storage_vol(virConnectPtr conn, remote_nonnull_storage_vol vol)
7434 7435
{
    virStorageVolPtr ret;
7436
    ret = virGetStorageVol(conn, vol.pool, vol.name, vol.key);
7437 7438 7439
    return ret;
}

7440
static virSecretPtr
7441
get_nonnull_secret(virConnectPtr conn, remote_nonnull_secret secret)
7442
{
7443
    return virGetSecret(conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
7444 7445
}

7446
static virNWFilterPtr
7447
get_nonnull_nwfilter(virConnectPtr conn, remote_nonnull_nwfilter nwfilter)
7448
{
7449
    return virGetNWFilter(conn, nwfilter.name, BAD_CAST nwfilter.uuid);
7450 7451
}

C
Chris Lalancette 已提交
7452
static virDomainSnapshotPtr
7453
get_nonnull_domain_snapshot(virDomainPtr domain, remote_nonnull_domain_snapshot snapshot)
C
Chris Lalancette 已提交
7454 7455 7456 7457
{
    return virGetDomainSnapshot(domain, snapshot.name);
}

7458 7459
/* Make remote_nonnull_domain and remote_nonnull_network. */
static void
7460
make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
7461 7462
{
    dom_dst->id = dom_src->id;
7463 7464
    dom_dst->name = strdup(dom_src->name);
    memcpy(dom_dst->uuid, dom_src->uuid, VIR_UUID_BUFLEN);
7465 7466 7467
}

static void
7468
make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src)
7469
{
7470 7471
    net_dst->name = strdup(net_src->name);
    memcpy(net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN);
7472 7473
}

D
Daniel Veillard 已提交
7474
static void
7475 7476
make_nonnull_interface(remote_nonnull_interface *interface_dst,
                       virInterfacePtr interface_src)
D
Daniel Veillard 已提交
7477
{
7478 7479
    interface_dst->name = strdup(interface_src->name);
    interface_dst->mac = strdup(interface_src->mac);
D
Daniel Veillard 已提交
7480 7481
}

7482
static void
7483
make_nonnull_storage_pool(remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
7484
{
7485 7486
    pool_dst->name = strdup(pool_src->name);
    memcpy(pool_dst->uuid, pool_src->uuid, VIR_UUID_BUFLEN);
7487 7488 7489
}

static void
7490
make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src)
7491
{
7492 7493 7494
    vol_dst->pool = strdup(vol_src->pool);
    vol_dst->name = strdup(vol_src->name);
    vol_dst->key = strdup(vol_src->key);
7495
}
7496 7497

static void
7498
make_nonnull_node_device(remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src)
7499 7500 7501
{
    dev_dst->name = strdup(dev_src->name);
}
7502 7503

static void
7504
make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
7505
{
7506
    memcpy(secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
7507
    secret_dst->usageType = secret_src->usageType;
7508
    secret_dst->usageID = strdup(secret_src->usageID);
7509
}
7510 7511

static void
7512
make_nonnull_nwfilter(remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src)
7513
{
7514 7515
    nwfilter_dst->name = strdup(nwfilter_src->name);
    memcpy(nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
7516
}
C
Chris Lalancette 已提交
7517 7518

static void
7519
make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src)
C
Chris Lalancette 已提交
7520 7521 7522 7523
{
    snapshot_dst->name = strdup(snapshot_src->name);
    make_nonnull_domain(&snapshot_dst->domain, snapshot_src->domain);
}