remote.c 200.5 KB
Newer Older
1
/*
2
 * remote.c: handlers for RPC method calls
3
 *
4
 * Copyright (C) 2007, 2008, 2009 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 "virterror_internal.h"
45

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

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

54 55
#include "libvirt_internal.h"
#include "datatypes.h"
56
#include "memory.h"
57
#include "util.h"
C
Chris Lalancette 已提交
58
#include "stream.h"
59

60
#define VIR_FROM_THIS VIR_FROM_REMOTE
61
#define REMOTE_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
62

63 64
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
65
static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface);
66 67
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);
68
static virSecretPtr get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret);
69
static virNWFilterPtr get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter);
70 71
static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
D
Daniel Veillard 已提交
72
static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
73 74
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);
75
static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src);
76
static void make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
77
static void make_nonnull_nwfilter (remote_nonnull_nwfilter *net_dst, virNWFilterPtr nwfilter_src);
78

79

80
#include "remote_dispatch_prototypes.h"
81 82 83 84

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

86 87 88 89 90 91 92 93 94 95
const dispatch_data const *remoteGetDispatchData(int proc)
{
    if (proc >= ARRAY_CARDINALITY(dispatch_table) ||
        dispatch_table[proc].fn == NULL) {
        return NULL;
    }

    return &(dispatch_table[proc]);
}

96 97 98
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
99 100 101
                               int procnr,
                               xdrproc_t proc,
                               void *data);
102

103 104 105 106 107
static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           int event,
                                           int detail,
                                           void *opaque)
108 109
{
    struct qemud_client *client = opaque;
110
    remote_domain_event_lifecycle_msg data;
111

112 113 114 115
    if (!client)
        return -1;

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

117
    virMutexLock(&client->lock);
118

119 120 121 122 123
    /* build return data */
    memset(&data, 0, sizeof data);
    make_nonnull_domain (&data.dom, dom);
    data.event = event;
    data.detail = detail;
124

125
    remoteDispatchDomainEventSend (client,
126 127
                                   REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
                                   (xdrproc_t)xdr_remote_domain_event_lifecycle_msg, &data);
128 129

    virMutexUnlock(&client->lock);
130

131 132
    return 0;
}
133

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED,
                                        virDomainPtr dom,
                                        void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_reboot_msg data;

    if (!client)
        return -1;

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

    virMutexLock(&client->lock);

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

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

    virMutexUnlock(&client->lock);

    return 0;
}

161

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           long long offset,
                                           void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_rtc_change_msg data;

    if (!client)
        return -1;

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

    virMutexLock(&client->lock);

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

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

    virMutexUnlock(&client->lock);

    return 0;
}


192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          int action,
                                          void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_watchdog_msg data;

    if (!client)
        return -1;

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

    virMutexLock(&client->lock);

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

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

    virMutexUnlock(&client->lock);

    return 0;
}


222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED,
                                         virDomainPtr dom,
                                         const char *srcPath,
                                         const char *devAlias,
                                         int action,
                                         void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_io_error_msg data;

    if (!client)
        return -1;

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

    virMutexLock(&client->lock);

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

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

    virMutexUnlock(&client->lock);

    return 0;
}


256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED,
                                          virDomainPtr dom,
                                          int phase,
                                          virDomainEventGraphicsAddressPtr local,
                                          virDomainEventGraphicsAddressPtr remote,
                                          const char *authScheme,
                                          virDomainEventGraphicsSubjectPtr subject,
                                          void *opaque)
{
    struct qemud_client *client = opaque;
    remote_domain_event_graphics_msg data;
    int i;

    if (!client)
        return -1;

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

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

    virMutexLock(&client->lock);

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

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

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

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

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

    VIR_FREE(data.subject.subject_val);

    virMutexUnlock(&client->lock);

    return 0;
}


320
static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
321
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
322
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
323
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventRTCChange),
324
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog),
325
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
326
    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
327 328 329 330
};

verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);

331 332 333
/*----- Functions. -----*/

static int
334
remoteDispatchOpen (struct qemud_server *server,
335
                    struct qemud_client *client,
336
                    virConnectPtr conn,
337
                    remote_message_header *hdr ATTRIBUTE_UNUSED,
338
                    remote_error *rerr,
339 340 341
                    struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED)
{
    const char *name;
342
    int flags, rc;
343 344

    /* Already opened? */
345
    if (conn) {
346 347
        remoteDispatchFormatError (rerr, "%s", _("connection already open"));
        return -1;
348 349
    }

350 351 352
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
353

354 355 356 357 358 359 360 361 362 363 364 365 366
    name = args->name ? *args->name : NULL;

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

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

367
    if (client->conn == NULL)
368 369
        remoteDispatchConnError(rerr, NULL);

370
    rc = client->conn ? 0 : -1;
371
    virMutexUnlock(&client->lock);
372
    return rc;
373 374
}

375 376 377 378
#define CHECK_CONN(client)                                              \
    if (!client->conn) {                                                \
        remoteDispatchFormatError (rerr, "%s", _("connection not open")); \
        return -1;                                                      \
379 380 381
    }

static int
382
remoteDispatchClose (struct qemud_server *server ATTRIBUTE_UNUSED,
383 384
                     struct qemud_client *client ATTRIBUTE_UNUSED,
                     virConnectPtr conn ATTRIBUTE_UNUSED,
385
                     remote_message_header *hdr ATTRIBUTE_UNUSED,
386
                     remote_error *rerr ATTRIBUTE_UNUSED,
387 388
                     void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
{
389 390 391
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
392

393
    client->closing = 1;
394

395
    virMutexUnlock(&client->lock);
396
    return 0;
397 398
}

399
static int
400
remoteDispatchSupportsFeature (struct qemud_server *server ATTRIBUTE_UNUSED,
401 402
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
403
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
404
                               remote_error *rerr,
405 406
                               remote_supports_feature_args *args, remote_supports_feature_ret *ret)
{
407
    ret->supported = virDrvSupportsFeature (conn, args->feature);
408 409

    if (ret->supported == -1) {
410
        remoteDispatchConnError(rerr, conn);
411 412
        return -1;
    }
413 414 415 416

    return 0;
}

417
static int
418
remoteDispatchGetType (struct qemud_server *server ATTRIBUTE_UNUSED,
419 420
                       struct qemud_client *client ATTRIBUTE_UNUSED,
                       virConnectPtr conn,
421
                       remote_message_header *hdr ATTRIBUTE_UNUSED,
422
                       remote_error *rerr,
423 424 425 426
                       void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret)
{
    const char *type;

427
    type = virConnectGetType (conn);
428
    if (type == NULL) {
429
        remoteDispatchConnError(rerr, conn);
430 431
        return -1;
    }
432 433 434 435 436 437

    /* We have to strdup because remoteDispatchClientRequest will
     * free this string after it's been serialised.
     */
    ret->type = strdup (type);
    if (!ret->type) {
438
        remoteDispatchOOMError(rerr);
439
        return -1;
440 441 442 443 444 445
    }

    return 0;
}

static int
446
remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
447 448
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
449
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
450
                          remote_error *rerr,
451 452 453 454 455
                          void *args ATTRIBUTE_UNUSED,
                          remote_get_version_ret *ret)
{
    unsigned long hvVer;

456 457
    if (virConnectGetVersion (conn, &hvVer) == -1) {
        remoteDispatchConnError(rerr, conn);
458
        return -1;
459
    }
460 461 462 463 464

    ret->hv_ver = hvVer;
    return 0;
}

465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
static int
remoteDispatchGetLibVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *rerr,
                             void *args ATTRIBUTE_UNUSED,
                             remote_get_lib_version_ret *ret)
{
    unsigned long libVer;

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

    ret->lib_ver = libVer;
    return 0;
}

485
static int
486
remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED,
487 488
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
489
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
490
                           remote_error *rerr,
491 492 493 494 495
                           void *args ATTRIBUTE_UNUSED,
                           remote_get_hostname_ret *ret)
{
    char *hostname;

496
    hostname = virConnectGetHostname (conn);
497
    if (hostname == NULL) {
498
        remoteDispatchConnError(rerr, conn);
499 500
        return -1;
    }
501 502 503 504 505

    ret->hostname = hostname;
    return 0;
}

506 507
static int
remoteDispatchGetUri (struct qemud_server *server ATTRIBUTE_UNUSED,
508 509
                      struct qemud_client *client ATTRIBUTE_UNUSED,
                      virConnectPtr conn,
510
                      remote_message_header *hdr ATTRIBUTE_UNUSED,
511
                      remote_error *rerr,
512 513 514 515 516 517
                      void *args ATTRIBUTE_UNUSED,
                      remote_get_uri_ret *ret)
{
    char *uri;
    CHECK_CONN(client);

518
    uri = virConnectGetURI (conn);
519
    if (uri == NULL) {
520
        remoteDispatchConnError(rerr, conn);
521 522
        return -1;
    }
523 524 525 526 527

    ret->uri = uri;
    return 0;
}

528
static int
529
remoteDispatchGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
530 531
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
532
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
533
                           remote_error *rerr,
534 535 536 537 538 539
                           remote_get_max_vcpus_args *args,
                           remote_get_max_vcpus_ret *ret)
{
    char *type;

    type = args->type ? *args->type : NULL;
540
    ret->max_vcpus = virConnectGetMaxVcpus (conn, type);
541
    if (ret->max_vcpus == -1) {
542
        remoteDispatchConnError(rerr, conn);
543 544
        return -1;
    }
545 546 547 548 549

    return 0;
}

static int
550
remoteDispatchNodeGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
551 552
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
553
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
554
                           remote_error *rerr,
555 556 557 558 559
                           void *args ATTRIBUTE_UNUSED,
                           remote_node_get_info_ret *ret)
{
    virNodeInfo info;

560 561
    if (virNodeGetInfo (conn, &info) == -1) {
        remoteDispatchConnError(rerr, conn);
562
        return -1;
563
    }
564 565 566 567 568 569 570 571 572 573 574 575 576 577

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

    return 0;
}

static int
578
remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED,
579 580
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
581
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
582
                               remote_error *rerr,
583 584 585 586 587
                               void *args ATTRIBUTE_UNUSED,
                               remote_get_capabilities_ret *ret)
{
    char *caps;

588
    caps = virConnectGetCapabilities (conn);
589
    if (caps == NULL) {
590
        remoteDispatchConnError(rerr, conn);
591 592
        return -1;
    }
593 594 595 596 597

    ret->capabilities = caps;
    return 0;
}

598 599
static int
remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
600 601
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
602
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
603
                                      remote_error *rerr,
604 605 606
                                      remote_node_get_cells_free_memory_args *args,
                                      remote_node_get_cells_free_memory_ret *ret)
{
D
Daniel P. Berrange 已提交
607
    int err;
608 609

    if (args->maxCells > REMOTE_NODE_MAX_CELLS) {
610 611 612
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxCells > REMOTE_NODE_MAX_CELLS"));
        return -1;
613 614 615
    }

    /* Allocate return buffer. */
616
    if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) {
617 618
        remoteDispatchOOMError(rerr);
        return -1;
619
    }
620

D
Daniel P. Berrange 已提交
621 622 623 624 625
    err = virNodeGetCellsFreeMemory(conn,
                                    (unsigned long long *)ret->freeMems.freeMems_val,
                                    args->startCell,
                                    args->maxCells);
    if (err <= 0) {
626
        VIR_FREE(ret->freeMems.freeMems_val);
627
        remoteDispatchConnError(rerr, conn);
628
        return -1;
629
    }
D
Daniel P. Berrange 已提交
630
    ret->freeMems.freeMems_len = err;
631 632 633 634 635 636 637

    return 0;
}


static int
remoteDispatchNodeGetFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
638 639
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
640
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
641
                                 remote_error *rerr,
642 643 644 645 646
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_node_get_free_memory_ret *ret)
{
    unsigned long long freeMem;

647
    freeMem = virNodeGetFreeMemory(conn);
648
    if (freeMem == 0) {
649
        remoteDispatchConnError(rerr, conn);
650 651
        return -1;
    }
652 653 654 655 656
    ret->freeMem = freeMem;
    return 0;
}


657
static int
658
remoteDispatchDomainGetSchedulerType (struct qemud_server *server ATTRIBUTE_UNUSED,
659 660
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
661
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
662
                                      remote_error *rerr,
663 664 665 666 667 668 669
                                      remote_domain_get_scheduler_type_args *args,
                                      remote_domain_get_scheduler_type_ret *ret)
{
    virDomainPtr dom;
    char *type;
    int nparams;

670
    dom = get_nonnull_domain (conn, args->dom);
671
    if (dom == NULL) {
672
        remoteDispatchConnError(rerr, conn);
673
        return -1;
674 675 676
    }

    type = virDomainGetSchedulerType (dom, &nparams);
677 678
    if (type == NULL) {
        virDomainFree(dom);
679
        remoteDispatchConnError(rerr, conn);
680 681
        return -1;
    }
682 683 684

    ret->type = type;
    ret->nparams = nparams;
685
    virDomainFree(dom);
686 687 688 689
    return 0;
}

static int
690
remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
691 692
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
693
                                            remote_message_header *hdr ATTRIBUTE_UNUSED,
694
                                            remote_error *rerr,
695 696 697 698 699 700 701 702 703 704
                                            remote_domain_get_scheduler_parameters_args *args,
                                            remote_domain_get_scheduler_parameters_ret *ret)
{
    virDomainPtr dom;
    virSchedParameterPtr params;
    int i, r, nparams;

    nparams = args->nparams;

    if (nparams > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX) {
705 706
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
707
    }
708
    if (VIR_ALLOC_N(params, nparams) < 0) {
709 710
        remoteDispatchOOMError(rerr);
        return -1;
711 712
    }

713
    dom = get_nonnull_domain (conn, args->dom);
714
    if (dom == NULL) {
715
        VIR_FREE(params);
716
        remoteDispatchConnError(rerr, conn);
717
        return -1;
718 719 720 721
    }

    r = virDomainGetSchedulerParameters (dom, params, &nparams);
    if (r == -1) {
722
        virDomainFree(dom);
723
        VIR_FREE(params);
724
        remoteDispatchConnError(rerr, conn);
725 726 727 728 729
        return -1;
    }

    /* Serialise the scheduler parameters. */
    ret->params.params_len = nparams;
730 731
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;
732 733 734 735

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

739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
        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:
754
            remoteDispatchFormatError (rerr, "%s", _("unknown type"));
755
            goto cleanup;
756 757
        }
    }
758
    virDomainFree(dom);
759
    VIR_FREE(params);
760 761

    return 0;
762 763

oom:
764
    remoteDispatchOOMError(rerr);
765 766 767 768 769
cleanup:
    virDomainFree(dom);
    for (i = 0 ; i < nparams ; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
770
    return -1;
771 772 773
}

static int
774
remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
775 776
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
777
                                            remote_message_header *hdr ATTRIBUTE_UNUSED,
778
                                            remote_error *rerr,
779 780 781 782 783 784 785 786 787 788
                                            remote_domain_set_scheduler_parameters_args *args,
                                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int i, r, nparams;
    virSchedParameterPtr params;

    nparams = args->params.params_len;

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

    /* Deserialise parameters. */
    for (i = 0; i < nparams; ++i) {
C
Chris Lalancette 已提交
799 800 801 802 803
        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;
        }
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
        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;
        }
    }

821
    dom = get_nonnull_domain (conn, args->dom);
822
    if (dom == NULL) {
823
        VIR_FREE(params);
824
        remoteDispatchConnError(rerr, conn);
825
        return -1;
826 827 828
    }

    r = virDomainSetSchedulerParameters (dom, params, nparams);
829
    virDomainFree(dom);
830
    VIR_FREE(params);
831
    if (r == -1) {
832
        remoteDispatchConnError(rerr, conn);
833 834
        return -1;
    }
835 836 837 838

    return 0;
}

839
static int
840
remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED,
841 842
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
843
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
844
                                remote_error *rerr,
845 846 847 848 849 850 851
                                remote_domain_block_stats_args *args,
                                remote_domain_block_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainBlockStats stats;

852
    dom = get_nonnull_domain (conn, args->dom);
853
    if (dom == NULL) {
854
        remoteDispatchConnError(rerr, conn);
855
        return -1;
856 857 858
    }
    path = args->path;

D
Daniel P. Berrange 已提交
859 860
    if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
861
        remoteDispatchConnError(rerr, conn);
862
        return -1;
D
Daniel P. Berrange 已提交
863 864
    }
    virDomainFree (dom);
865 866 867 868 869 870 871 872 873 874 875

    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
876
remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED,
877 878
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
879
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
880
                                    remote_error *rerr,
881 882 883 884 885 886 887
                                    remote_domain_interface_stats_args *args,
                                    remote_domain_interface_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainInterfaceStats stats;

888
    dom = get_nonnull_domain (conn, args->dom);
889
    if (dom == NULL) {
890
        remoteDispatchConnError(rerr, conn);
891
        return -1;
892 893 894
    }
    path = args->path;

D
Daniel P. Berrange 已提交
895 896
    if (virDomainInterfaceStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
897
        remoteDispatchConnError(rerr, conn);
898
        return -1;
D
Daniel P. Berrange 已提交
899 900
    }
    virDomainFree (dom);
901 902 903 904 905 906 907 908 909 910 911 912 913

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

914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
static int
remoteDispatchDomainMemoryStats (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_domain_memory_stats_args *args,
                                 remote_domain_memory_stats_ret *ret)
{
    virDomainPtr dom;
    struct _virDomainMemoryStat *stats;
    unsigned int nr_stats, i;

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

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

    /* Allocate stats array for making dispatch call */
    if (VIR_ALLOC_N(stats, args->maxStats) < 0) {
        remoteDispatchOOMError(rerr);
        return -1;
     }

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

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

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

970 971
static int
remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
972 973
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
974
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
975
                               remote_error *rerr,
976 977 978 979 980 981 982 983 984
                               remote_domain_block_peek_args *args,
                               remote_domain_block_peek_ret *ret)
{
    virDomainPtr dom;
    char *path;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

985
    dom = get_nonnull_domain (conn, args->dom);
986
    if (dom == NULL) {
987
        remoteDispatchConnError(rerr, conn);
988
        return -1;
989 990 991 992 993 994 995
    }
    path = args->path;
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
996
        virDomainFree (dom);
997 998 999
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
1000 1001 1002
    }

    ret->buffer.buffer_len = size;
1003
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
1004
        virDomainFree (dom);
1005
        remoteDispatchOOMError(rerr);
1006
        return -1;
1007 1008 1009 1010 1011 1012
    }

    if (virDomainBlockPeek (dom, path, offset, size,
                            ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
1013
        remoteDispatchConnError(rerr, conn);
1014 1015 1016 1017 1018 1019 1020
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

R
Richard W.M. Jones 已提交
1021 1022
static int
remoteDispatchDomainMemoryPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
1023 1024
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
1025
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
1026
                                remote_error *rerr,
R
Richard W.M. Jones 已提交
1027 1028 1029 1030 1031 1032 1033 1034
                                remote_domain_memory_peek_args *args,
                                remote_domain_memory_peek_ret *ret)
{
    virDomainPtr dom;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

1035
    dom = get_nonnull_domain (conn, args->dom);
R
Richard W.M. Jones 已提交
1036
    if (dom == NULL) {
1037
        remoteDispatchConnError(rerr, conn);
1038
        return -1;
R
Richard W.M. Jones 已提交
1039 1040 1041 1042 1043 1044
    }
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
1045
        virDomainFree (dom);
1046 1047 1048
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
R
Richard W.M. Jones 已提交
1049 1050 1051 1052 1053
    }

    ret->buffer.buffer_len = size;
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
        virDomainFree (dom);
1054
        remoteDispatchOOMError(rerr);
1055
        return -1;
R
Richard W.M. Jones 已提交
1056 1057 1058 1059 1060 1061
    }

    if (virDomainMemoryPeek (dom, offset, size,
                             ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
1062
        remoteDispatchConnError(rerr, conn);
R
Richard W.M. Jones 已提交
1063 1064 1065 1066 1067 1068 1069
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

1070
static int
1071
remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1072 1073
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1074
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1075
                                  remote_error *rerr,
1076 1077 1078 1079 1080
                                  remote_domain_attach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1081
    dom = get_nonnull_domain (conn, args->dom);
1082
    if (dom == NULL) {
1083
        remoteDispatchConnError(rerr, conn);
1084
        return -1;
1085 1086
    }

1087 1088
    if (virDomainAttachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
1089
        remoteDispatchConnError(rerr, conn);
1090
        return -1;
1091 1092
    }
    virDomainFree(dom);
1093 1094 1095
    return 0;
}

J
Jim Fehlig 已提交
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
static int
remoteDispatchDomainAttachDeviceFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_attach_device_flags_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

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

1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
static int
remoteDispatchDomainUpdateDeviceFlags (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr,
                                       remote_domain_update_device_flags_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

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

1148
static int
1149
remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
1150 1151
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1152
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
1153
                            remote_error *rerr,
1154 1155 1156 1157 1158
                            remote_domain_create_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1159
    dom = get_nonnull_domain (conn, args->dom);
1160
    if (dom == NULL) {
1161
        remoteDispatchConnError(rerr, conn);
1162
        return -1;
1163 1164
    }

1165 1166
    if (virDomainCreate (dom) == -1) {
        virDomainFree(dom);
1167
        remoteDispatchConnError(rerr, conn);
1168
        return -1;
1169 1170
    }
    virDomainFree(dom);
1171 1172 1173 1174
    return 0;
}

static int
1175
remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1176 1177
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1178
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1179 1180 1181
                               remote_error *rerr,
                               remote_domain_create_xml_args *args,
                               remote_domain_create_xml_ret *ret)
1182 1183 1184
{
    virDomainPtr dom;

1185
    dom = virDomainCreateXML (conn, args->xml_desc, args->flags);
1186
    if (dom == NULL) {
1187
        remoteDispatchConnError(rerr, conn);
1188 1189
        return -1;
    }
1190 1191

    make_nonnull_domain (&ret->dom, dom);
1192
    virDomainFree(dom);
1193 1194 1195 1196 1197

    return 0;
}

static int
1198
remoteDispatchDomainDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1199 1200
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1201
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1202
                               remote_error *rerr,
1203 1204 1205 1206 1207
                               remote_domain_define_xml_args *args,
                               remote_domain_define_xml_ret *ret)
{
    virDomainPtr dom;

1208
    dom = virDomainDefineXML (conn, args->xml);
1209
    if (dom == NULL) {
1210
        remoteDispatchConnError(rerr, conn);
1211 1212
        return -1;
    }
1213 1214

    make_nonnull_domain (&ret->dom, dom);
1215
    virDomainFree(dom);
1216 1217 1218 1219 1220

    return 0;
}

static int
1221
remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
1222 1223
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1224
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1225
                             remote_error *rerr,
1226 1227 1228 1229 1230
                             remote_domain_destroy_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1231
    dom = get_nonnull_domain (conn, args->dom);
1232
    if (dom == NULL) {
1233
        remoteDispatchConnError(rerr, conn);
1234
        return -1;
1235 1236
    }

1237 1238
    if (virDomainDestroy (dom) == -1) {
        virDomainFree(dom);
1239
        remoteDispatchConnError(rerr, conn);
1240
        return -1;
1241 1242
    }
    virDomainFree(dom);
1243 1244 1245 1246
    return 0;
}

static int
1247
remoteDispatchDomainDetachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1248 1249
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1250
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1251
                                  remote_error *rerr,
1252 1253 1254 1255 1256
                                  remote_domain_detach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1257
    dom = get_nonnull_domain (conn, args->dom);
1258
    if (dom == NULL) {
1259
        remoteDispatchConnError(rerr, conn);
1260
        return -1;
1261 1262
    }

1263 1264
    if (virDomainDetachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
J
Jim Fehlig 已提交
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    virDomainFree(dom);
    return 0;
}

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

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

    if (virDomainDetachDeviceFlags (dom, args->xml, args->flags) == -1) {
        virDomainFree(dom);
1292
        remoteDispatchConnError(rerr, conn);
1293
        return -1;
1294
    }
1295

1296
    virDomainFree(dom);
1297 1298 1299 1300
    return 0;
}

static int
1301
remoteDispatchDomainDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1302 1303
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1304
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1305
                             remote_error *rerr,
1306 1307 1308 1309 1310
                             remote_domain_dump_xml_args *args,
                             remote_domain_dump_xml_ret *ret)
{
    virDomainPtr dom;

1311
    dom = get_nonnull_domain (conn, args->dom);
1312
    if (dom == NULL) {
1313
        remoteDispatchConnError(rerr, conn);
1314
        return -1;
1315 1316 1317 1318
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virDomainGetXMLDesc (dom, args->flags);
1319
    if (!ret->xml) {
1320
        virDomainFree(dom);
1321
        remoteDispatchConnError(rerr, conn);
1322
        return -1;
1323 1324
    }
    virDomainFree(dom);
1325 1326 1327
    return 0;
}

1328 1329 1330 1331
static int
remoteDispatchDomainXmlFromNative (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1332
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
                                   remote_error *rerr,
                                   remote_domain_xml_from_native_args *args,
                                   remote_domain_xml_from_native_ret *ret)
{
    /* remoteDispatchClientRequest will free this. */
    ret->domainXml = virConnectDomainXMLFromNative (conn,
                                                    args->nativeFormat,
                                                    args->nativeConfig,
                                                    args->flags);
    if (!ret->domainXml) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}

static int
remoteDispatchDomainXmlToNative (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1353
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
                                 remote_error *rerr,
                                 remote_domain_xml_to_native_args *args,
                                 remote_domain_xml_to_native_ret *ret)
{
    /* remoteDispatchClientRequest will free this. */
    ret->nativeConfig = virConnectDomainXMLToNative (conn,
                                                     args->nativeFormat,
                                                     args->domainXml,
                                                     args->flags);
    if (!ret->nativeConfig) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}


1371
static int
1372
remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1373 1374
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1375
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1376
                                  remote_error *rerr,
1377 1378 1379 1380 1381
                                  remote_domain_get_autostart_args *args,
                                  remote_domain_get_autostart_ret *ret)
{
    virDomainPtr dom;

1382
    dom = get_nonnull_domain (conn, args->dom);
1383
    if (dom == NULL) {
1384
        remoteDispatchConnError(rerr, conn);
1385
        return -1;
1386 1387
    }

1388 1389
    if (virDomainGetAutostart (dom, &ret->autostart) == -1) {
        virDomainFree(dom);
1390
        remoteDispatchConnError(rerr, conn);
1391
        return -1;
1392 1393
    }
    virDomainFree(dom);
1394 1395 1396 1397
    return 0;
}

static int
1398
remoteDispatchDomainGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
1399 1400
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1401
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1402
                             remote_error *rerr,
1403 1404 1405 1406 1407 1408
                             remote_domain_get_info_args *args,
                             remote_domain_get_info_ret *ret)
{
    virDomainPtr dom;
    virDomainInfo info;

1409
    dom = get_nonnull_domain (conn, args->dom);
1410
    if (dom == NULL) {
1411
        remoteDispatchConnError(rerr, conn);
1412
        return -1;
1413 1414
    }

1415 1416
    if (virDomainGetInfo (dom, &info) == -1) {
        virDomainFree(dom);
1417
        remoteDispatchConnError(rerr, conn);
1418
        return -1;
1419
    }
1420 1421 1422 1423 1424 1425 1426

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

1427 1428
    virDomainFree(dom);

1429 1430 1431 1432
    return 0;
}

static int
1433
remoteDispatchDomainGetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1434 1435
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1436
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1437
                                  remote_error *rerr,
1438 1439 1440 1441 1442
                                  remote_domain_get_max_memory_args *args,
                                  remote_domain_get_max_memory_ret *ret)
{
    virDomainPtr dom;

1443
    dom = get_nonnull_domain (conn, args->dom);
1444
    if (dom == NULL) {
1445
        remoteDispatchConnError(rerr, conn);
1446
        return -1;
1447 1448 1449
    }

    ret->memory = virDomainGetMaxMemory (dom);
1450 1451
    if (ret->memory == 0) {
        virDomainFree(dom);
1452
        remoteDispatchConnError(rerr, conn);
1453 1454 1455
        return -1;
    }
    virDomainFree(dom);
1456 1457 1458 1459
    return 0;
}

static int
1460
remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1461 1462
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1463
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
1464
                                 remote_error *rerr,
1465 1466 1467 1468 1469
                                 remote_domain_get_max_vcpus_args *args,
                                 remote_domain_get_max_vcpus_ret *ret)
{
    virDomainPtr dom;

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

    ret->num = virDomainGetMaxVcpus (dom);
1477 1478
    if (ret->num == -1) {
        virDomainFree(dom);
1479
        remoteDispatchConnError(rerr, conn);
1480 1481 1482
        return -1;
    }
    virDomainFree(dom);
1483 1484 1485
    return 0;
}

1486 1487 1488 1489
static int
remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1490
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
                                     remote_error *rerr,
                                     remote_domain_get_security_label_args *args,
                                     remote_domain_get_security_label_ret *ret)
{
    virDomainPtr dom;
    virSecurityLabel seclabel;

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

    memset(&seclabel, 0, sizeof seclabel);
    if (virDomainGetSecurityLabel(dom, &seclabel) == -1) {
        virDomainFree(dom);
1507
        remoteDispatchConnError(rerr, conn);
1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
        return -1;
    }

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

    return 0;
}

static int
remoteDispatchNodeGetSecurityModel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1528
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1529 1530 1531 1532 1533 1534 1535 1536
                                   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) {
1537
        remoteDispatchConnError(rerr, conn);
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
        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;
}

1558
static int
1559
remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED,
1560 1561
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1562
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1563
                               remote_error *rerr,
1564 1565 1566 1567 1568
                               remote_domain_get_os_type_args *args,
                               remote_domain_get_os_type_ret *ret)
{
    virDomainPtr dom;

1569
    dom = get_nonnull_domain (conn, args->dom);
1570
    if (dom == NULL) {
1571
        remoteDispatchConnError(rerr, conn);
1572
        return -1;
1573 1574 1575 1576
    }

    /* remoteDispatchClientRequest will free this */
    ret->type = virDomainGetOSType (dom);
1577
    if (ret->type == NULL) {
1578
        virDomainFree(dom);
1579
        remoteDispatchConnError(rerr, conn);
1580
        return -1;
1581 1582
    }
    virDomainFree(dom);
1583 1584 1585 1586
    return 0;
}

static int
1587
remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1588 1589
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1590
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
1591
                              remote_error *rerr,
1592 1593 1594
                              remote_domain_get_vcpus_args *args,
                              remote_domain_get_vcpus_ret *ret)
{
1595 1596 1597
    virDomainPtr dom = NULL;
    virVcpuInfoPtr info = NULL;
    unsigned char *cpumaps = NULL;
1598 1599
    int info_len, i;

1600
    dom = get_nonnull_domain (conn, args->dom);
1601
    if (dom == NULL) {
1602
        remoteDispatchConnError(rerr, conn);
1603
        return -1;
1604 1605 1606
    }

    if (args->maxinfo > REMOTE_VCPUINFO_MAX) {
1607
        virDomainFree(dom);
1608 1609
        remoteDispatchFormatError (rerr, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX"));
        return -1;
1610 1611
    }

1612
    if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
1613
        virDomainFree(dom);
1614 1615
        remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX"));
        return -1;
1616 1617 1618
    }

    /* Allocate buffers to take the results. */
1619 1620
    if (VIR_ALLOC_N(info, args->maxinfo) < 0)
        goto oom;
1621 1622
    if (args->maplen > 0 &&
        VIR_ALLOC_N(cpumaps, args->maxinfo * args->maplen) < 0)
1623
        goto oom;
1624 1625 1626 1627

    info_len = virDomainGetVcpus (dom,
                                  info, args->maxinfo,
                                  cpumaps, args->maplen);
1628
    if (info_len == -1) {
1629 1630
        VIR_FREE(info);
        VIR_FREE(cpumaps);
1631
        virDomainFree(dom);
1632
        remoteDispatchConnError(rerr, conn);
1633 1634
        return -1;
    }
1635 1636 1637

    /* Allocate the return buffer for info. */
    ret->info.info_len = info_len;
1638 1639
    if (VIR_ALLOC_N(ret->info.info_val, info_len) < 0)
        goto oom;
1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651

    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.
     */
1652
    ret->cpumaps.cpumaps_len = args->maxinfo * args->maplen;
1653 1654
    ret->cpumaps.cpumaps_val = (char *) cpumaps;

1655
    VIR_FREE(info);
1656
    virDomainFree(dom);
1657
    return 0;
1658 1659 1660 1661 1662

oom:
    VIR_FREE(info);
    VIR_FREE(cpumaps);
    virDomainFree(dom);
1663 1664
    remoteDispatchOOMError(rerr);
    return -1;
1665 1666
}

1667
static int
1668
remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED,
1669 1670
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1671
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1672
                                    remote_error *rerr,
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686
                                    remote_domain_migrate_prepare_args *args,
                                    remote_domain_migrate_prepare_ret *ret)
{
    int r;
    char *cookie = NULL;
    int cookielen = 0;
    char *uri_in;
    char **uri_out;
    char *dname;

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

    /* Wacky world of XDR ... */
1687
    if (VIR_ALLOC(uri_out) < 0) {
1688 1689
        remoteDispatchOOMError(rerr);
        return -1;
1690
    }
1691

1692
    r = virDomainMigratePrepare (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1693 1694
                                 uri_in, uri_out,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1695
    if (r == -1) {
1696
        VIR_FREE(uri_out);
1697
        remoteDispatchConnError(rerr, conn);
D
Daniel P. Berrange 已提交
1698 1699
        return -1;
    }
1700 1701 1702 1703 1704 1705

    /* 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 已提交
1706 1707
    if (*uri_out == NULL) {
        ret->uri_out = NULL;
1708
        VIR_FREE(uri_out);
D
Daniel P. Berrange 已提交
1709 1710 1711
    } else {
        ret->uri_out = uri_out;
    }
1712 1713 1714 1715 1716

    return 0;
}

static int
1717
remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED,
1718 1719
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1720
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1721
                                    remote_error *rerr,
1722 1723 1724 1725 1726 1727 1728
                                    remote_domain_migrate_perform_args *args,
                                    void *ret ATTRIBUTE_UNUSED)
{
    int r;
    virDomainPtr dom;
    char *dname;

1729
    dom = get_nonnull_domain (conn, args->dom);
1730
    if (dom == NULL) {
1731
        remoteDispatchConnError(rerr, conn);
1732
        return -1;
1733 1734 1735 1736
    }

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

D
Daniel P. Berrange 已提交
1737 1738 1739 1740 1741
    r = virDomainMigratePerform (dom,
                                 args->cookie.cookie_val,
                                 args->cookie.cookie_len,
                                 args->uri,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1742
    virDomainFree (dom);
1743
    if (r == -1) {
1744
        remoteDispatchConnError(rerr, conn);
1745 1746
        return -1;
    }
1747 1748 1749 1750 1751

    return 0;
}

static int
1752
remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED,
1753 1754
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1755
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1756
                                   remote_error *rerr,
1757 1758 1759 1760 1761 1762
                                   remote_domain_migrate_finish_args *args,
                                   remote_domain_migrate_finish_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1763
    ddom = virDomainMigrateFinish (conn, args->dname,
D
Daniel P. Berrange 已提交
1764 1765 1766 1767
                                   args->cookie.cookie_val,
                                   args->cookie.cookie_len,
                                   args->uri,
                                   args->flags);
1768
    if (ddom == NULL) {
1769
        remoteDispatchConnError(rerr, conn);
1770 1771
        return -1;
    }
1772 1773

    make_nonnull_domain (&ret->ddom, ddom);
D
Daniel P. Berrange 已提交
1774
    virDomainFree (ddom);
1775 1776 1777
    return 0;
}

D
Daniel Veillard 已提交
1778 1779
static int
remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1780 1781
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1782
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
1783
                                     remote_error *rerr,
D
Daniel Veillard 已提交
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799
                                     remote_domain_migrate_prepare2_args *args,
                                     remote_domain_migrate_prepare2_ret *ret)
{
    int r;
    char *cookie = NULL;
    int cookielen = 0;
    char *uri_in;
    char **uri_out;
    char *dname;
    CHECK_CONN (client);

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

    /* Wacky world of XDR ... */
    if (VIR_ALLOC(uri_out) < 0) {
1800 1801
        remoteDispatchOOMError(rerr);
        return -1;
D
Daniel Veillard 已提交
1802 1803
    }

1804
    r = virDomainMigratePrepare2 (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1805 1806 1807
                                  uri_in, uri_out,
                                  args->flags, dname, args->resource,
                                  args->dom_xml);
1808
    if (r == -1) {
1809
        remoteDispatchConnError(rerr, conn);
1810 1811
        return -1;
    }
D
Daniel Veillard 已提交
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824

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

    return 0;
}

static int
remoteDispatchDomainMigrateFinish2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1825 1826
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1827
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1828
                                    remote_error *rerr,
D
Daniel Veillard 已提交
1829 1830 1831 1832 1833 1834
                                    remote_domain_migrate_finish2_args *args,
                                    remote_domain_migrate_finish2_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1835
    ddom = virDomainMigrateFinish2 (conn, args->dname,
D
Daniel P. Berrange 已提交
1836 1837 1838 1839 1840
                                    args->cookie.cookie_val,
                                    args->cookie.cookie_len,
                                    args->uri,
                                    args->flags,
                                    args->retcode);
1841
    if (ddom == NULL) {
1842
        remoteDispatchConnError(rerr, conn);
1843 1844
        return -1;
    }
D
Daniel Veillard 已提交
1845 1846 1847 1848 1849 1850

    make_nonnull_domain (&ret->ddom, ddom);

    return 0;
}

C
Chris Lalancette 已提交
1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872
static int
remoteDispatchDomainMigratePrepareTunnel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                         struct qemud_client *client,
                                         virConnectPtr conn,
                                         remote_message_header *hdr,
                                         remote_error *rerr,
                                         remote_domain_migrate_prepare_tunnel_args *args,
                                         void *ret ATTRIBUTE_UNUSED)
{
    int r;
    char *dname;
    struct qemud_client_stream *stream;
    CHECK_CONN (client);

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

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

1873
    r = virDomainMigratePrepareTunnel(conn, stream->st,
C
Chris Lalancette 已提交
1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891
                                      args->flags, dname, args->resource,
                                      args->dom_xml);
    if (r == -1) {
        remoteFreeClientStream(client, stream);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

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

    return 0;
}

1892
static int
1893
remoteDispatchListDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1894 1895
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1896
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1897
                                  remote_error *rerr,
1898 1899 1900 1901 1902
                                  remote_list_defined_domains_args *args,
                                  remote_list_defined_domains_ret *ret)
{

    if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) {
1903 1904 1905
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX"));
        return -1;
1906 1907 1908
    }

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

    ret->names.names_len =
1915
        virConnectListDefinedDomains (conn,
1916
                                      ret->names.names_val, args->maxnames);
1917 1918
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
1919
        remoteDispatchConnError(rerr, conn);
1920 1921
        return -1;
    }
1922 1923 1924 1925 1926

    return 0;
}

static int
1927
remoteDispatchDomainLookupById (struct qemud_server *server ATTRIBUTE_UNUSED,
1928 1929
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
1930
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
1931
                                remote_error *rerr,
1932 1933 1934 1935 1936
                                remote_domain_lookup_by_id_args *args,
                                remote_domain_lookup_by_id_ret *ret)
{
    virDomainPtr dom;

1937
    dom = virDomainLookupByID (conn, args->id);
1938
    if (dom == NULL) {
1939
        remoteDispatchConnError(rerr, conn);
1940 1941
        return -1;
    }
1942 1943

    make_nonnull_domain (&ret->dom, dom);
1944
    virDomainFree(dom);
1945 1946 1947 1948
    return 0;
}

static int
1949
remoteDispatchDomainLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
1950 1951
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1952
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1953
                                  remote_error *rerr,
1954 1955 1956 1957 1958
                                  remote_domain_lookup_by_name_args *args,
                                  remote_domain_lookup_by_name_ret *ret)
{
    virDomainPtr dom;

1959
    dom = virDomainLookupByName (conn, args->name);
1960
    if (dom == NULL) {
1961
        remoteDispatchConnError(rerr, conn);
1962 1963
        return -1;
    }
1964 1965

    make_nonnull_domain (&ret->dom, dom);
1966
    virDomainFree(dom);
1967 1968 1969 1970
    return 0;
}

static int
1971
remoteDispatchDomainLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
1972 1973
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1974
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1975
                                  remote_error *rerr,
1976 1977 1978 1979 1980
                                  remote_domain_lookup_by_uuid_args *args,
                                  remote_domain_lookup_by_uuid_ret *ret)
{
    virDomainPtr dom;

1981
    dom = virDomainLookupByUUID (conn, (unsigned char *) args->uuid);
1982
    if (dom == NULL) {
1983
        remoteDispatchConnError(rerr, conn);
1984 1985
        return -1;
    }
1986 1987

    make_nonnull_domain (&ret->dom, dom);
1988
    virDomainFree(dom);
1989 1990 1991 1992
    return 0;
}

static int
1993
remoteDispatchNumOfDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1994 1995
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1996
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1997
                                   remote_error *rerr,
1998 1999 2000 2001
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_num_of_defined_domains_ret *ret)
{

2002
    ret->num = virConnectNumOfDefinedDomains (conn);
2003
    if (ret->num == -1) {
2004
        remoteDispatchConnError(rerr, conn);
2005 2006
        return -1;
    }
2007 2008 2009 2010 2011

    return 0;
}

static int
2012
remoteDispatchDomainPinVcpu (struct qemud_server *server ATTRIBUTE_UNUSED,
2013 2014
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2015
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2016
                             remote_error *rerr,
2017 2018 2019 2020 2021 2022
                             remote_domain_pin_vcpu_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int rv;

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

    if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) {
2030
        virDomainFree(dom);
2031 2032
        remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX"));
        return -1;
2033 2034 2035 2036 2037
    }

    rv = virDomainPinVcpu (dom, args->vcpu,
                           (unsigned char *) args->cpumap.cpumap_val,
                           args->cpumap.cpumap_len);
2038 2039
    if (rv == -1) {
        virDomainFree(dom);
2040
        remoteDispatchConnError(rerr, conn);
2041 2042 2043
        return -1;
    }
    virDomainFree(dom);
2044 2045 2046 2047
    return 0;
}

static int
2048
remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED,
2049 2050
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2051
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2052
                            remote_error *rerr,
2053 2054 2055 2056 2057
                            remote_domain_reboot_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2058
    dom = get_nonnull_domain (conn, args->dom);
2059
    if (dom == NULL) {
2060
        remoteDispatchConnError(rerr, conn);
2061
        return -1;
2062 2063
    }

2064 2065
    if (virDomainReboot (dom, args->flags) == -1) {
        virDomainFree(dom);
2066
        remoteDispatchConnError(rerr, conn);
2067
        return -1;
2068 2069
    }
    virDomainFree(dom);
2070 2071 2072 2073
    return 0;
}

static int
2074
remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED,
2075 2076
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2077
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2078
                             remote_error *rerr,
2079 2080 2081 2082
                             remote_domain_restore_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{

2083 2084
    if (virDomainRestore (conn, args->from) == -1) {
        remoteDispatchConnError(rerr, conn);
2085
        return -1;
2086
    }
2087 2088 2089 2090 2091

    return 0;
}

static int
2092
remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED,
2093 2094
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2095
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2096
                            remote_error *rerr,
2097 2098 2099 2100 2101
                            remote_domain_resume_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2102
    dom = get_nonnull_domain (conn, args->dom);
2103
    if (dom == NULL) {
2104
        remoteDispatchConnError(rerr, conn);
2105
        return -1;
2106 2107
    }

2108 2109
    if (virDomainResume (dom) == -1) {
        virDomainFree(dom);
2110
        remoteDispatchConnError(rerr, conn);
2111
        return -1;
2112 2113
    }
    virDomainFree(dom);
2114 2115 2116 2117
    return 0;
}

static int
2118
remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED,
2119 2120
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
2121
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
2122
                          remote_error *rerr,
2123 2124 2125 2126 2127
                          remote_domain_save_args *args,
                          void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2128
    dom = get_nonnull_domain (conn, args->dom);
2129
    if (dom == NULL) {
2130
        remoteDispatchConnError(rerr, conn);
2131
        return -1;
2132 2133
    }

2134 2135
    if (virDomainSave (dom, args->to) == -1) {
        virDomainFree(dom);
2136
        remoteDispatchConnError(rerr, conn);
2137
        return -1;
2138 2139
    }
    virDomainFree(dom);
2140 2141 2142 2143
    return 0;
}

static int
2144
remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED,
2145 2146
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2147
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2148
                              remote_error *rerr,
2149 2150 2151 2152 2153
                              remote_domain_core_dump_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2154
    dom = get_nonnull_domain (conn, args->dom);
2155
    if (dom == NULL) {
2156
        remoteDispatchConnError(rerr, conn);
2157
        return -1;
2158 2159
    }

2160 2161
    if (virDomainCoreDump (dom, args->to, args->flags) == -1) {
        virDomainFree(dom);
2162
        remoteDispatchConnError(rerr, conn);
2163
        return -1;
2164 2165
    }
    virDomainFree(dom);
2166 2167 2168 2169
    return 0;
}

static int
2170
remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2171 2172
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2173
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
2174
                                  remote_error *rerr,
2175 2176 2177 2178 2179
                                  remote_domain_set_autostart_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2180
    dom = get_nonnull_domain (conn, args->dom);
2181
    if (dom == NULL) {
2182
        remoteDispatchConnError(rerr, conn);
2183
        return -1;
2184 2185
    }

2186 2187
    if (virDomainSetAutostart (dom, args->autostart) == -1) {
        virDomainFree(dom);
2188
        remoteDispatchConnError(rerr, conn);
2189
        return -1;
2190 2191
    }
    virDomainFree(dom);
2192 2193 2194 2195
    return 0;
}

static int
2196
remoteDispatchDomainSetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
2197 2198
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2199
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
2200
                                  remote_error *rerr,
2201 2202 2203 2204 2205
                                  remote_domain_set_max_memory_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2206
    dom = get_nonnull_domain (conn, args->dom);
2207
    if (dom == NULL) {
2208
        remoteDispatchConnError(rerr, conn);
2209
        return -1;
2210 2211
    }

2212 2213
    if (virDomainSetMaxMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
2214
        remoteDispatchConnError(rerr, conn);
2215
        return -1;
2216 2217
    }
    virDomainFree(dom);
2218 2219 2220 2221
    return 0;
}

static int
2222
remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
2223 2224
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2225
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
2226
                               remote_error *rerr,
2227 2228 2229 2230 2231
                               remote_domain_set_memory_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2232
    dom = get_nonnull_domain (conn, args->dom);
2233
    if (dom == NULL) {
2234
        remoteDispatchConnError(rerr, conn);
2235
        return -1;
2236 2237
    }

2238 2239
    if (virDomainSetMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
2240
        remoteDispatchConnError(rerr, conn);
2241
        return -1;
2242 2243
    }
    virDomainFree(dom);
2244 2245 2246 2247
    return 0;
}

static int
2248
remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
2249 2250
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2251
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2252
                              remote_error *rerr,
2253 2254 2255 2256 2257
                              remote_domain_set_vcpus_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2258
    dom = get_nonnull_domain (conn, args->dom);
2259
    if (dom == NULL) {
2260
        remoteDispatchConnError(rerr, conn);
2261
        return -1;
2262 2263
    }

2264 2265
    if (virDomainSetVcpus (dom, args->nvcpus) == -1) {
        virDomainFree(dom);
2266
        remoteDispatchConnError(rerr, conn);
2267
        return -1;
2268 2269
    }
    virDomainFree(dom);
2270 2271 2272 2273
    return 0;
}

static int
2274
remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED,
2275 2276
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2277
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2278
                              remote_error *rerr,
2279 2280 2281 2282 2283
                              remote_domain_shutdown_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2284
    dom = get_nonnull_domain (conn, args->dom);
2285
    if (dom == NULL) {
2286
        remoteDispatchConnError(rerr, conn);
2287
        return -1;
2288 2289
    }

2290 2291
    if (virDomainShutdown (dom) == -1) {
        virDomainFree(dom);
2292
        remoteDispatchConnError(rerr, conn);
2293
        return -1;
2294 2295
    }
    virDomainFree(dom);
2296 2297 2298 2299
    return 0;
}

static int
2300
remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED,
2301 2302
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2303
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2304
                             remote_error *rerr,
2305 2306 2307 2308 2309
                             remote_domain_suspend_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2310
    dom = get_nonnull_domain (conn, args->dom);
2311
    if (dom == NULL) {
2312
        remoteDispatchConnError(rerr, conn);
2313
        return -1;
2314 2315
    }

2316 2317
    if (virDomainSuspend (dom) == -1) {
        virDomainFree(dom);
2318
        remoteDispatchConnError(rerr, conn);
2319
        return -1;
2320 2321
    }
    virDomainFree(dom);
2322 2323 2324 2325
    return 0;
}

static int
2326
remoteDispatchDomainUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2327 2328
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2329
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2330
                              remote_error *rerr,
2331 2332 2333 2334 2335
                              remote_domain_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2336
    dom = get_nonnull_domain (conn, args->dom);
2337
    if (dom == NULL) {
2338
        remoteDispatchConnError(rerr, conn);
2339
        return -1;
2340 2341
    }

2342 2343
    if (virDomainUndefine (dom) == -1) {
        virDomainFree(dom);
2344
        remoteDispatchConnError(rerr, conn);
2345
        return -1;
2346 2347
    }
    virDomainFree(dom);
2348 2349 2350 2351
    return 0;
}

static int
2352
remoteDispatchListDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2353 2354
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2355
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2356
                                   remote_error *rerr,
2357 2358 2359 2360 2361
                                   remote_list_defined_networks_args *args,
                                   remote_list_defined_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2362 2363 2364
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2365 2366 2367
    }

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

    ret->names.names_len =
2374
        virConnectListDefinedNetworks (conn,
2375
                                       ret->names.names_val, args->maxnames);
2376 2377
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
2378
        remoteDispatchConnError(rerr, conn);
2379 2380
        return -1;
    }
2381 2382 2383 2384 2385

    return 0;
}

static int
2386
remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2387 2388
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
2389
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
2390
                           remote_error *rerr,
2391 2392 2393 2394 2395
                           remote_list_domains_args *args,
                           remote_list_domains_ret *ret)
{

    if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
2396 2397 2398
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX"));
        return -1;
2399 2400 2401
    }

    /* Allocate return buffer. */
2402
    if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) {
2403 2404
        remoteDispatchOOMError(rerr);
        return -1;
2405
    }
2406

2407
    ret->ids.ids_len = virConnectListDomains (conn,
2408
                                              ret->ids.ids_val, args->maxids);
2409 2410
    if (ret->ids.ids_len == -1) {
        VIR_FREE(ret->ids.ids_val);
2411
        remoteDispatchConnError(rerr, conn);
2412 2413
        return -1;
    }
2414 2415 2416 2417 2418

    return 0;
}

static int
2419
remoteDispatchListNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2420 2421
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2422
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2423
                            remote_error *rerr,
2424 2425 2426 2427 2428
                            remote_list_networks_args *args,
                            remote_list_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2429 2430 2431
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2432 2433 2434
    }

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

    ret->names.names_len =
2441
        virConnectListNetworks (conn,
2442
                                ret->names.names_val, args->maxnames);
2443 2444
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
2445
        remoteDispatchConnError(rerr, conn);
2446 2447
        return -1;
    }
2448 2449 2450 2451 2452

    return 0;
}

static int
2453
remoteDispatchNetworkCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
2454 2455
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2456
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2457
                             remote_error *rerr,
2458 2459 2460 2461 2462
                             remote_network_create_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2463
    net = get_nonnull_network (conn, args->net);
2464
    if (net == NULL) {
2465
        remoteDispatchConnError(rerr, conn);
2466
        return -1;
2467 2468
    }

2469 2470
    if (virNetworkCreate (net) == -1) {
        virNetworkFree(net);
2471
        remoteDispatchConnError(rerr, conn);
2472
        return -1;
2473 2474
    }
    virNetworkFree(net);
2475 2476 2477 2478
    return 0;
}

static int
2479
remoteDispatchNetworkCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2480 2481
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2482
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
2483
                                remote_error *rerr,
2484 2485 2486 2487 2488
                                remote_network_create_xml_args *args,
                                remote_network_create_xml_ret *ret)
{
    virNetworkPtr net;

2489
    net = virNetworkCreateXML (conn, args->xml);
2490
    if (net == NULL) {
2491
        remoteDispatchConnError(rerr, conn);
2492 2493
        return -1;
    }
2494 2495

    make_nonnull_network (&ret->net, net);
2496
    virNetworkFree(net);
2497 2498 2499 2500
    return 0;
}

static int
2501
remoteDispatchNetworkDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2502 2503
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2504
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
2505
                                remote_error *rerr,
2506 2507 2508 2509 2510
                                remote_network_define_xml_args *args,
                                remote_network_define_xml_ret *ret)
{
    virNetworkPtr net;

2511
    net = virNetworkDefineXML (conn, args->xml);
2512
    if (net == NULL) {
2513
        remoteDispatchConnError(rerr, conn);
2514 2515
        return -1;
    }
2516 2517

    make_nonnull_network (&ret->net, net);
2518
    virNetworkFree(net);
2519 2520 2521 2522
    return 0;
}

static int
2523
remoteDispatchNetworkDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
2524 2525
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2526
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2527
                              remote_error *rerr,
2528 2529 2530 2531 2532
                              remote_network_destroy_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2533
    net = get_nonnull_network (conn, args->net);
2534
    if (net == NULL) {
2535
        remoteDispatchConnError(rerr, conn);
2536
        return -1;
2537 2538
    }

2539 2540
    if (virNetworkDestroy (net) == -1) {
        virNetworkFree(net);
2541
        remoteDispatchConnError(rerr, conn);
2542
        return -1;
2543 2544
    }
    virNetworkFree(net);
2545 2546 2547 2548
    return 0;
}

static int
2549
remoteDispatchNetworkDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2550 2551
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2552
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2553
                              remote_error *rerr,
2554 2555 2556 2557 2558
                              remote_network_dump_xml_args *args,
                              remote_network_dump_xml_ret *ret)
{
    virNetworkPtr net;

2559
    net = get_nonnull_network (conn, args->net);
2560
    if (net == NULL) {
2561
        remoteDispatchConnError(rerr, conn);
2562
        return -1;
2563 2564 2565 2566
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNetworkGetXMLDesc (net, args->flags);
2567 2568
    if (!ret->xml) {
        virNetworkFree(net);
2569
        remoteDispatchConnError(rerr, conn);
2570 2571 2572
        return -1;
    }
    virNetworkFree(net);
2573 2574 2575 2576
    return 0;
}

static int
2577
remoteDispatchNetworkGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2578 2579
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2580
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2581
                                   remote_error *rerr,
2582 2583 2584 2585 2586
                                   remote_network_get_autostart_args *args,
                                   remote_network_get_autostart_ret *ret)
{
    virNetworkPtr net;

2587
    net = get_nonnull_network (conn, args->net);
2588
    if (net == NULL) {
2589
        remoteDispatchConnError(rerr, conn);
2590
        return -1;
2591 2592
    }

2593 2594
    if (virNetworkGetAutostart (net, &ret->autostart) == -1) {
        virNetworkFree(net);
2595
        remoteDispatchConnError(rerr, conn);
2596
        return -1;
2597 2598
    }
    virNetworkFree(net);
2599 2600 2601 2602
    return 0;
}

static int
2603
remoteDispatchNetworkGetBridgeName (struct qemud_server *server ATTRIBUTE_UNUSED,
2604 2605
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2606
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
2607
                                    remote_error *rerr,
2608 2609 2610 2611 2612
                                    remote_network_get_bridge_name_args *args,
                                    remote_network_get_bridge_name_ret *ret)
{
    virNetworkPtr net;

2613
    net = get_nonnull_network (conn, args->net);
2614
    if (net == NULL) {
2615
        remoteDispatchConnError(rerr, conn);
2616
        return -1;
2617 2618 2619 2620
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virNetworkGetBridgeName (net);
2621 2622
    if (!ret->name) {
        virNetworkFree(net);
2623
        remoteDispatchConnError(rerr, conn);
2624 2625 2626
        return -1;
    }
    virNetworkFree(net);
2627 2628 2629 2630
    return 0;
}

static int
2631
remoteDispatchNetworkLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
2632 2633
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2634
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2635
                                   remote_error *rerr,
2636 2637 2638 2639 2640
                                   remote_network_lookup_by_name_args *args,
                                   remote_network_lookup_by_name_ret *ret)
{
    virNetworkPtr net;

2641
    net = virNetworkLookupByName (conn, args->name);
2642
    if (net == NULL) {
2643
        remoteDispatchConnError(rerr, conn);
2644 2645
        return -1;
    }
2646 2647

    make_nonnull_network (&ret->net, net);
2648
    virNetworkFree(net);
2649 2650 2651 2652
    return 0;
}

static int
2653
remoteDispatchNetworkLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
2654 2655
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2656
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2657
                                   remote_error *rerr,
2658 2659 2660 2661 2662
                                   remote_network_lookup_by_uuid_args *args,
                                   remote_network_lookup_by_uuid_ret *ret)
{
    virNetworkPtr net;

2663
    net = virNetworkLookupByUUID (conn, (unsigned char *) args->uuid);
2664
    if (net == NULL) {
2665
        remoteDispatchConnError(rerr, conn);
2666 2667
        return -1;
    }
2668 2669

    make_nonnull_network (&ret->net, net);
2670
    virNetworkFree(net);
2671 2672 2673 2674
    return 0;
}

static int
2675
remoteDispatchNetworkSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2676 2677
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2678
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2679
                                   remote_error *rerr,
2680 2681 2682 2683 2684
                                   remote_network_set_autostart_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2685
    net = get_nonnull_network (conn, args->net);
2686
    if (net == NULL) {
2687
        remoteDispatchConnError(rerr, conn);
2688
        return -1;
2689 2690
    }

2691 2692
    if (virNetworkSetAutostart (net, args->autostart) == -1) {
        virNetworkFree(net);
2693
        remoteDispatchConnError(rerr, conn);
2694
        return -1;
2695 2696
    }
    virNetworkFree(net);
2697 2698 2699 2700
    return 0;
}

static int
2701
remoteDispatchNetworkUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2702 2703
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2704
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
2705
                               remote_error *rerr,
2706 2707 2708 2709 2710
                               remote_network_undefine_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2711
    net = get_nonnull_network (conn, args->net);
2712
    if (net == NULL) {
2713
        remoteDispatchConnError(rerr, conn);
2714
        return -1;
2715 2716
    }

2717 2718
    if (virNetworkUndefine (net) == -1) {
        virNetworkFree(net);
2719
        remoteDispatchConnError(rerr, conn);
2720
        return -1;
2721 2722
    }
    virNetworkFree(net);
2723 2724 2725 2726
    return 0;
}

static int
2727
remoteDispatchNumOfDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2728 2729
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2730
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
2731
                                    remote_error *rerr,
2732 2733 2734 2735
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_num_of_defined_networks_ret *ret)
{

2736
    ret->num = virConnectNumOfDefinedNetworks (conn);
2737
    if (ret->num == -1) {
2738
        remoteDispatchConnError(rerr, conn);
2739 2740
        return -1;
    }
2741 2742 2743 2744 2745

    return 0;
}

static int
2746
remoteDispatchNumOfDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2747 2748
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2749
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2750
                            remote_error *rerr,
2751 2752 2753 2754
                            void *args ATTRIBUTE_UNUSED,
                            remote_num_of_domains_ret *ret)
{

2755
    ret->num = virConnectNumOfDomains (conn);
2756
    if (ret->num == -1) {
2757
        remoteDispatchConnError(rerr, conn);
2758 2759
        return -1;
    }
2760 2761 2762 2763 2764

    return 0;
}

static int
2765
remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2766 2767
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2768
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2769
                             remote_error *rerr,
2770 2771 2772 2773
                             void *args ATTRIBUTE_UNUSED,
                             remote_num_of_networks_ret *ret)
{

2774
    ret->num = virConnectNumOfNetworks (conn);
2775
    if (ret->num == -1) {
2776
        remoteDispatchConnError(rerr, conn);
2777 2778
        return -1;
    }
2779 2780 2781 2782

    return 0;
}

2783

D
Daniel Veillard 已提交
2784 2785 2786 2787 2788
/*-------------------------------------------------------------*/
static int
remoteDispatchNumOfInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2789
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807
                               remote_error *rerr,
                               void *args ATTRIBUTE_UNUSED,
                               remote_num_of_interfaces_ret *ret)
{

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

    return 0;
}

static int
remoteDispatchListInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2808
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837
                              remote_error *rerr,
                              remote_list_interfaces_args *args,
                              remote_list_interfaces_ret *ret)
{

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

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

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

    return 0;
}

2838 2839 2840 2841
static int
remoteDispatchNumOfDefinedInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
2842
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860
                                      remote_error *rerr,
                                      void *args ATTRIBUTE_UNUSED,
                                      remote_num_of_defined_interfaces_ret *ret)
{

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

    return 0;
}

static int
remoteDispatchListDefinedInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
2861
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890
                                     remote_error *rerr,
                                     remote_list_defined_interfaces_args *args,
                                     remote_list_defined_interfaces_ret *ret)
{

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

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

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

    return 0;
}

D
Daniel Veillard 已提交
2891 2892 2893 2894
static int
remoteDispatchInterfaceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
2895
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2896 2897 2898 2899
                                     remote_error *rerr,
                                     remote_interface_lookup_by_name_args *args,
                                     remote_interface_lookup_by_name_ret *ret)
{
2900
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2901

2902 2903
    iface = virInterfaceLookupByName (conn, args->name);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2904 2905 2906 2907
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2908 2909
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2910 2911 2912 2913 2914 2915 2916
    return 0;
}

static int
remoteDispatchInterfaceLookupByMacString (struct qemud_server *server ATTRIBUTE_UNUSED,
                                          struct qemud_client *client ATTRIBUTE_UNUSED,
                                          virConnectPtr conn,
2917
                                          remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2918 2919 2920 2921
                                          remote_error *rerr,
                                          remote_interface_lookup_by_mac_string_args *args,
                                          remote_interface_lookup_by_mac_string_ret *ret)
{
2922
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2923

2924 2925
    iface = virInterfaceLookupByMACString (conn, args->mac);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2926 2927 2928 2929
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2930 2931
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2932 2933 2934 2935 2936 2937 2938
    return 0;
}

static int
remoteDispatchInterfaceGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2939
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2940 2941 2942 2943
                                   remote_error *rerr,
                                   remote_interface_get_xml_desc_args *args,
                                   remote_interface_get_xml_desc_ret *ret)
{
2944
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2945

2946 2947
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2948 2949 2950 2951 2952
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* remoteDispatchClientRequest will free this. */
2953
    ret->xml = virInterfaceGetXMLDesc (iface, args->flags);
D
Daniel Veillard 已提交
2954
    if (!ret->xml) {
2955
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
2956 2957 2958
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
2959
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2960 2961 2962 2963 2964 2965 2966
    return 0;
}

static int
remoteDispatchInterfaceDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2967
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2968 2969 2970 2971
                                  remote_error *rerr,
                                  remote_interface_define_xml_args *args,
                                  remote_interface_define_xml_ret *ret)
{
2972
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2973

2974 2975
    iface = virInterfaceDefineXML (conn, args->xml, args->flags);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2976 2977 2978 2979
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2980 2981
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2982 2983 2984 2985 2986
    return 0;
}

static int
remoteDispatchInterfaceUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2987 2988 2989 2990 2991 2992
                                 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 已提交
2993
{
2994
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2995

2996 2997
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2998 2999 3000 3001
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3002 3003
    if (virInterfaceUndefine (iface) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3004 3005 3006
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
3007
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3008 3009 3010 3011 3012
    return 0;
}

static int
remoteDispatchInterfaceCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
3013 3014 3015 3016 3017 3018
                               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 已提交
3019
{
3020
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3021

3022 3023
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3024 3025 3026 3027
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3028 3029
    if (virInterfaceCreate (iface, args->flags) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3030 3031 3032
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
3033
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3034 3035 3036 3037 3038
    return 0;
}

static int
remoteDispatchInterfaceDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
3039 3040 3041 3042 3043 3044
                                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 已提交
3045
{
3046
    virInterfacePtr iface;
D
Daniel Veillard 已提交
3047

3048 3049
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
3050 3051 3052 3053
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

3054 3055
    if (virInterfaceDestroy (iface, args->flags) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
3056 3057 3058
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
3059
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
3060 3061 3062 3063 3064
    return 0;
}

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

3065
static int
3066
remoteDispatchAuthList (struct qemud_server *server,
3067
                        struct qemud_client *client,
3068
                        virConnectPtr conn ATTRIBUTE_UNUSED,
3069
                        remote_message_header *hdr ATTRIBUTE_UNUSED,
3070
                        remote_error *rerr,
3071 3072 3073 3074
                        void *args ATTRIBUTE_UNUSED,
                        remote_auth_list_ret *ret)
{
    ret->types.types_len = 1;
3075
    if (VIR_ALLOC_N(ret->types.types_val, ret->types.types_len) < 0) {
3076 3077
        remoteDispatchOOMError(rerr);
        return -1;
3078
    }
3079 3080 3081
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3082
    ret->types.types_val[0] = client->auth;
3083
    virMutexUnlock(&client->lock);
3084

3085 3086 3087 3088 3089 3090 3091 3092
    return 0;
}


#if HAVE_SASL
/*
 * NB, keep in sync with similar method in src/remote_internal.c
 */
3093
static char *addrToString(remote_error *rerr,
3094 3095 3096 3097 3098 3099 3100 3101 3102
                          struct sockaddr_storage *sa, socklen_t salen) {
    char host[1024], port[20];
    char *addr;
    int err;

    if ((err = getnameinfo((struct sockaddr *)sa, salen,
                           host, sizeof(host),
                           port, sizeof(port),
                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
3103 3104 3105
        remoteDispatchFormatError(rerr,
                                  _("Cannot resolve address %d: %s"),
                                  err, gai_strerror(err));
3106 3107 3108
        return NULL;
    }

3109
    if (virAsprintf(&addr, "%s;%s", host, port) == -1) {
3110
        virReportOOMError();
3111 3112 3113 3114 3115 3116 3117 3118 3119
        return NULL;
    }

    return addr;
}


/*
 * Initializes the SASL session in prepare for authentication
3120
 * and gives the client a list of allowed mechanisms to choose
3121 3122 3123 3124
 *
 * XXX callbacks for stuff like password verification ?
 */
static int
3125
remoteDispatchAuthSaslInit (struct qemud_server *server,
3126
                            struct qemud_client *client,
3127
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3128
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3129
                            remote_error *rerr,
3130 3131 3132 3133
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret)
{
    const char *mechlist = NULL;
3134
    sasl_security_properties_t secprops;
3135 3136 3137 3138 3139
    int err;
    struct sockaddr_storage sa;
    socklen_t salen;
    char *localAddr, *remoteAddr;

3140 3141 3142
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3143

3144 3145 3146
    REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn != NULL) {
3147
        VIR_ERROR0(_("client tried invalid SASL init request"));
3148
        goto authfail;
3149 3150 3151 3152 3153
    }

    /* Get local address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getsockname(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
3154
        char ebuf[1024];
3155
        remoteDispatchFormatError(rerr,
3156
                                  _("failed to get sock address: %s"),
3157
                                  virStrerror(errno, ebuf, sizeof ebuf));
3158
        goto error;
3159
    }
3160
    if ((localAddr = addrToString(rerr, &sa, salen)) == NULL) {
3161
        goto error;
3162 3163 3164 3165 3166
    }

    /* Get remote address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getpeername(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
3167
        char ebuf[1024];
3168
        remoteDispatchFormatError(rerr, _("failed to get peer address: %s"),
3169
                                  virStrerror(errno, ebuf, sizeof ebuf));
3170
        VIR_FREE(localAddr);
3171
        goto error;
3172
    }
3173
    if ((remoteAddr = addrToString(rerr, &sa, salen)) == NULL) {
3174
        VIR_FREE(localAddr);
3175
        goto error;
3176 3177 3178 3179 3180 3181 3182 3183 3184 3185
    }

    err = sasl_server_new("libvirt",
                          NULL, /* FQDN - just delegates to gethostname */
                          NULL, /* User realm */
                          localAddr,
                          remoteAddr,
                          NULL, /* XXX Callbacks */
                          SASL_SUCCESS_DATA,
                          &client->saslconn);
3186 3187
    VIR_FREE(localAddr);
    VIR_FREE(remoteAddr);
3188
    if (err != SASL_OK) {
3189 3190
        VIR_ERROR(_("sasl context setup failed %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3191
        client->saslconn = NULL;
3192
        goto authfail;
3193 3194
    }

3195 3196 3197 3198 3199 3200 3201
    /* 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 已提交
3202
            VIR_ERROR0(_("cannot get TLS cipher size"));
3203 3204
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
3205
            goto authfail;
3206 3207 3208 3209 3210
        }
        ssf *= 8; /* tls key size is bytes, sasl wants bits */

        err = sasl_setprop(client->saslconn, SASL_SSF_EXTERNAL, &ssf);
        if (err != SASL_OK) {
3211 3212
            VIR_ERROR(_("cannot set SASL external SSF %d (%s)"),
                      err, sasl_errstring(err, NULL, NULL));
3213 3214
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
3215
            goto authfail;
3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238
        }
    }

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

    err = sasl_setprop(client->saslconn, SASL_SEC_PROPS, &secprops);
    if (err != SASL_OK) {
3239 3240
        VIR_ERROR(_("cannot set SASL security props %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3241 3242
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3243
        goto authfail;
3244 3245
    }

3246 3247 3248 3249 3250 3251 3252 3253 3254
    err = sasl_listmech(client->saslconn,
                        NULL, /* Don't need to set user */
                        "", /* Prefix */
                        ",", /* Separator */
                        "", /* Suffix */
                        &mechlist,
                        NULL,
                        NULL);
    if (err != SASL_OK) {
3255 3256
        VIR_ERROR(_("cannot list SASL mechanisms %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3257 3258
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3259
        goto authfail;
3260 3261 3262 3263
    }
    REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist);
    ret->mechlist = strdup(mechlist);
    if (!ret->mechlist) {
3264
        VIR_ERROR0(_("cannot allocate mechlist"));
3265 3266
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3267
        goto authfail;
3268 3269
    }

3270
    virMutexUnlock(&client->lock);
3271
    return 0;
3272 3273 3274 3275

authfail:
    remoteDispatchAuthError(rerr);
error:
3276
    virMutexUnlock(&client->lock);
3277
    return -1;
3278 3279 3280
}


3281
/* We asked for an SSF layer, so sanity check that we actually
3282 3283 3284
 * got what we asked for */
static int
remoteSASLCheckSSF (struct qemud_client *client,
3285
                    remote_error *rerr) {
3286 3287 3288 3289 3290 3291 3292 3293 3294
    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) {
3295 3296
        VIR_ERROR(_("cannot query SASL ssf on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3297
        remoteDispatchAuthError(rerr);
3298 3299 3300 3301 3302 3303 3304
        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 */
3305
        VIR_ERROR(_("negotiated SSF %d was not strong enough"), ssf);
3306
        remoteDispatchAuthError(rerr);
3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }

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

3324 3325 3326
static int
remoteSASLCheckAccess (struct qemud_server *server,
                       struct qemud_client *client,
3327
                       remote_error *rerr) {
3328 3329 3330 3331 3332 3333
    const void *val;
    int err;
    char **wildcards;

    err = sasl_getprop(client->saslconn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
3334 3335
        VIR_ERROR(_("cannot query SASL username on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
3336
        remoteDispatchAuthError(rerr);
3337 3338 3339 3340 3341
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    if (val == NULL) {
3342
        VIR_ERROR0(_("no client username was found"));
3343
        remoteDispatchAuthError(rerr);
3344 3345 3346 3347 3348 3349 3350 3351
        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) {
3352
        VIR_ERROR0(_("out of memory copying username"));
3353
        remoteDispatchAuthError(rerr);
3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }

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

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

    /* Denied */
3371
    VIR_ERROR(_("SASL client %s not allowed in whitelist"), client->saslUsername);
3372
    remoteDispatchAuthError(rerr);
3373 3374 3375 3376 3377 3378
    sasl_dispose(&client->saslconn);
    client->saslconn = NULL;
    return -1;
}


3379 3380 3381 3382
/*
 * This starts the SASL authentication negotiation.
 */
static int
3383 3384
remoteDispatchAuthSaslStart (struct qemud_server *server,
                             struct qemud_client *client,
3385
                             virConnectPtr conn ATTRIBUTE_UNUSED,
3386
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
3387
                             remote_error *rerr,
3388 3389 3390 3391 3392 3393 3394
                             remote_auth_sasl_start_args *args,
                             remote_auth_sasl_start_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

3395 3396 3397
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3398

3399 3400 3401
    REMOTE_DEBUG("Start SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
3402
        VIR_ERROR0(_("client tried invalid SASL start request"));
3403
        goto authfail;
3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416
    }

    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) {
3417 3418
        VIR_ERROR(_("sasl start failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3419 3420
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3421
        goto authfail;
3422 3423
    }
    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
3424
        VIR_ERROR(_("sasl start reply data too long %d"), serveroutlen);
3425 3426
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3427
        goto authfail;
3428 3429 3430 3431
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
3432
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
3433
            remoteDispatchOOMError(rerr);
3434
            goto error;
3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446
        }
        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 {
3447
        if (remoteSASLCheckSSF(client, rerr) < 0)
3448
            goto error;
3449

3450
        /* Check username whitelist ACL */
3451
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
3452
            goto error;
3453

3454 3455 3456 3457 3458
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

3459
    virMutexUnlock(&client->lock);
3460
    return 0;
3461 3462 3463 3464

authfail:
    remoteDispatchAuthError(rerr);
error:
3465
    virMutexUnlock(&client->lock);
3466
    return -1;
3467 3468 3469 3470
}


static int
3471 3472
remoteDispatchAuthSaslStep (struct qemud_server *server,
                            struct qemud_client *client,
3473
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3474
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3475
                            remote_error *rerr,
3476 3477 3478 3479 3480 3481 3482
                            remote_auth_sasl_step_args *args,
                            remote_auth_sasl_step_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

3483 3484 3485
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3486

3487 3488 3489
    REMOTE_DEBUG("Step SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
3490
        VIR_ERROR0(_("client tried invalid SASL start request"));
3491
        goto authfail;
3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503
    }

    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) {
3504 3505
        VIR_ERROR(_("sasl step failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3506 3507
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3508
        goto authfail;
3509 3510 3511
    }

    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
3512 3513
        VIR_ERROR(_("sasl step reply data too long %d"),
                  serveroutlen);
3514 3515
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3516
        goto authfail;
3517 3518 3519 3520
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
3521
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
3522
            remoteDispatchOOMError(rerr);
3523
            goto error;
3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535
        }
        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 {
3536
        if (remoteSASLCheckSSF(client, rerr) < 0)
3537
            goto error;
3538

3539
        /* Check username whitelist ACL */
3540
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
3541
            goto error;
3542

3543 3544 3545 3546 3547
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

3548
    virMutexUnlock(&client->lock);
3549
    return 0;
3550 3551 3552 3553

authfail:
    remoteDispatchAuthError(rerr);
error:
3554
    virMutexUnlock(&client->lock);
3555
    return -1;
3556 3557 3558 3559 3560
}


#else /* HAVE_SASL */
static int
3561
remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED,
3562 3563
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3564
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3565
                            remote_error *rerr,
3566 3567 3568
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED)
{
3569
    VIR_ERROR0(_("client tried unsupported SASL init request"));
3570
    remoteDispatchAuthError(rerr);
3571 3572 3573 3574
    return -1;
}

static int
3575
remoteDispatchAuthSaslStart (struct qemud_server *server ATTRIBUTE_UNUSED,
3576 3577
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn ATTRIBUTE_UNUSED,
3578
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
3579
                             remote_error *rerr,
3580 3581 3582
                             remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED,
                             remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED)
{
3583
    VIR_ERROR0(_("client tried unsupported SASL start request"));
3584
    remoteDispatchAuthError(rerr);
3585 3586 3587 3588
    return -1;
}

static int
3589
remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
3590 3591
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3592
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3593
                            remote_error *rerr,
3594 3595 3596
                            remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED)
{
3597
    VIR_ERROR0(_("client tried unsupported SASL step request"));
3598
    remoteDispatchAuthError(rerr);
3599 3600 3601 3602 3603
    return -1;
}
#endif /* HAVE_SASL */


3604 3605 3606 3607 3608
#if HAVE_POLKIT1
static int
remoteDispatchAuthPolkit (struct qemud_server *server,
                          struct qemud_client *client,
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3609
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
    pid_t callerPid;
    uid_t callerUid;
    const char *action;
    int status = -1;
    char pidbuf[50];
    int rv;

    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);
3653
        goto authfail;
3654 3655
    }

3656
    if (virRun(pkcheck, &status) < 0) {
3657
        VIR_ERROR(_("Cannot invoke %s"), PKCHECK_PATH);
3658
        goto authfail;
3659 3660
    }
    if (status != 0) {
3661
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %d"),
3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678
                  action, callerPid, callerUid, status);
        goto authfail;
    }
    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:
    remoteDispatchAuthError(rerr);
    virMutexUnlock(&client->lock);
    return -1;
}
#elif HAVE_POLKIT0
3679
static int
3680
remoteDispatchAuthPolkit (struct qemud_server *server,
3681
                          struct qemud_client *client,
3682
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3683
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3684
                          remote_error *rerr,
3685 3686 3687 3688 3689
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
    pid_t callerPid;
    uid_t callerUid;
3690 3691 3692 3693 3694 3695
    PolKitCaller *pkcaller = NULL;
    PolKitAction *pkaction = NULL;
    PolKitContext *pkcontext = NULL;
    PolKitError *pkerr = NULL;
    PolKitResult pkresult;
    DBusError err;
3696 3697
    const char *action;

3698 3699 3700
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3701 3702

    action = client->readonly ?
3703 3704
        "org.libvirt.unix.monitor" :
        "org.libvirt.unix.manage";
3705 3706 3707

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

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

3717
    VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
3718 3719 3720
    dbus_error_init(&err);
    if (!(pkcaller = polkit_caller_new_from_pid(server->sysbus,
                                                callerPid, &err))) {
3721
        VIR_ERROR(_("Failed to lookup policy kit caller: %s"), err.message);
3722
        dbus_error_free(&err);
3723
        goto authfail;
3724
    }
3725

3726
    if (!(pkaction = polkit_action_new())) {
3727
        char ebuf[1024];
3728
        VIR_ERROR(_("Failed to create polkit action %s"),
3729
                  virStrerror(errno, ebuf, sizeof ebuf));
3730
        polkit_caller_unref(pkcaller);
3731
        goto authfail;
3732 3733 3734 3735 3736
    }
    polkit_action_set_action_id(pkaction, action);

    if (!(pkcontext = polkit_context_new()) ||
        !polkit_context_init(pkcontext, &pkerr)) {
3737
        char ebuf[1024];
3738
        VIR_ERROR(_("Failed to create polkit context %s"),
3739
                  (pkerr ? polkit_error_get_error_message(pkerr)
3740
                   : virStrerror(errno, ebuf, sizeof ebuf)));
3741 3742 3743 3744 3745
        if (pkerr)
            polkit_error_free(pkerr);
        polkit_caller_unref(pkcaller);
        polkit_action_unref(pkaction);
        dbus_error_free(&err);
3746
        goto authfail;
3747
    }
3748

3749
# if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
3750 3751 3752 3753 3754 3755
    pkresult = polkit_context_is_caller_authorized(pkcontext,
                                                   pkaction,
                                                   pkcaller,
                                                   0,
                                                   &pkerr);
    if (pkerr && polkit_error_is_set(pkerr)) {
3756 3757 3758
        VIR_ERROR(_("Policy kit failed to check authorization %d %s"),
                  polkit_error_get_error_code(pkerr),
                  polkit_error_get_error_message(pkerr));
3759
        goto authfail;
3760
    }
3761
# else
3762 3763 3764
    pkresult = polkit_context_can_caller_do_action(pkcontext,
                                                   pkaction,
                                                   pkcaller);
3765
# endif
3766 3767 3768 3769
    polkit_context_unref(pkcontext);
    polkit_caller_unref(pkcaller);
    polkit_action_unref(pkaction);
    if (pkresult != POLKIT_RESULT_YES) {
3770
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %s"),
3771 3772
                  action, callerPid, callerUid,
                  polkit_result_to_string_representation(pkresult));
3773
        goto authfail;
3774
    }
3775
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d, result %s"),
3776 3777 3778 3779
             action, callerPid, callerUid,
             polkit_result_to_string_representation(pkresult));
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;
3780

3781
    virMutexUnlock(&client->lock);
3782
    return 0;
3783 3784 3785

authfail:
    remoteDispatchAuthError(rerr);
3786
    virMutexUnlock(&client->lock);
3787
    return -1;
3788 3789
}

3790
#else /* !HAVE_POLKIT0 & !HAVE_POLKIT1*/
3791 3792

static int
3793
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
3794
                          struct qemud_client *client ATTRIBUTE_UNUSED,
3795
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3796
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3797 3798 3799
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED)
3800
{
3801
    VIR_ERROR0(_("client tried unsupported PolicyKit init request"));
3802
    remoteDispatchAuthError(rerr);
3803 3804
    return -1;
}
3805
#endif /* HAVE_POLKIT1 */
3806

3807 3808 3809 3810 3811 3812 3813 3814

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


static int
remoteDispatchListDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3815 3816
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3817
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
3818
                                       remote_error *rerr,
3819 3820 3821 3822 3823
                                       remote_list_defined_storage_pools_args *args,
                                       remote_list_defined_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
3824 3825
        remoteDispatchFormatError (rerr, "%s",
                            _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
3826
        return -1;
3827 3828 3829
    }

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

    ret->names.names_len =
3836
        virConnectListDefinedStoragePools (conn,
3837 3838 3839
                                           ret->names.names_val, args->maxnames);
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3840
        remoteDispatchConnError(rerr, conn);
3841 3842
        return -1;
    }
3843 3844 3845 3846 3847 3848

    return 0;
}

static int
remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3849 3850
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3851
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
3852
                                remote_error *rerr,
3853 3854 3855 3856 3857
                                remote_list_storage_pools_args *args,
                                remote_list_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
3858 3859 3860
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX"));
        return -1;
3861 3862 3863
    }

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

    ret->names.names_len =
3870
        virConnectListStoragePools (conn,
3871
                                ret->names.names_val, args->maxnames);
3872 3873
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3874
        remoteDispatchConnError(rerr, conn);
3875 3876
        return -1;
    }
3877 3878 3879 3880

    return 0;
}

3881 3882
static int
remoteDispatchFindStoragePoolSources (struct qemud_server *server ATTRIBUTE_UNUSED,
3883 3884
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3885
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
3886
                                      remote_error *rerr,
3887 3888 3889 3890
                                      remote_find_storage_pool_sources_args *args,
                                      remote_find_storage_pool_sources_ret *ret)
{
    ret->xml =
3891
        virConnectFindStoragePoolSources (conn,
3892 3893 3894
                                          args->type,
                                          args->srcSpec ? *args->srcSpec : NULL,
                                          args->flags);
3895
    if (ret->xml == NULL) {
3896
        remoteDispatchConnError(rerr, conn);
3897
        return -1;
3898
    }
3899 3900 3901 3902 3903

    return 0;
}


3904 3905
static int
remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
3906 3907
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3908
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
3909
                                 remote_error *rerr,
3910 3911 3912 3913 3914
                                 remote_storage_pool_create_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3915
    pool = get_nonnull_storage_pool (conn, args->pool);
3916
    if (pool == NULL) {
3917
        remoteDispatchConnError(rerr, conn);
3918
        return -1;
3919 3920 3921 3922
    }

    if (virStoragePoolCreate (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3923
        remoteDispatchConnError(rerr, conn);
3924 3925 3926 3927 3928 3929 3930 3931
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3932 3933
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3934
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
3935
                                    remote_error *rerr,
3936 3937 3938 3939 3940
                                    remote_storage_pool_create_xml_args *args,
                                    remote_storage_pool_create_xml_ret *ret)
{
    virStoragePoolPtr pool;

3941
    pool = virStoragePoolCreateXML (conn, args->xml, args->flags);
3942
    if (pool == NULL) {
3943
        remoteDispatchConnError(rerr, conn);
3944 3945
        return -1;
    }
3946 3947 3948 3949 3950 3951 3952 3953

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

static int
remoteDispatchStoragePoolDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3954 3955
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3956
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
3957
                                    remote_error *rerr,
3958 3959 3960 3961 3962
                                    remote_storage_pool_define_xml_args *args,
                                    remote_storage_pool_define_xml_ret *ret)
{
    virStoragePoolPtr pool;

3963
    pool = virStoragePoolDefineXML (conn, args->xml, args->flags);
3964
    if (pool == NULL) {
3965
        remoteDispatchConnError(rerr, conn);
3966 3967
        return -1;
    }
3968 3969 3970 3971 3972 3973 3974 3975

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

static int
remoteDispatchStoragePoolBuild (struct qemud_server *server ATTRIBUTE_UNUSED,
3976 3977
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3978
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
3979 3980 3981
                                remote_error *rerr,
                                remote_storage_pool_build_args *args,
                                void *ret ATTRIBUTE_UNUSED)
3982 3983 3984
{
    virStoragePoolPtr pool;

3985
    pool = get_nonnull_storage_pool (conn, args->pool);
3986
    if (pool == NULL) {
3987
        remoteDispatchConnError(rerr, conn);
3988
        return -1;
3989 3990 3991 3992
    }

    if (virStoragePoolBuild (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3993
        remoteDispatchConnError(rerr, conn);
3994 3995 3996 3997 3998 3999 4000 4001 4002
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
4003 4004
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4005
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4006
                                  remote_error *rerr,
4007 4008 4009 4010 4011
                                  remote_storage_pool_destroy_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4012
    pool = get_nonnull_storage_pool (conn, args->pool);
4013
    if (pool == NULL) {
4014
        remoteDispatchConnError(rerr, conn);
4015
        return -1;
4016 4017 4018 4019
    }

    if (virStoragePoolDestroy (pool) == -1) {
        virStoragePoolFree(pool);
4020
        remoteDispatchConnError(rerr, conn);
4021 4022 4023 4024 4025 4026 4027 4028
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
4029 4030
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4031
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4032
                                 remote_error *rerr,
4033 4034 4035 4036 4037
                                 remote_storage_pool_delete_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4038
    pool = get_nonnull_storage_pool (conn, args->pool);
4039
    if (pool == NULL) {
4040
        remoteDispatchConnError(rerr, conn);
4041
        return -1;
4042 4043 4044 4045
    }

    if (virStoragePoolDelete (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
4046
        remoteDispatchConnError(rerr, conn);
4047 4048 4049 4050 4051 4052 4053 4054
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolRefresh (struct qemud_server *server ATTRIBUTE_UNUSED,
4055 4056
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4057
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4058
                                  remote_error *rerr,
4059 4060 4061 4062 4063
                                  remote_storage_pool_refresh_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4064
    pool = get_nonnull_storage_pool (conn, args->pool);
4065
    if (pool == NULL) {
4066
        remoteDispatchConnError(rerr, conn);
4067
        return -1;
4068 4069 4070 4071
    }

    if (virStoragePoolRefresh (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
4072
        remoteDispatchConnError(rerr, conn);
4073 4074 4075 4076 4077 4078 4079 4080
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
4081 4082
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4083
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4084
                                  remote_error *rerr,
4085 4086 4087 4088 4089 4090
                                  remote_storage_pool_get_info_args *args,
                                  remote_storage_pool_get_info_ret *ret)
{
    virStoragePoolPtr pool;
    virStoragePoolInfo info;

4091
    pool = get_nonnull_storage_pool (conn, args->pool);
4092
    if (pool == NULL) {
4093
        remoteDispatchConnError(rerr, conn);
4094
        return -1;
4095 4096 4097 4098
    }

    if (virStoragePoolGetInfo (pool, &info) == -1) {
        virStoragePoolFree(pool);
4099
        remoteDispatchConnError(rerr, conn);
4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114
        return -1;
    }

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

    virStoragePoolFree(pool);

    return 0;
}

static int
remoteDispatchStoragePoolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4115 4116
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4117
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4118
                                  remote_error *rerr,
4119 4120 4121 4122 4123
                                  remote_storage_pool_dump_xml_args *args,
                                  remote_storage_pool_dump_xml_ret *ret)
{
    virStoragePoolPtr pool;

4124
    pool = get_nonnull_storage_pool (conn, args->pool);
4125
    if (pool == NULL) {
4126
        remoteDispatchConnError(rerr, conn);
4127
        return -1;
4128 4129 4130 4131 4132 4133
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStoragePoolGetXMLDesc (pool, args->flags);
    if (!ret->xml) {
        virStoragePoolFree(pool);
4134
        remoteDispatchConnError(rerr, conn);
4135 4136 4137 4138 4139 4140 4141 4142
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
4143 4144
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4145
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4146
                                       remote_error *rerr,
4147 4148 4149 4150 4151
                                       remote_storage_pool_get_autostart_args *args,
                                       remote_storage_pool_get_autostart_ret *ret)
{
    virStoragePoolPtr pool;

4152
    pool = get_nonnull_storage_pool (conn, args->pool);
4153
    if (pool == NULL) {
4154
        remoteDispatchConnError(rerr, conn);
4155
        return -1;
4156 4157 4158 4159
    }

    if (virStoragePoolGetAutostart (pool, &ret->autostart) == -1) {
        virStoragePoolFree(pool);
4160
        remoteDispatchConnError(rerr, conn);
4161 4162 4163 4164 4165 4166 4167 4168 4169
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4170 4171
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4172
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4173
                                       remote_error *rerr,
4174 4175 4176 4177 4178
                                       remote_storage_pool_lookup_by_name_args *args,
                                       remote_storage_pool_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;

4179
    pool = virStoragePoolLookupByName (conn, args->name);
4180
    if (pool == NULL) {
4181
        remoteDispatchConnError(rerr, conn);
4182 4183
        return -1;
    }
4184 4185 4186 4187 4188 4189 4190 4191

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

static int
remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
4192 4193
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4194
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4195
                                       remote_error *rerr,
4196 4197 4198 4199 4200
                                       remote_storage_pool_lookup_by_uuid_args *args,
                                       remote_storage_pool_lookup_by_uuid_ret *ret)
{
    virStoragePoolPtr pool;

4201
    pool = virStoragePoolLookupByUUID (conn, (unsigned char *) args->uuid);
4202
    if (pool == NULL) {
4203
        remoteDispatchConnError(rerr, conn);
4204 4205
        return -1;
    }
4206 4207 4208 4209 4210 4211 4212 4213

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

static int
remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server ATTRIBUTE_UNUSED,
4214 4215
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
4216
                                         remote_message_header *hdr ATTRIBUTE_UNUSED,
4217
                                         remote_error *rerr,
4218 4219 4220 4221 4222 4223
                                         remote_storage_pool_lookup_by_volume_args *args,
                                         remote_storage_pool_lookup_by_volume_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4224
    vol = get_nonnull_storage_vol (conn, args->vol);
4225
    if (vol == NULL) {
4226
        remoteDispatchConnError(rerr, conn);
4227 4228
        return -1;
    }
4229 4230 4231

    pool = virStoragePoolLookupByVolume (vol);
    virStorageVolFree(vol);
4232
    if (pool == NULL) {
4233
        remoteDispatchConnError(rerr, conn);
4234 4235
        return -1;
    }
4236 4237 4238 4239 4240 4241 4242 4243

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

static int
remoteDispatchStoragePoolSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
4244 4245
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4246
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4247
                                       remote_error *rerr,
4248 4249 4250 4251 4252
                                       remote_storage_pool_set_autostart_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4253
    pool = get_nonnull_storage_pool (conn, args->pool);
4254
    if (pool == NULL) {
4255
        remoteDispatchConnError(rerr, conn);
4256
        return -1;
4257 4258 4259 4260
    }

    if (virStoragePoolSetAutostart (pool, args->autostart) == -1) {
        virStoragePoolFree(pool);
4261
        remoteDispatchConnError(rerr, conn);
4262 4263 4264 4265 4266 4267 4268 4269
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
4270 4271
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4272
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4273
                                   remote_error *rerr,
4274 4275 4276 4277 4278
                                   remote_storage_pool_undefine_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

4279
    pool = get_nonnull_storage_pool (conn, args->pool);
4280
    if (pool == NULL) {
4281
        remoteDispatchConnError(rerr, conn);
4282
        return -1;
4283 4284 4285 4286
    }

    if (virStoragePoolUndefine (pool) == -1) {
        virStoragePoolFree(pool);
4287
        remoteDispatchConnError(rerr, conn);
4288 4289 4290 4291 4292 4293 4294 4295
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchNumOfStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
4296 4297
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4298
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4299
                                 remote_error *rerr,
4300 4301 4302 4303
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_num_of_storage_pools_ret *ret)
{

4304
    ret->num = virConnectNumOfStoragePools (conn);
4305
    if (ret->num == -1) {
4306
        remoteDispatchConnError(rerr, conn);
4307 4308
        return -1;
    }
4309 4310 4311 4312 4313 4314

    return 0;
}

static int
remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
4315 4316
                                        struct qemud_client *client ATTRIBUTE_UNUSED,
                                        virConnectPtr conn,
4317
                                        remote_message_header *hdr ATTRIBUTE_UNUSED,
4318
                                        remote_error *rerr,
4319 4320 4321 4322
                                        void *args ATTRIBUTE_UNUSED,
                                        remote_num_of_defined_storage_pools_ret *ret)
{

4323
    ret->num = virConnectNumOfDefinedStoragePools (conn);
4324
    if (ret->num == -1) {
4325
        remoteDispatchConnError(rerr, conn);
4326 4327
        return -1;
    }
4328 4329 4330 4331 4332 4333

    return 0;
}

static int
remoteDispatchStoragePoolListVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
4334 4335
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4336
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4337
                                      remote_error *rerr,
4338 4339 4340 4341 4342 4343
                                      remote_storage_pool_list_volumes_args *args,
                                      remote_storage_pool_list_volumes_ret *ret)
{
    virStoragePoolPtr pool;

    if (args->maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) {
4344 4345 4346
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX"));
        return -1;
4347 4348
    }

4349
    pool = get_nonnull_storage_pool (conn, args->pool);
4350
    if (pool == NULL) {
4351
        remoteDispatchConnError(rerr, conn);
4352
        return -1;
4353 4354 4355
    }

    /* Allocate return buffer. */
4356 4357
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        virStoragePoolFree(pool);
4358 4359
        remoteDispatchOOMError(rerr);
        return -1;
4360
    }
4361 4362 4363 4364 4365

    ret->names.names_len =
        virStoragePoolListVolumes (pool,
                                   ret->names.names_val, args->maxnames);
    virStoragePoolFree(pool);
4366 4367
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
4368
        remoteDispatchConnError(rerr, conn);
4369 4370
        return -1;
    }
4371 4372 4373 4374 4375 4376 4377

    return 0;
}


static int
remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
4378 4379
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4380
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4381
                                       remote_error *rerr,
4382 4383 4384 4385 4386
                                       remote_storage_pool_num_of_volumes_args *args,
                                       remote_storage_pool_num_of_volumes_ret *ret)
{
    virStoragePoolPtr pool;

4387
    pool = get_nonnull_storage_pool (conn, args->pool);
4388
    if (pool == NULL) {
4389
        remoteDispatchConnError(rerr, conn);
4390
        return -1;
4391 4392 4393 4394
    }

    ret->num = virStoragePoolNumOfVolumes (pool);
    virStoragePoolFree(pool);
4395
    if (ret->num == -1) {
4396
        remoteDispatchConnError(rerr, conn);
4397 4398
        return -1;
    }
4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411

    return 0;
}


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



static int
remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4412 4413
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4414
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4415
                                   remote_error *rerr,
4416 4417 4418 4419 4420 4421
                                   remote_storage_vol_create_xml_args *args,
                                   remote_storage_vol_create_xml_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4422
    pool = get_nonnull_storage_pool (conn, args->pool);
4423
    if (pool == NULL) {
4424
        remoteDispatchConnError(rerr, conn);
4425
        return -1;
4426 4427 4428 4429
    }

    vol = virStorageVolCreateXML (pool, args->xml, args->flags);
    virStoragePoolFree(pool);
4430
    if (vol == NULL) {
4431
        remoteDispatchConnError(rerr, conn);
4432 4433
        return -1;
    }
4434 4435 4436 4437 4438 4439

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

4440 4441 4442 4443
static int
remoteDispatchStorageVolCreateXmlFrom (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4444
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459
                                       remote_error *rerr,
                                       remote_storage_vol_create_xml_from_args *args,
                                       remote_storage_vol_create_xml_from_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr clonevol, newvol;

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

    clonevol = get_nonnull_storage_vol (conn, args->clonevol);
    if (clonevol == NULL) {
4460
        virStoragePoolFree(pool);
4461 4462 4463 4464 4465 4466
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    newvol = virStorageVolCreateXMLFrom (pool, args->xml, clonevol,
                                         args->flags);
4467 4468
    virStorageVolFree(clonevol);
    virStoragePoolFree(pool);
4469 4470 4471 4472 4473 4474 4475 4476 4477
    if (newvol == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_storage_vol (&ret->vol, newvol);
    virStorageVolFree(newvol);
    return 0;
}
4478 4479 4480

static int
remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
4481 4482
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4483
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4484
                                remote_error *rerr,
4485 4486 4487 4488 4489
                                remote_storage_vol_delete_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virStorageVolPtr vol;

4490
    vol = get_nonnull_storage_vol (conn, args->vol);
4491
    if (vol == NULL) {
4492
        remoteDispatchConnError(rerr, conn);
4493
        return -1;
4494 4495 4496 4497
    }

    if (virStorageVolDelete (vol, args->flags) == -1) {
        virStorageVolFree(vol);
4498
        remoteDispatchConnError(rerr, conn);
4499 4500 4501 4502 4503 4504
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}

4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536
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;
}

4537 4538
static int
remoteDispatchStorageVolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
4539 4540
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4541
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4542
                                 remote_error *rerr,
4543 4544 4545 4546 4547 4548
                                 remote_storage_vol_get_info_args *args,
                                 remote_storage_vol_get_info_ret *ret)
{
    virStorageVolPtr vol;
    virStorageVolInfo info;

4549
    vol = get_nonnull_storage_vol (conn, args->vol);
4550
    if (vol == NULL) {
4551
        remoteDispatchConnError(rerr, conn);
4552
        return -1;
4553 4554 4555 4556
    }

    if (virStorageVolGetInfo (vol, &info) == -1) {
        virStorageVolFree(vol);
4557
        remoteDispatchConnError(rerr, conn);
4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
        return -1;
    }

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

    virStorageVolFree(vol);

    return 0;
}

static int
remoteDispatchStorageVolDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4572 4573
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4574
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4575
                                 remote_error *rerr,
4576 4577 4578 4579 4580
                                 remote_storage_vol_dump_xml_args *args,
                                 remote_storage_vol_dump_xml_ret *ret)
{
    virStorageVolPtr vol;

4581
    vol = get_nonnull_storage_vol (conn, args->vol);
4582
    if (vol == NULL) {
4583
        remoteDispatchConnError(rerr, conn);
4584
        return -1;
4585 4586 4587 4588 4589 4590
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStorageVolGetXMLDesc (vol, args->flags);
    if (!ret->xml) {
        virStorageVolFree(vol);
4591
        remoteDispatchConnError(rerr, conn);
4592 4593 4594 4595 4596 4597 4598 4599 4600
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolGetPath (struct qemud_server *server ATTRIBUTE_UNUSED,
4601 4602
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4603
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4604
                                 remote_error *rerr,
4605 4606 4607 4608 4609
                                 remote_storage_vol_get_path_args *args,
                                 remote_storage_vol_get_path_ret *ret)
{
    virStorageVolPtr vol;

4610
    vol = get_nonnull_storage_vol (conn, args->vol);
4611
    if (vol == NULL) {
4612
        remoteDispatchConnError(rerr, conn);
4613
        return -1;
4614 4615 4616 4617 4618 4619
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virStorageVolGetPath (vol);
    if (!ret->name) {
        virStorageVolFree(vol);
4620
        remoteDispatchConnError(rerr, conn);
4621 4622 4623 4624 4625 4626 4627 4628 4629
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4630 4631
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4632
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4633
                                      remote_error *rerr,
4634 4635 4636 4637 4638 4639
                                      remote_storage_vol_lookup_by_name_args *args,
                                      remote_storage_vol_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4640
    pool = get_nonnull_storage_pool (conn, args->pool);
4641
    if (pool == NULL) {
4642
        remoteDispatchConnError(rerr, conn);
4643
        return -1;
4644 4645 4646 4647
    }

    vol = virStorageVolLookupByName (pool, args->name);
    virStoragePoolFree(pool);
4648
    if (vol == NULL) {
4649
        remoteDispatchConnError(rerr, conn);
4650 4651
        return -1;
    }
4652 4653 4654 4655 4656 4657 4658 4659

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

static int
remoteDispatchStorageVolLookupByKey (struct qemud_server *server ATTRIBUTE_UNUSED,
4660 4661
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
4662
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
4663
                                     remote_error *rerr,
4664 4665 4666 4667 4668
                                     remote_storage_vol_lookup_by_key_args *args,
                                     remote_storage_vol_lookup_by_key_ret *ret)
{
    virStorageVolPtr vol;

4669
    vol = virStorageVolLookupByKey (conn, args->key);
4670
    if (vol == NULL) {
4671
        remoteDispatchConnError(rerr, conn);
4672 4673
        return -1;
    }
4674 4675 4676 4677 4678 4679 4680 4681 4682

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


static int
remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUSED,
4683 4684
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4685
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4686
                                      remote_error *rerr,
4687 4688 4689 4690 4691
                                      remote_storage_vol_lookup_by_path_args *args,
                                      remote_storage_vol_lookup_by_path_ret *ret)
{
    virStorageVolPtr vol;

4692
    vol = virStorageVolLookupByPath (conn, args->path);
4693
    if (vol == NULL) {
4694
        remoteDispatchConnError(rerr, conn);
4695 4696
        return -1;
    }
4697 4698 4699 4700 4701 4702 4703

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


4704 4705 4706 4707 4708 4709
/***************************************************************
 *     NODE INFO APIS
 **************************************************************/

static int
remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
4710 4711
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4712
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4713
                                remote_error *rerr,
4714 4715 4716 4717 4718
                                remote_node_num_of_devices_args *args,
                                remote_node_num_of_devices_ret *ret)
{
    CHECK_CONN(client);

4719
    ret->num = virNodeNumOfDevices (conn,
4720 4721
                                    args->cap ? *args->cap : NULL,
                                    args->flags);
4722
    if (ret->num == -1) {
4723
        remoteDispatchConnError(rerr, conn);
4724 4725
        return -1;
    }
4726 4727 4728 4729 4730 4731 4732

    return 0;
}


static int
remoteDispatchNodeListDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
4733 4734
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
4735
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
4736
                               remote_error *rerr,
4737 4738 4739 4740 4741 4742
                               remote_node_list_devices_args *args,
                               remote_node_list_devices_ret *ret)
{
    CHECK_CONN(client);

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
4743 4744 4745
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
4746 4747 4748 4749
    }

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

    ret->names.names_len =
4755
        virNodeListDevices (conn,
4756 4757 4758
                            args->cap ? *args->cap : NULL,
                            ret->names.names_val, args->maxnames, args->flags);
    if (ret->names.names_len == -1) {
4759
        remoteDispatchConnError(rerr, conn);
4760 4761 4762 4763 4764 4765 4766 4767 4768 4769
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4770 4771
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4772
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4773
                                      remote_error *rerr,
4774 4775 4776 4777 4778 4779 4780
                                      remote_node_device_lookup_by_name_args *args,
                                      remote_node_device_lookup_by_name_ret *ret)
{
    virNodeDevicePtr dev;

    CHECK_CONN(client);

4781
    dev = virNodeDeviceLookupByName (conn, args->name);
4782
    if (dev == NULL) {
4783
        remoteDispatchConnError(rerr, conn);
4784 4785
        return -1;
    }
4786 4787 4788 4789 4790 4791 4792 4793 4794

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


static int
remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4795 4796
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4797
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4798
                                 remote_error *rerr,
4799 4800 4801 4802 4803 4804
                                 remote_node_device_dump_xml_args *args,
                                 remote_node_device_dump_xml_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4805
    dev = virNodeDeviceLookupByName(conn, args->name);
4806
    if (dev == NULL) {
4807
        remoteDispatchConnError(rerr, conn);
4808
        return -1;
4809 4810 4811 4812 4813
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags);
    if (!ret->xml) {
4814
        remoteDispatchConnError(rerr, conn);
4815 4816 4817 4818 4819 4820 4821 4822 4823 4824
        virNodeDeviceFree(dev);
        return -1;
    }
    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED,
4825 4826
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4827
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4828
                                   remote_error *rerr,
4829 4830 4831 4832 4833 4834 4835
                                   remote_node_device_get_parent_args *args,
                                   remote_node_device_get_parent_ret *ret)
{
    virNodeDevicePtr dev;
    const char *parent;
    CHECK_CONN(client);

4836
    dev = virNodeDeviceLookupByName(conn, args->name);
4837
    if (dev == NULL) {
4838
        remoteDispatchConnError(rerr, conn);
4839
        return -1;
4840 4841 4842 4843 4844 4845 4846 4847 4848 4849
    }

    parent = virNodeDeviceGetParent(dev);

    if (parent == NULL) {
        ret->parent = NULL;
    } else {
        /* remoteDispatchClientRequest will free this. */
        char **parent_p;
        if (VIR_ALLOC(parent_p) < 0) {
4850 4851
            remoteDispatchOOMError(rerr);
            return -1;
4852 4853 4854
        }
        *parent_p = strdup(parent);
        if (*parent_p == NULL) {
4855 4856
            remoteDispatchOOMError(rerr);
            return -1;
4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867
        }
        ret->parent = parent_p;
    }

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4868 4869
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4870
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4871
                                   remote_error *rerr,
4872 4873 4874 4875 4876 4877
                                   remote_node_device_num_of_caps_args *args,
                                   remote_node_device_num_of_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4878
    dev = virNodeDeviceLookupByName(conn, args->name);
4879
    if (dev == NULL) {
4880
        remoteDispatchConnError(rerr, conn);
4881
        return -1;
4882 4883 4884
    }

    ret->num = virNodeDeviceNumOfCaps(dev);
4885
    if (ret->num < 0) {
4886
        remoteDispatchConnError(rerr, conn);
4887 4888
        return -1;
    }
4889 4890 4891 4892 4893 4894 4895 4896

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4897 4898
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4899
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4900
                                  remote_error *rerr,
4901 4902 4903 4904 4905 4906
                                  remote_node_device_list_caps_args *args,
                                  remote_node_device_list_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4907
    dev = virNodeDeviceLookupByName(conn, args->name);
4908
    if (dev == NULL) {
4909
        remoteDispatchConnError(rerr, conn);
4910
        return -1;
4911 4912 4913
    }

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
4914 4915 4916
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
4917 4918 4919 4920
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
4921 4922
        remoteDispatchOOMError(rerr);
        return -1;
4923 4924 4925 4926 4927 4928
    }

    ret->names.names_len =
        virNodeDeviceListCaps (dev, ret->names.names_val,
                               args->maxnames);
    if (ret->names.names_len == -1) {
4929
        remoteDispatchConnError(rerr, conn);
4930 4931 4932 4933 4934 4935 4936 4937
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


4938 4939 4940 4941
static int
remoteDispatchNodeDeviceDettach (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4942
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4943 4944 4945 4946 4947 4948 4949 4950 4951
                                 remote_error *rerr,
                                 remote_node_device_dettach_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
4952
        remoteDispatchConnError(rerr, conn);
4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968
        return -1;
    }

    if (virNodeDeviceDettach(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNodeDeviceReAttach (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4969
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4970 4971 4972 4973 4974 4975 4976 4977 4978
                                  remote_error *rerr,
                                  remote_node_device_re_attach_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
4979
        remoteDispatchConnError(rerr, conn);
4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995
        return -1;
    }

    if (virNodeDeviceReAttach(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNodeDeviceReset (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
4996
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
4997 4998 4999 5000 5001 5002 5003 5004 5005
                               remote_error *rerr,
                               remote_node_device_reset_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5006
        remoteDispatchConnError(rerr, conn);
5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018
        return -1;
    }

    if (virNodeDeviceReset(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


5019 5020 5021 5022
static int
remoteDispatchNodeDeviceCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
5023
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046
                                  remote_error *rerr,
                                  remote_node_device_create_xml_args *args,
                                  remote_node_device_create_xml_ret *ret)
{
    virNodeDevicePtr dev;

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

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

    return 0;
}


static int
remoteDispatchNodeDeviceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
5047
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
5048 5049 5050 5051 5052 5053 5054 5055
                                remote_error *rerr,
                                remote_node_device_destroy_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
5056
        remoteDispatchConnError(rerr, conn);
5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068
        return -1;
    }

    if (virNodeDeviceDestroy(dev) == -1) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    return 0;
}


5069 5070 5071 5072 5073 5074

/***************************
 * Register / deregister events
 ***************************/
static int
remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED,
5075 5076
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
5077
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
5078
                                    remote_error *rerr ATTRIBUTE_UNUSED,
5079 5080 5081 5082
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_domain_events_register_ret *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);
5083 5084 5085 5086 5087 5088
    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;
    }
5089

5090 5091 5092 5093 5094
    if ((callbackID = virConnectDomainEventRegisterAny(conn,
                                                       NULL,
                                                       VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                                       VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
                                                       client, NULL)) < 0) {
5095 5096 5097
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
5098

5099
    client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = callbackID;
5100

5101 5102 5103 5104 5105
    return 0;
}

static int
remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED,
5106 5107
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
5108
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
5109
                                      remote_error *rerr ATTRIBUTE_UNUSED,
5110 5111 5112 5113 5114
                                      void *args ATTRIBUTE_UNUSED,
                                      remote_domain_events_deregister_ret *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);

5115 5116
    if (client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] == -1) {
        remoteDispatchFormatError(rerr, _("domain event %d not registered"), VIR_DOMAIN_EVENT_ID_LIFECYCLE);
5117 5118
        return -1;
    }
5119

5120 5121 5122 5123 5124
    if (virConnectDomainEventDeregisterAny(conn,
                                           client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE]) < 0) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
5125

5126
    client->domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LIFECYCLE] = -1;
5127 5128 5129 5130 5131
    return 0;
}

static void
remoteDispatchDomainEventSend (struct qemud_client *client,
5132 5133 5134
                               int procnr,
                               xdrproc_t proc,
                               void *data)
5135
{
5136
    struct qemud_client_message *msg = NULL;
5137
    XDR xdr;
5138
    unsigned int len;
5139

5140
    if (VIR_ALLOC(msg) < 0)
5141 5142
        return;

5143 5144
    msg->hdr.prog = REMOTE_PROGRAM;
    msg->hdr.vers = REMOTE_PROTOCOL_VERSION;
5145
    msg->hdr.proc = procnr;
5146
    msg->hdr.type = REMOTE_MESSAGE;
5147 5148
    msg->hdr.serial = 1;
    msg->hdr.status = REMOTE_OK;
5149

5150 5151
    if (remoteEncodeClientMessageHeader(msg) < 0)
        goto error;
5152

5153 5154
    /* Serialise the return header and event. */
    xdrmem_create (&xdr,
5155 5156
                   msg->buffer,
                   msg->bufferLength,
5157
                   XDR_ENCODE);
5158

5159 5160
    /* Skip over the header we just wrote */
    if (xdr_setpos (&xdr, msg->bufferOffset) == 0)
5161
        goto xdr_error;
5162

5163 5164
    if (!(proc)(&xdr, data)) {
        VIR_WARN("Failed to serialize domain event %d", procnr);
5165
        goto xdr_error;
5166
    }
5167

5168 5169
    /* Update length word to include payload*/
    len = msg->bufferOffset = xdr_getpos (&xdr);
5170 5171
    if (xdr_setpos (&xdr, 0) == 0)
        goto xdr_error;
5172

5173 5174
    if (!xdr_u_int (&xdr, &len))
        goto xdr_error;
5175 5176

    /* Send it. */
5177 5178 5179 5180
    msg->async = 1;
    msg->bufferLength = len;
    msg->bufferOffset = 0;
    qemudClientMessageQueuePush(&client->tx, msg);
5181
    qemudUpdateClientEvent(client);
5182 5183 5184 5185 5186 5187 5188 5189

    xdr_destroy (&xdr);
    return;

xdr_error:
    xdr_destroy(&xdr);
error:
    VIR_FREE(msg);
5190
}
5191

5192 5193 5194
static int
remoteDispatchNumOfSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
                            struct qemud_client *client ATTRIBUTE_UNUSED,
5195 5196 5197
                            virConnectPtr conn,
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                            remote_error *err,
5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212
                            void *args ATTRIBUTE_UNUSED,
                            remote_num_of_secrets_ret *ret)
{
    ret->num = virConnectNumOfSecrets (conn);
    if (ret->num == -1) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

    return 0;
}

static int
remoteDispatchListSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
                           struct qemud_client *client ATTRIBUTE_UNUSED,
5213 5214 5215
                           virConnectPtr conn,
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                           remote_error *err,
5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243
                           remote_list_secrets_args *args,
                           remote_list_secrets_ret *ret)
{
    if (args->maxuuids > REMOTE_SECRET_UUID_LIST_MAX) {
        remoteDispatchFormatError (err, "%s",
                                   _("maxuuids > REMOTE_SECRET_UUID_LIST_MAX"));
        return -1;
    }

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

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

    return 0;
}

static int
remoteDispatchSecretDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
5244 5245 5246
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *err,
5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265
                               remote_secret_define_xml_args *args,
                               remote_secret_define_xml_ret *ret)
{
    virSecretPtr secret;

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

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

static int
remoteDispatchSecretGetValue (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
5266 5267 5268
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
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 5296 5297
                              remote_secret_get_value_args *args,
                              remote_secret_get_value_ret *ret)
{
    virSecretPtr secret;
    size_t value_size;
    unsigned char *value;

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

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

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

static int
remoteDispatchSecretGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
5298 5299 5300
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *err,
5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321
                                remote_secret_get_xml_desc_args *args,
                                remote_secret_get_xml_desc_ret *ret)
{
    virSecretPtr secret;

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

static int
5322 5323
remoteDispatchSecretLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
5324 5325 5326
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *err,
5327 5328
                                  remote_secret_lookup_by_uuid_args *args,
                                  remote_secret_lookup_by_uuid_ret *ret)
5329 5330 5331
{
    virSecretPtr secret;

5332
    secret = virSecretLookupByUUID (conn, (unsigned char *)args->uuid);
5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

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

static int
remoteDispatchSecretSetValue (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
5346 5347 5348
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372
                              remote_secret_set_value_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virSecretPtr secret;

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

    virSecretFree(secret);
    return 0;
}

static int
remoteDispatchSecretUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
5373 5374 5375
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395
                              remote_secret_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virSecretPtr secret;

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

    virSecretFree(secret);
    return 0;
}

5396 5397 5398
static int
remoteDispatchSecretLookupByUsage (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
5399 5400 5401
                                   virConnectPtr conn,
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
                                   remote_error *err,
5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417
                                   remote_secret_lookup_by_usage_args *args,
                                   remote_secret_lookup_by_usage_ret *ret)
{
    virSecretPtr secret;

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

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

5418

5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620
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);
        return -1;
    }

    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);
        return -1;
    }

    return 0;
}

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

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

    ret->active = virInterfaceIsActive(iface);

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

    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);
        return -1;
    }

    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);
        return -1;
    }

    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);
        return -1;
    }

    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);
        return -1;
    }

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


5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642
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;
}


5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663
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;
5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707

    return 0;
}


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

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

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

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

    virDomainFree(dom);

5708 5709 5710 5711
    return 0;
}


5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740
static int
remoteDispatchDomainAbortJob (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *rerr,
                              remote_domain_abort_job_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

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

    virDomainFree(dom);

    return 0;
}


5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769
static int
remoteDispatchDomainMigrateSetMaxDowntime(struct qemud_server *server ATTRIBUTE_UNUSED,
                                          struct qemud_client *client ATTRIBUTE_UNUSED,
                                          virConnectPtr conn,
                                          remote_message_header *hdr ATTRIBUTE_UNUSED,
                                          remote_error *rerr,
                                          remote_domain_migrate_set_max_downtime_args *args,
                                          void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

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

    virDomainFree(dom);

    return 0;
}


5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841
static int
remoteDispatchDomainEventsRegisterAny (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
                                       remote_error *rerr ATTRIBUTE_UNUSED,
                                       remote_domain_events_register_any_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);
    int callbackID;

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

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

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

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

    return 0;
}


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

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

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

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

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


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 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 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 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020

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

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

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

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

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

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


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

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

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


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

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

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

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

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

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

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

    return 0;
}


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

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

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


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

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

    return 0;
}


6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046
/*----- Helpers. -----*/

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

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

D
Daniel Veillard 已提交
6047
static virInterfacePtr
6048
get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface)
D
Daniel Veillard 已提交
6049
{
6050
    return virGetInterface (conn, iface.name, iface.mac);
D
Daniel Veillard 已提交
6051 6052
}

6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066
static virStoragePoolPtr
get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool)
{
    return virGetStoragePool (conn, pool.name, BAD_CAST pool.uuid);
}

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

6067 6068 6069
static virSecretPtr
get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret)
{
6070
    return virGetSecret (conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
6071 6072
}

6073 6074 6075 6076 6077 6078
static virNWFilterPtr
get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter)
{
    return virGetNWFilter (conn, nwfilter.name, BAD_CAST nwfilter.uuid);
}

6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094
/* Make remote_nonnull_domain and remote_nonnull_network. */
static void
make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
{
    dom_dst->id = dom_src->id;
    dom_dst->name = strdup (dom_src->name);
    memcpy (dom_dst->uuid, dom_src->uuid, VIR_UUID_BUFLEN);
}

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

D
Daniel Veillard 已提交
6095 6096 6097 6098 6099 6100 6101 6102
static void
make_nonnull_interface (remote_nonnull_interface *interface_dst,
                        virInterfacePtr interface_src)
{
    interface_dst->name = strdup (interface_src->name);
    interface_dst->mac = strdup (interface_src->mac);
}

6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116
static void
make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
{
    pool_dst->name = strdup (pool_src->name);
    memcpy (pool_dst->uuid, pool_src->uuid, VIR_UUID_BUFLEN);
}

static void
make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src)
{
    vol_dst->pool = strdup (vol_src->pool);
    vol_dst->name = strdup (vol_src->name);
    vol_dst->key = strdup (vol_src->key);
}
6117 6118 6119 6120 6121 6122

static void
make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src)
{
    dev_dst->name = strdup(dev_src->name);
}
6123 6124 6125 6126

static void
make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
{
6127
    memcpy (secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
6128 6129
    secret_dst->usageType = secret_src->usageType;
    secret_dst->usageID = strdup (secret_src->usageID);
6130
}
6131 6132 6133 6134 6135 6136 6137

static void
make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src)
{
    nwfilter_dst->name = strdup (nwfilter_src->name);
    memcpy (nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
}