remote.c 135.8 KB
Newer Older
1 2 3
/*
 * remote.c: code handling remote requests (from remote_internal.c)
 *
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

45 46 47 48 49
#ifdef HAVE_POLKIT
#include <polkit/polkit.h>
#include <polkit-dbus/polkit-dbus.h>
#endif

50 51
#include "libvirt_internal.h"
#include "datatypes.h"
52
#include "qemud.h"
53
#include "memory.h"
54

55
#define REMOTE_DEBUG(fmt, ...) DEBUG(fmt, __VA_ARGS__)
56

57 58 59
static void remoteDispatchFormatError (remote_error *rerr,
                                       const char *fmt, ...)
    ATTRIBUTE_FORMAT(printf, 2, 3);
60 61
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
62 63
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);
64 65
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);
66 67
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);
68
static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src);
69 70 71

#include "remote_dispatch_prototypes.h"

72 73 74 75 76 77 78 79 80
typedef union {
#include "remote_dispatch_args.h"
} dispatch_args;

typedef union {
#include "remote_dispatch_ret.h"
} dispatch_ret;


81 82 83 84 85 86 87 88 89 90 91 92 93
/**
 * When the RPC handler is called:
 *
 *  - Server object is unlocked
 *  - Client object is unlocked
 *
 * Both must be locked before use. Server lock must
 * be held before attempting to lock client.
 *
 * Without any locking, it is safe to use:
 *
 *   'conn', 'rerr', 'args and 'ret'
 */
94 95
typedef int (*dispatch_fn) (struct qemud_server *server,
                            struct qemud_client *client,
96
                            virConnectPtr conn,
97
                            remote_error *err,
98 99 100 101 102 103 104 105 106 107 108 109
                            dispatch_args *args,
                            dispatch_ret *ret);

typedef struct {
    dispatch_fn fn;
    xdrproc_t args_filter;
    xdrproc_t ret_filter;
} dispatch_data;

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

111 112 113
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
114
                               struct qemud_client_message *msg,
115
                               virDomainPtr dom,
116 117
                               int event,
                               int detail);
118

119 120 121 122 123 124 125 126 127 128 129 130 131 132 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 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 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215

/* Convert a libvirt  virError object into wire format */
static void
remoteDispatchCopyError (remote_error *rerr,
                         virErrorPtr verr)
{
    rerr->code = verr->code;
    rerr->domain = verr->domain;
    rerr->message = verr->message ? malloc(sizeof(char*)) : NULL;
    if (rerr->message) *rerr->message = strdup(verr->message);
    rerr->level = verr->level;
    rerr->str1 = verr->str1 ? malloc(sizeof(char*)) : NULL;
    if (rerr->str1) *rerr->str1 = strdup(verr->str1);
    rerr->str2 = verr->str2 ? malloc(sizeof(char*)) : NULL;
    if (rerr->str2) *rerr->str2 = strdup(verr->str2);
    rerr->str3 = verr->str3 ? malloc(sizeof(char*)) : NULL;
    if (rerr->str3) *rerr->str3 = strdup(verr->str3);
    rerr->int1 = verr->int1;
    rerr->int2 = verr->int2;
}


/* A set of helpers for sending back errors to client
   in various ways .... */

static void
remoteDispatchStringError (remote_error *rerr,
                           int code, const char *msg)
{
    virError verr;

    memset(&verr, 0, sizeof verr);

    /* Construct the dummy libvirt virError. */
    verr.code = code;
    verr.domain = VIR_FROM_REMOTE;
    verr.message = (char *)msg;
    verr.level = VIR_ERR_ERROR;
    verr.str1 = (char *)msg;

    remoteDispatchCopyError(rerr, &verr);
}

static void
remoteDispatchAuthError (remote_error *rerr)
{
    remoteDispatchStringError (rerr, VIR_ERR_AUTH_FAILED, "authentication failed");
}

static void
remoteDispatchFormatError (remote_error *rerr,
                           const char *fmt, ...)
{
    va_list args;
    char msgbuf[1024];
    char *msg = msgbuf;

    va_start (args, fmt);
    vsnprintf (msgbuf, sizeof msgbuf, fmt, args);
    va_end (args);

    remoteDispatchStringError (rerr, VIR_ERR_RPC, msg);
}

static void
remoteDispatchGenericError (remote_error *rerr)
{
    remoteDispatchStringError(rerr,
                              VIR_ERR_INTERNAL_ERROR,
                              "library function returned error but did not set virterror");
}

static void
remoteDispatchOOMError (remote_error *rerr)
{
    remoteDispatchStringError(rerr,
                              VIR_ERR_NO_MEMORY,
                              NULL);
}

static void
remoteDispatchConnError (remote_error *rerr,
                         virConnectPtr conn)
{
    virErrorPtr verr;

    if (conn)
        verr = virConnGetLastError(conn);
    else
        verr = virGetLastError();
    if (verr)
        remoteDispatchCopyError(rerr, verr);
    else
        remoteDispatchGenericError(rerr);
}


216 217 218
/* This function gets called from qemud when it detects an incoming
 * remote protocol message.  At this point, client->buffer contains
 * the full call message (including length word which we skip).
219 220 221
 *
 * Server object is unlocked
 * Client object is locked
222
 */
223
int
224
remoteDispatchClientRequest (struct qemud_server *server,
225 226
                             struct qemud_client *client,
                             struct qemud_client_message *msg)
227 228 229
{
    XDR xdr;
    remote_message_header req, rep;
230
    remote_error rerr;
231 232 233
    dispatch_args args;
    dispatch_ret ret;
    const dispatch_data *data = NULL;
234 235
    int rv = -1;
    unsigned int len;
236
    virConnectPtr conn = NULL;
237

238 239
    memset(&args, 0, sizeof args);
    memset(&ret, 0, sizeof ret);
240
    memset(&rerr, 0, sizeof rerr);
241 242

    /* Parse the header. */
243 244 245 246
    xdrmem_create (&xdr,
                   msg->buffer + REMOTE_MESSAGE_HEADER_XDR_LEN,
                   msg->bufferLength - REMOTE_MESSAGE_HEADER_XDR_LEN,
                   XDR_DECODE);
247

248 249
    if (!xdr_remote_message_header (&xdr, &req))
        goto fatal_error;
250 251 252

    /* Check version, etc. */
    if (req.prog != REMOTE_PROGRAM) {
253 254 255 256
        remoteDispatchFormatError (&rerr,
                                   _("program mismatch (actual %x, expected %x)"),
                                   req.prog, REMOTE_PROGRAM);
        goto rpc_error;
257 258
    }
    if (req.vers != REMOTE_PROTOCOL_VERSION) {
259 260 261 262
        remoteDispatchFormatError (&rerr,
                                   _("version mismatch (actual %x, expected %x)"),
                                   req.vers, REMOTE_PROTOCOL_VERSION);
        goto rpc_error;
263 264
    }
    if (req.direction != REMOTE_CALL) {
265 266 267
        remoteDispatchFormatError (&rerr, _("direction (%d) != REMOTE_CALL"),
                                   (int) req.direction);
        goto rpc_error;
268 269
    }
    if (req.status != REMOTE_OK) {
270 271 272
        remoteDispatchFormatError (&rerr, _("status (%d) != REMOTE_OK"),
                                   (int) req.status);
        goto rpc_error;
273 274
    }

275 276 277 278 279 280 281
    /* If client is marked as needing auth, don't allow any RPC ops,
     * except for authentication ones
     */
    if (client->auth) {
        if (req.proc != REMOTE_PROC_AUTH_LIST &&
            req.proc != REMOTE_PROC_AUTH_SASL_INIT &&
            req.proc != REMOTE_PROC_AUTH_SASL_START &&
282 283
            req.proc != REMOTE_PROC_AUTH_SASL_STEP &&
            req.proc != REMOTE_PROC_AUTH_POLKIT
284
            ) {
285 286 287 288 289
            /* Explicitly *NOT* calling  remoteDispatchAuthError() because
               we want back-compatability with libvirt clients which don't
               support the VIR_ERR_AUTH_FAILED error code */
            remoteDispatchFormatError (&rerr, "%s", _("authentication required"));
            goto rpc_error;
290 291 292
        }
    }

293 294
    if (req.proc >= ARRAY_CARDINALITY(dispatch_table) ||
        dispatch_table[req.proc].fn == NULL) {
295 296 297
        remoteDispatchFormatError (&rerr, _("unknown procedure: %d"),
                                   req.proc);
        goto rpc_error;
298 299
    }

300 301 302 303
    data = &(dispatch_table[req.proc]);

    /* De-serialize args off the wire */
    if (!((data->args_filter)(&xdr, &args))) {
304 305
        remoteDispatchFormatError (&rerr, "%s", _("parse args failed"));
        goto rpc_error;
306 307 308
    }

    /* Call function. */
309
    conn = client->conn;
310
    virMutexUnlock(&client->lock);
311 312 313 314 315 316 317 318 319 320 321 322 323

    /*
     * When the RPC handler is called:
     *
     *  - Server object is unlocked
     *  - Client object is unlocked
     *
     * Without locking, it is safe to use:
     *
     *   'conn', 'rerr', 'args and 'ret'
     */
    rv = (data->fn)(server, client, conn, &rerr, &args, &ret);

324 325 326
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
327

328
    xdr_free (data->args_filter, (char*)&args);
329

330 331
rpc_error:
    xdr_destroy (&xdr);
332 333 334 335 336 337 338

    /* Return header. */
    rep.prog = req.prog;
    rep.vers = req.vers;
    rep.proc = req.proc;
    rep.direction = REMOTE_REPLY;
    rep.serial = req.serial;
339
    rep.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK;
340 341

    /* Serialise the return header. */
342
    xdrmem_create (&xdr, msg->buffer, sizeof msg->buffer, XDR_ENCODE);
343 344

    len = 0; /* We'll come back and write this later. */
345
    if (!xdr_u_int (&xdr, &len)) {
346
        if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
347
        goto fatal_error;
348 349 350
    }

    if (!xdr_remote_message_header (&xdr, &rep)) {
351
        if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
352
        goto fatal_error;
353 354 355
    }

    /* If OK, serialise return structure, if error serialise error. */
356 357 358
    if (rv >= 0) {
        if (!((data->ret_filter) (&xdr, &ret)))
            goto fatal_error;
359
        xdr_free (data->ret_filter, (char*)&ret);
360
    } else /* error */ {
361 362 363 364 365
        /* Error was NULL so synthesize an error. */
        if (rerr.code == 0)
            remoteDispatchGenericError(&rerr);
        if (!xdr_remote_error (&xdr, &rerr))
            goto fatal_error;
366
        xdr_free((xdrproc_t)xdr_remote_error,  (char *)&rerr);
367 368 369 370
    }

    /* Write the length word. */
    len = xdr_getpos (&xdr);
371 372
    if (xdr_setpos (&xdr, 0) == 0)
        goto fatal_error;
373

374
    if (!xdr_u_int (&xdr, &len))
375
        goto fatal_error;
376 377

    xdr_destroy (&xdr);
378 379 380 381 382

    msg->bufferLength = len;
    msg->bufferOffset = 0;

    return 0;
383

384 385 386
fatal_error:
    /* Seriously bad stuff happened, so we'll kill off this client
       and not send back any RPC error */
387
    xdr_destroy (&xdr);
388
    return -1;
389 390
}

391
int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
392 393 394 395
                            virDomainPtr dom,
                            int event,
                            int detail,
                            void *opaque)
396 397
{
    struct qemud_client *client = opaque;
398
    REMOTE_DEBUG("Relaying domain event %d %d", event, detail);
399

400 401 402 403 404 405 406 407 408 409 410 411 412 413
    if (client) {
        struct qemud_client_message *ev;

        if (VIR_ALLOC(ev) < 0)
            return -1;

        virMutexLock(&client->lock);

        remoteDispatchDomainEventSend (client, ev, dom, event, detail);

        if (qemudRegisterClientEvent(client->server, client, 1) < 0)
            qemudDispatchClientFailure(client);

        virMutexUnlock(&client->lock);
414 415 416
    }
    return 0;
}
417 418


419 420 421
/*----- Functions. -----*/

static int
422
remoteDispatchOpen (struct qemud_server *server,
423
                    struct qemud_client *client,
424
                    virConnectPtr conn,
425
                    remote_error *rerr,
426 427 428
                    struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED)
{
    const char *name;
429
    int flags, rc;
430 431

    /* Already opened? */
432
    if (conn) {
433 434
        remoteDispatchFormatError (rerr, "%s", _("connection already open"));
        return -1;
435 436
    }

437 438 439
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
440

441 442 443 444 445 446 447 448 449 450 451 452 453
    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);

454
    if (client->conn == NULL)
455 456
        remoteDispatchConnError(rerr, NULL);

457
    rc = client->conn ? 0 : -1;
458
    virMutexUnlock(&client->lock);
459
    return rc;
460 461
}

462 463 464 465
#define CHECK_CONN(client)                                              \
    if (!client->conn) {                                                \
        remoteDispatchFormatError (rerr, "%s", _("connection not open")); \
        return -1;                                                      \
466 467 468
    }

static int
469
remoteDispatchClose (struct qemud_server *server ATTRIBUTE_UNUSED,
470 471 472
                     struct qemud_client *client ATTRIBUTE_UNUSED,
                     virConnectPtr conn ATTRIBUTE_UNUSED,
                     remote_error *rerr ATTRIBUTE_UNUSED,
473 474
                     void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
{
475 476 477
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
478

479
    client->closing = 1;
480

481
    virMutexUnlock(&client->lock);
482
    return 0;
483 484
}

485
static int
486
remoteDispatchSupportsFeature (struct qemud_server *server ATTRIBUTE_UNUSED,
487 488
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
489
                               remote_error *rerr,
490 491
                               remote_supports_feature_args *args, remote_supports_feature_ret *ret)
{
492
    ret->supported = virDrvSupportsFeature (conn, args->feature);
493 494

    if (ret->supported == -1) {
495
        remoteDispatchConnError(rerr, conn);
496 497
        return -1;
    }
498 499 500 501

    return 0;
}

502
static int
503
remoteDispatchGetType (struct qemud_server *server ATTRIBUTE_UNUSED,
504 505
                       struct qemud_client *client ATTRIBUTE_UNUSED,
                       virConnectPtr conn,
506
                       remote_error *rerr,
507 508 509 510
                       void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret)
{
    const char *type;

511
    type = virConnectGetType (conn);
512
    if (type == NULL) {
513
        remoteDispatchConnError(rerr, conn);
514 515
        return -1;
    }
516 517 518 519 520 521

    /* We have to strdup because remoteDispatchClientRequest will
     * free this string after it's been serialised.
     */
    ret->type = strdup (type);
    if (!ret->type) {
522 523
        remoteDispatchFormatError (rerr, "%s", _("out of memory in strdup"));
        return -1;
524 525 526 527 528 529
    }

    return 0;
}

static int
530
remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
531 532
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
533
                          remote_error *rerr,
534 535 536 537 538
                          void *args ATTRIBUTE_UNUSED,
                          remote_get_version_ret *ret)
{
    unsigned long hvVer;

539 540
    if (virConnectGetVersion (conn, &hvVer) == -1) {
        remoteDispatchConnError(rerr, conn);
541
        return -1;
542
    }
543 544 545 546 547

    ret->hv_ver = hvVer;
    return 0;
}

548
static int
549
remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED,
550 551
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
552
                           remote_error *rerr,
553 554 555 556 557
                           void *args ATTRIBUTE_UNUSED,
                           remote_get_hostname_ret *ret)
{
    char *hostname;

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

    ret->hostname = hostname;
    return 0;
}

568 569
static int
remoteDispatchGetUri (struct qemud_server *server ATTRIBUTE_UNUSED,
570 571
                      struct qemud_client *client ATTRIBUTE_UNUSED,
                      virConnectPtr conn,
572
                      remote_error *rerr,
573 574 575 576 577 578
                      void *args ATTRIBUTE_UNUSED,
                      remote_get_uri_ret *ret)
{
    char *uri;
    CHECK_CONN(client);

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

    ret->uri = uri;
    return 0;
}

589
static int
590
remoteDispatchGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
591 592
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
593
                           remote_error *rerr,
594 595 596 597 598 599
                           remote_get_max_vcpus_args *args,
                           remote_get_max_vcpus_ret *ret)
{
    char *type;

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

    return 0;
}

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

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

    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
637
remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED,
638 639
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
640
                               remote_error *rerr,
641 642 643 644 645
                               void *args ATTRIBUTE_UNUSED,
                               remote_get_capabilities_ret *ret)
{
    char *caps;

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

    ret->capabilities = caps;
    return 0;
}

656 657
static int
remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
658 659
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
660
                                      remote_error *rerr,
661 662 663 664 665
                                      remote_node_get_cells_free_memory_args *args,
                                      remote_node_get_cells_free_memory_ret *ret)
{

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

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

677
    ret->freeMems.freeMems_len = virNodeGetCellsFreeMemory(conn,
678 679 680
                                                           (unsigned long long *)ret->freeMems.freeMems_val,
                                                           args->startCell,
                                                           args->maxCells);
681 682
    if (ret->freeMems.freeMems_len == 0) {
        VIR_FREE(ret->freeMems.freeMems_val);
683
        remoteDispatchConnError(rerr, conn);
684
        return -1;
685
    }
686 687 688 689 690 691 692

    return 0;
}


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

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


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

723
    dom = get_nonnull_domain (conn, args->dom);
724
    if (dom == NULL) {
725
        remoteDispatchConnError(rerr, conn);
726
        return -1;
727 728 729
    }

    type = virDomainGetSchedulerType (dom, &nparams);
730 731
    if (type == NULL) {
        virDomainFree(dom);
732
        remoteDispatchConnError(rerr, conn);
733 734
        return -1;
    }
735 736 737

    ret->type = type;
    ret->nparams = nparams;
738
    virDomainFree(dom);
739 740 741 742
    return 0;
}

static int
743
remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
744 745
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
746
                                            remote_error *rerr,
747 748 749 750 751 752 753 754 755 756
                                            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) {
757 758
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
759
    }
760
    if (VIR_ALLOC_N(params, nparams) < 0) {
761 762
        remoteDispatchOOMError(rerr);
        return -1;
763 764
    }

765
    dom = get_nonnull_domain (conn, args->dom);
766
    if (dom == NULL) {
767
        VIR_FREE(params);
768
        remoteDispatchConnError(rerr, conn);
769
        return -1;
770 771 772 773
    }

    r = virDomainGetSchedulerParameters (dom, params, &nparams);
    if (r == -1) {
774
        virDomainFree(dom);
775
        VIR_FREE(params);
776
        remoteDispatchConnError(rerr, conn);
777 778 779 780 781
        return -1;
    }

    /* Serialise the scheduler parameters. */
    ret->params.params_len = nparams;
782 783
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;
784 785 786 787

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

791 792 793 794 795 796 797 798 799 800 801 802 803 804 805
        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:
806
            remoteDispatchFormatError (rerr, "%s", _("unknown type"));
807
            goto cleanup;
808 809
        }
    }
810
    virDomainFree(dom);
811
    VIR_FREE(params);
812 813

    return 0;
814 815

oom:
816
    remoteDispatchOOMError(rerr);
817 818 819 820 821
cleanup:
    virDomainFree(dom);
    for (i = 0 ; i < nparams ; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
822
    return -1;
823 824 825
}

static int
826
remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
827 828
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
829
                                            remote_error *rerr,
830 831 832 833 834 835 836 837 838 839
                                            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) {
840 841
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
842
    }
843
    if (VIR_ALLOC_N(params, nparams)) {
844 845
        remoteDispatchOOMError(rerr);
        return -1;
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
    }

    /* Deserialise parameters. */
    for (i = 0; i < nparams; ++i) {
        strncpy (params[i].field, args->params.params_val[i].field,
                 VIR_DOMAIN_SCHED_FIELD_LENGTH);
        params[i].field[VIR_DOMAIN_SCHED_FIELD_LENGTH-1] = '\0';
        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;
        }
    }

870
    dom = get_nonnull_domain (conn, args->dom);
871
    if (dom == NULL) {
872
        VIR_FREE(params);
873
        remoteDispatchConnError(rerr, conn);
874
        return -1;
875 876 877
    }

    r = virDomainSetSchedulerParameters (dom, params, nparams);
878
    virDomainFree(dom);
879
    VIR_FREE(params);
880
    if (r == -1) {
881
        remoteDispatchConnError(rerr, conn);
882 883
        return -1;
    }
884 885 886 887

    return 0;
}

888
static int
889
remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED,
890 891
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
892
                                remote_error *rerr,
893 894 895 896 897 898 899
                                remote_domain_block_stats_args *args,
                                remote_domain_block_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainBlockStats stats;

900
    dom = get_nonnull_domain (conn, args->dom);
901
    if (dom == NULL) {
902
        remoteDispatchConnError(rerr, conn);
903
        return -1;
904 905 906
    }
    path = args->path;

D
Daniel P. Berrange 已提交
907 908
    if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
909
        remoteDispatchConnError(rerr, conn);
910
        return -1;
D
Daniel P. Berrange 已提交
911 912
    }
    virDomainFree (dom);
913 914 915 916 917 918 919 920 921 922 923

    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
924
remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED,
925 926
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
927
                                    remote_error *rerr,
928 929 930 931 932 933 934
                                    remote_domain_interface_stats_args *args,
                                    remote_domain_interface_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainInterfaceStats stats;

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

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

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

961 962
static int
remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
963 964
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
965
                               remote_error *rerr,
966 967 968 969 970 971 972 973 974
                               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;

975
    dom = get_nonnull_domain (conn, args->dom);
976
    if (dom == NULL) {
977
        remoteDispatchConnError(rerr, conn);
978
        return -1;
979 980 981 982 983 984 985
    }
    path = args->path;
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
986
        virDomainFree (dom);
987 988 989
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
990 991 992
    }

    ret->buffer.buffer_len = size;
993 994
    if (VIR_ALLOC_N(ret->buffer.buffer_val, size) < 0) {
        virDomainFree (dom);
995 996
        remoteDispatchFormatError (rerr, "%s", strerror (errno));
        return -1;
997 998 999 1000 1001 1002
    }

    if (virDomainBlockPeek (dom, path, offset, size,
                            ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
1003
        remoteDispatchConnError(rerr, conn);
1004 1005 1006 1007 1008 1009 1010
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

R
Richard W.M. Jones 已提交
1011 1012
static int
remoteDispatchDomainMemoryPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
1013 1014
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
1015
                                remote_error *rerr,
R
Richard W.M. Jones 已提交
1016 1017 1018 1019 1020 1021 1022 1023
                                remote_domain_memory_peek_args *args,
                                remote_domain_memory_peek_ret *ret)
{
    virDomainPtr dom;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

1024
    dom = get_nonnull_domain (conn, args->dom);
R
Richard W.M. Jones 已提交
1025
    if (dom == NULL) {
1026
        remoteDispatchConnError(rerr, conn);
1027
        return -1;
R
Richard W.M. Jones 已提交
1028 1029 1030 1031 1032 1033
    }
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
1034 1035
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
R
Richard W.M. Jones 已提交
1036
        virDomainFree (dom);
1037
        return -1;
R
Richard W.M. Jones 已提交
1038 1039 1040 1041
    }

    ret->buffer.buffer_len = size;
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
1042
        remoteDispatchFormatError (rerr, "%s", strerror (errno));
R
Richard W.M. Jones 已提交
1043
        virDomainFree (dom);
1044
        return -1;
R
Richard W.M. Jones 已提交
1045 1046 1047 1048 1049 1050
    }

    if (virDomainMemoryPeek (dom, offset, size,
                             ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
1051
        remoteDispatchConnError(rerr, conn);
R
Richard W.M. Jones 已提交
1052 1053 1054 1055 1056 1057 1058
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

1059
static int
1060
remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1061 1062
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1063
                                  remote_error *rerr,
1064 1065 1066 1067 1068
                                  remote_domain_attach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1069
    dom = get_nonnull_domain (conn, args->dom);
1070
    if (dom == NULL) {
1071
        remoteDispatchConnError(rerr, conn);
1072
        return -1;
1073 1074
    }

1075 1076
    if (virDomainAttachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
1077
        remoteDispatchConnError(rerr, conn);
1078
        return -1;
1079 1080
    }
    virDomainFree(dom);
1081 1082 1083 1084
    return 0;
}

static int
1085
remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
1086 1087
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1088
                            remote_error *rerr,
1089 1090 1091 1092 1093
                            remote_domain_create_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1094
    dom = get_nonnull_domain (conn, args->dom);
1095
    if (dom == NULL) {
1096
        remoteDispatchConnError(rerr, conn);
1097
        return -1;
1098 1099
    }

1100 1101
    if (virDomainCreate (dom) == -1) {
        virDomainFree(dom);
1102
        remoteDispatchConnError(rerr, conn);
1103
        return -1;
1104 1105
    }
    virDomainFree(dom);
1106 1107 1108 1109
    return 0;
}

static int
1110
remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1111 1112 1113 1114 1115
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_error *rerr,
                               remote_domain_create_xml_args *args,
                               remote_domain_create_xml_ret *ret)
1116 1117 1118
{
    virDomainPtr dom;

1119
    dom = virDomainCreateXML (conn, args->xml_desc, args->flags);
1120
    if (dom == NULL) {
1121
        remoteDispatchConnError(rerr, conn);
1122 1123
        return -1;
    }
1124 1125

    make_nonnull_domain (&ret->dom, dom);
1126
    virDomainFree(dom);
1127 1128 1129 1130 1131

    return 0;
}

static int
1132
remoteDispatchDomainDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1133 1134
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1135
                               remote_error *rerr,
1136 1137 1138 1139 1140
                               remote_domain_define_xml_args *args,
                               remote_domain_define_xml_ret *ret)
{
    virDomainPtr dom;

1141
    dom = virDomainDefineXML (conn, args->xml);
1142
    if (dom == NULL) {
1143
        remoteDispatchConnError(rerr, conn);
1144 1145
        return -1;
    }
1146 1147

    make_nonnull_domain (&ret->dom, dom);
1148
    virDomainFree(dom);
1149 1150 1151 1152 1153

    return 0;
}

static int
1154
remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
1155 1156
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1157
                             remote_error *rerr,
1158 1159 1160 1161 1162
                             remote_domain_destroy_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1163
    dom = get_nonnull_domain (conn, args->dom);
1164
    if (dom == NULL) {
1165
        remoteDispatchConnError(rerr, conn);
1166
        return -1;
1167 1168
    }

1169 1170
    if (virDomainDestroy (dom) == -1) {
        virDomainFree(dom);
1171
        remoteDispatchConnError(rerr, conn);
1172
        return -1;
1173 1174
    }
    virDomainFree(dom);
1175 1176 1177 1178
    return 0;
}

static int
1179
remoteDispatchDomainDetachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1180 1181
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1182
                                  remote_error *rerr,
1183 1184 1185 1186 1187
                                  remote_domain_detach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1188
    dom = get_nonnull_domain (conn, args->dom);
1189
    if (dom == NULL) {
1190
        remoteDispatchConnError(rerr, conn);
1191
        return -1;
1192 1193
    }

1194 1195
    if (virDomainDetachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
1196
        remoteDispatchConnError(rerr, conn);
1197
        return -1;
1198
    }
1199

1200
    virDomainFree(dom);
1201 1202 1203 1204
    return 0;
}

static int
1205
remoteDispatchDomainDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1206 1207
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1208
                             remote_error *rerr,
1209 1210 1211 1212 1213
                             remote_domain_dump_xml_args *args,
                             remote_domain_dump_xml_ret *ret)
{
    virDomainPtr dom;

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

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virDomainGetXMLDesc (dom, args->flags);
1222
    if (!ret->xml) {
1223
        virDomainFree(dom);
1224
        remoteDispatchConnError(rerr, conn);
1225
        return -1;
1226 1227
    }
    virDomainFree(dom);
1228 1229 1230 1231
    return 0;
}

static int
1232
remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1233 1234
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1235
                                  remote_error *rerr,
1236 1237 1238 1239 1240
                                  remote_domain_get_autostart_args *args,
                                  remote_domain_get_autostart_ret *ret)
{
    virDomainPtr dom;

1241
    dom = get_nonnull_domain (conn, args->dom);
1242
    if (dom == NULL) {
1243
        remoteDispatchConnError(rerr, conn);
1244
        return -1;
1245 1246
    }

1247 1248
    if (virDomainGetAutostart (dom, &ret->autostart) == -1) {
        virDomainFree(dom);
1249
        remoteDispatchConnError(rerr, conn);
1250
        return -1;
1251 1252
    }
    virDomainFree(dom);
1253 1254 1255 1256
    return 0;
}

static int
1257
remoteDispatchDomainGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
1258 1259
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1260
                             remote_error *rerr,
1261 1262 1263 1264 1265 1266
                             remote_domain_get_info_args *args,
                             remote_domain_get_info_ret *ret)
{
    virDomainPtr dom;
    virDomainInfo info;

1267
    dom = get_nonnull_domain (conn, args->dom);
1268
    if (dom == NULL) {
1269
        remoteDispatchConnError(rerr, conn);
1270
        return -1;
1271 1272
    }

1273 1274
    if (virDomainGetInfo (dom, &info) == -1) {
        virDomainFree(dom);
1275
        remoteDispatchConnError(rerr, conn);
1276
        return -1;
1277
    }
1278 1279 1280 1281 1282 1283 1284

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

1285 1286
    virDomainFree(dom);

1287 1288 1289 1290
    return 0;
}

static int
1291
remoteDispatchDomainGetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1292 1293
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1294
                                  remote_error *rerr,
1295 1296 1297 1298 1299
                                  remote_domain_get_max_memory_args *args,
                                  remote_domain_get_max_memory_ret *ret)
{
    virDomainPtr dom;

1300
    dom = get_nonnull_domain (conn, args->dom);
1301
    if (dom == NULL) {
1302
        remoteDispatchConnError(rerr, conn);
1303
        return -1;
1304 1305 1306
    }

    ret->memory = virDomainGetMaxMemory (dom);
1307 1308
    if (ret->memory == 0) {
        virDomainFree(dom);
1309
        remoteDispatchConnError(rerr, conn);
1310 1311 1312
        return -1;
    }
    virDomainFree(dom);
1313 1314 1315 1316
    return 0;
}

static int
1317
remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1318 1319
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1320
                                 remote_error *rerr,
1321 1322 1323 1324 1325
                                 remote_domain_get_max_vcpus_args *args,
                                 remote_domain_get_max_vcpus_ret *ret)
{
    virDomainPtr dom;

1326
    dom = get_nonnull_domain (conn, args->dom);
1327
    if (dom == NULL) {
1328
        remoteDispatchConnError(rerr, conn);
1329
        return -1;
1330 1331 1332
    }

    ret->num = virDomainGetMaxVcpus (dom);
1333 1334
    if (ret->num == -1) {
        virDomainFree(dom);
1335
        remoteDispatchConnError(rerr, conn);
1336 1337 1338
        return -1;
    }
    virDomainFree(dom);
1339 1340 1341 1342
    return 0;
}

static int
1343
remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED,
1344 1345
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1346
                               remote_error *rerr,
1347 1348 1349 1350 1351
                               remote_domain_get_os_type_args *args,
                               remote_domain_get_os_type_ret *ret)
{
    virDomainPtr dom;

1352
    dom = get_nonnull_domain (conn, args->dom);
1353
    if (dom == NULL) {
1354
        remoteDispatchConnError(rerr, conn);
1355
        return -1;
1356 1357 1358 1359
    }

    /* remoteDispatchClientRequest will free this */
    ret->type = virDomainGetOSType (dom);
1360
    if (ret->type == NULL) {
1361
        virDomainFree(dom);
1362
        remoteDispatchConnError(rerr, conn);
1363
        return -1;
1364 1365
    }
    virDomainFree(dom);
1366 1367 1368 1369
    return 0;
}

static int
1370
remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1371 1372
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1373
                              remote_error *rerr,
1374 1375 1376
                              remote_domain_get_vcpus_args *args,
                              remote_domain_get_vcpus_ret *ret)
{
1377 1378 1379
    virDomainPtr dom = NULL;
    virVcpuInfoPtr info = NULL;
    unsigned char *cpumaps = NULL;
1380 1381
    int info_len, i;

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

    if (args->maxinfo > REMOTE_VCPUINFO_MAX) {
1389
        virDomainFree(dom);
1390 1391
        remoteDispatchFormatError (rerr, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX"));
        return -1;
1392 1393
    }

1394
    if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
1395
        virDomainFree(dom);
1396 1397
        remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX"));
        return -1;
1398 1399 1400
    }

    /* Allocate buffers to take the results. */
1401 1402 1403 1404
    if (VIR_ALLOC_N(info, args->maxinfo) < 0)
        goto oom;
    if (VIR_ALLOC_N(cpumaps, args->maxinfo) < 0)
        goto oom;
1405 1406 1407 1408

    info_len = virDomainGetVcpus (dom,
                                  info, args->maxinfo,
                                  cpumaps, args->maplen);
1409
    if (info_len == -1) {
1410 1411
        VIR_FREE(info);
        VIR_FREE(cpumaps);
1412
        virDomainFree(dom);
1413
        remoteDispatchConnError(rerr, conn);
1414 1415
        return -1;
    }
1416 1417 1418

    /* Allocate the return buffer for info. */
    ret->info.info_len = info_len;
1419 1420
    if (VIR_ALLOC_N(ret->info.info_val, info_len) < 0)
        goto oom;
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432

    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.
     */
1433
    ret->cpumaps.cpumaps_len = args->maxinfo * args->maplen;
1434 1435
    ret->cpumaps.cpumaps_val = (char *) cpumaps;

1436
    VIR_FREE(info);
1437
    virDomainFree(dom);
1438
    return 0;
1439 1440 1441 1442 1443

oom:
    VIR_FREE(info);
    VIR_FREE(cpumaps);
    virDomainFree(dom);
1444 1445
    remoteDispatchOOMError(rerr);
    return -1;
1446 1447
}

1448
static int
1449
remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED,
1450 1451
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1452
                                    remote_error *rerr,
1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
                                    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 ... */
1467
    if (VIR_ALLOC(uri_out) < 0) {
1468 1469
        remoteDispatchOOMError(rerr);
        return -1;
1470
    }
1471

1472
    r = virDomainMigratePrepare (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1473 1474
                                 uri_in, uri_out,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1475
    if (r == -1) {
1476
        VIR_FREE(uri_out);
1477
        remoteDispatchConnError(rerr, conn);
D
Daniel P. Berrange 已提交
1478 1479
        return -1;
    }
1480 1481 1482 1483 1484 1485

    /* 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 已提交
1486 1487
    if (*uri_out == NULL) {
        ret->uri_out = NULL;
1488
        VIR_FREE(uri_out);
D
Daniel P. Berrange 已提交
1489 1490 1491
    } else {
        ret->uri_out = uri_out;
    }
1492 1493 1494 1495 1496

    return 0;
}

static int
1497
remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED,
1498 1499
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1500
                                    remote_error *rerr,
1501 1502 1503 1504 1505 1506 1507
                                    remote_domain_migrate_perform_args *args,
                                    void *ret ATTRIBUTE_UNUSED)
{
    int r;
    virDomainPtr dom;
    char *dname;

1508
    dom = get_nonnull_domain (conn, args->dom);
1509
    if (dom == NULL) {
1510
        remoteDispatchConnError(rerr, conn);
1511
        return -1;
1512 1513 1514 1515
    }

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

D
Daniel P. Berrange 已提交
1516 1517 1518 1519 1520
    r = virDomainMigratePerform (dom,
                                 args->cookie.cookie_val,
                                 args->cookie.cookie_len,
                                 args->uri,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1521
    virDomainFree (dom);
1522
    if (r == -1) {
1523
        remoteDispatchConnError(rerr, conn);
1524 1525
        return -1;
    }
1526 1527 1528 1529 1530

    return 0;
}

static int
1531
remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED,
1532 1533
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1534
                                   remote_error *rerr,
1535 1536 1537 1538 1539 1540
                                   remote_domain_migrate_finish_args *args,
                                   remote_domain_migrate_finish_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1541
    ddom = virDomainMigrateFinish (conn, args->dname,
D
Daniel P. Berrange 已提交
1542 1543 1544 1545
                                   args->cookie.cookie_val,
                                   args->cookie.cookie_len,
                                   args->uri,
                                   args->flags);
1546
    if (ddom == NULL) {
1547
        remoteDispatchConnError(rerr, conn);
1548 1549
        return -1;
    }
1550 1551

    make_nonnull_domain (&ret->ddom, ddom);
D
Daniel P. Berrange 已提交
1552
    virDomainFree (ddom);
1553 1554 1555
    return 0;
}

D
Daniel Veillard 已提交
1556 1557
static int
remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1558 1559
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1560
                                     remote_error *rerr,
D
Daniel Veillard 已提交
1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
                                     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) {
1577 1578
        remoteDispatchOOMError(rerr);
        return -1;
D
Daniel Veillard 已提交
1579 1580
    }

1581
    r = virDomainMigratePrepare2 (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1582 1583 1584
                                  uri_in, uri_out,
                                  args->flags, dname, args->resource,
                                  args->dom_xml);
1585
    if (r == -1) {
1586
        remoteDispatchConnError(rerr, conn);
1587 1588
        return -1;
    }
D
Daniel Veillard 已提交
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601

    /* 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,
1602 1603
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1604
                                    remote_error *rerr,
D
Daniel Veillard 已提交
1605 1606 1607 1608 1609 1610
                                    remote_domain_migrate_finish2_args *args,
                                    remote_domain_migrate_finish2_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1611
    ddom = virDomainMigrateFinish2 (conn, args->dname,
D
Daniel P. Berrange 已提交
1612 1613 1614 1615 1616
                                    args->cookie.cookie_val,
                                    args->cookie.cookie_len,
                                    args->uri,
                                    args->flags,
                                    args->retcode);
1617
    if (ddom == NULL) {
1618
        remoteDispatchConnError(rerr, conn);
1619 1620
        return -1;
    }
D
Daniel Veillard 已提交
1621 1622 1623 1624 1625 1626

    make_nonnull_domain (&ret->ddom, ddom);

    return 0;
}

1627
static int
1628
remoteDispatchListDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1629 1630
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1631
                                  remote_error *rerr,
1632 1633 1634 1635 1636
                                  remote_list_defined_domains_args *args,
                                  remote_list_defined_domains_ret *ret)
{

    if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) {
1637 1638 1639
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX"));
        return -1;
1640 1641 1642
    }

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

    ret->names.names_len =
1649
        virConnectListDefinedDomains (conn,
1650
                                      ret->names.names_val, args->maxnames);
1651 1652
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
1653
        remoteDispatchConnError(rerr, conn);
1654 1655
        return -1;
    }
1656 1657 1658 1659 1660

    return 0;
}

static int
1661
remoteDispatchDomainLookupById (struct qemud_server *server ATTRIBUTE_UNUSED,
1662 1663
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
1664
                                remote_error *rerr,
1665 1666 1667 1668 1669
                                remote_domain_lookup_by_id_args *args,
                                remote_domain_lookup_by_id_ret *ret)
{
    virDomainPtr dom;

1670
    dom = virDomainLookupByID (conn, args->id);
1671
    if (dom == NULL) {
1672
        remoteDispatchConnError(rerr, conn);
1673 1674
        return -1;
    }
1675 1676

    make_nonnull_domain (&ret->dom, dom);
1677
    virDomainFree(dom);
1678 1679 1680 1681
    return 0;
}

static int
1682
remoteDispatchDomainLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
1683 1684
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1685
                                  remote_error *rerr,
1686 1687 1688 1689 1690
                                  remote_domain_lookup_by_name_args *args,
                                  remote_domain_lookup_by_name_ret *ret)
{
    virDomainPtr dom;

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

    make_nonnull_domain (&ret->dom, dom);
1698
    virDomainFree(dom);
1699 1700 1701 1702
    return 0;
}

static int
1703
remoteDispatchDomainLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
1704 1705
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1706
                                  remote_error *rerr,
1707 1708 1709 1710 1711
                                  remote_domain_lookup_by_uuid_args *args,
                                  remote_domain_lookup_by_uuid_ret *ret)
{
    virDomainPtr dom;

1712
    dom = virDomainLookupByUUID (conn, (unsigned char *) args->uuid);
1713
    if (dom == NULL) {
1714
        remoteDispatchConnError(rerr, conn);
1715 1716
        return -1;
    }
1717 1718

    make_nonnull_domain (&ret->dom, dom);
1719
    virDomainFree(dom);
1720 1721 1722 1723
    return 0;
}

static int
1724
remoteDispatchNumOfDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1725 1726
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1727
                                   remote_error *rerr,
1728 1729 1730 1731
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_num_of_defined_domains_ret *ret)
{

1732
    ret->num = virConnectNumOfDefinedDomains (conn);
1733
    if (ret->num == -1) {
1734
        remoteDispatchConnError(rerr, conn);
1735 1736
        return -1;
    }
1737 1738 1739 1740 1741

    return 0;
}

static int
1742
remoteDispatchDomainPinVcpu (struct qemud_server *server ATTRIBUTE_UNUSED,
1743 1744
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1745
                             remote_error *rerr,
1746 1747 1748 1749 1750 1751
                             remote_domain_pin_vcpu_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int rv;

1752
    dom = get_nonnull_domain (conn, args->dom);
1753
    if (dom == NULL) {
1754
        remoteDispatchConnError(rerr, conn);
1755
        return -1;
1756 1757 1758
    }

    if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) {
1759
        virDomainFree(dom);
1760 1761
        remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX"));
        return -1;
1762 1763 1764 1765 1766
    }

    rv = virDomainPinVcpu (dom, args->vcpu,
                           (unsigned char *) args->cpumap.cpumap_val,
                           args->cpumap.cpumap_len);
1767 1768
    if (rv == -1) {
        virDomainFree(dom);
1769
        remoteDispatchConnError(rerr, conn);
1770 1771 1772
        return -1;
    }
    virDomainFree(dom);
1773 1774 1775 1776
    return 0;
}

static int
1777
remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED,
1778 1779
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1780
                            remote_error *rerr,
1781 1782 1783 1784 1785
                            remote_domain_reboot_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1786
    dom = get_nonnull_domain (conn, args->dom);
1787
    if (dom == NULL) {
1788
        remoteDispatchConnError(rerr, conn);
1789
        return -1;
1790 1791
    }

1792 1793
    if (virDomainReboot (dom, args->flags) == -1) {
        virDomainFree(dom);
1794
        remoteDispatchConnError(rerr, conn);
1795
        return -1;
1796 1797
    }
    virDomainFree(dom);
1798 1799 1800 1801
    return 0;
}

static int
1802
remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED,
1803 1804
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1805
                             remote_error *rerr,
1806 1807 1808 1809
                             remote_domain_restore_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{

1810 1811
    if (virDomainRestore (conn, args->from) == -1) {
        remoteDispatchConnError(rerr, conn);
1812
        return -1;
1813
    }
1814 1815 1816 1817 1818

    return 0;
}

static int
1819
remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED,
1820 1821
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1822
                            remote_error *rerr,
1823 1824 1825 1826 1827
                            remote_domain_resume_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1828
    dom = get_nonnull_domain (conn, args->dom);
1829
    if (dom == NULL) {
1830
        remoteDispatchConnError(rerr, conn);
1831
        return -1;
1832 1833
    }

1834 1835
    if (virDomainResume (dom) == -1) {
        virDomainFree(dom);
1836
        remoteDispatchConnError(rerr, conn);
1837
        return -1;
1838 1839
    }
    virDomainFree(dom);
1840 1841 1842 1843
    return 0;
}

static int
1844
remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED,
1845 1846
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
1847
                          remote_error *rerr,
1848 1849 1850 1851 1852
                          remote_domain_save_args *args,
                          void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1853
    dom = get_nonnull_domain (conn, args->dom);
1854
    if (dom == NULL) {
1855
        remoteDispatchConnError(rerr, conn);
1856
        return -1;
1857 1858
    }

1859 1860
    if (virDomainSave (dom, args->to) == -1) {
        virDomainFree(dom);
1861
        remoteDispatchConnError(rerr, conn);
1862
        return -1;
1863 1864
    }
    virDomainFree(dom);
1865 1866 1867 1868
    return 0;
}

static int
1869
remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED,
1870 1871
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1872
                              remote_error *rerr,
1873 1874 1875 1876 1877
                              remote_domain_core_dump_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

1884 1885
    if (virDomainCoreDump (dom, args->to, args->flags) == -1) {
        virDomainFree(dom);
1886
        remoteDispatchConnError(rerr, conn);
1887
        return -1;
1888 1889
    }
    virDomainFree(dom);
1890 1891 1892 1893
    return 0;
}

static int
1894
remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1895 1896
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1897
                                  remote_error *rerr,
1898 1899 1900 1901 1902
                                  remote_domain_set_autostart_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1903
    dom = get_nonnull_domain (conn, args->dom);
1904
    if (dom == NULL) {
1905
        remoteDispatchConnError(rerr, conn);
1906
        return -1;
1907 1908
    }

1909 1910
    if (virDomainSetAutostart (dom, args->autostart) == -1) {
        virDomainFree(dom);
1911
        remoteDispatchConnError(rerr, conn);
1912
        return -1;
1913 1914
    }
    virDomainFree(dom);
1915 1916 1917 1918
    return 0;
}

static int
1919
remoteDispatchDomainSetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1920 1921
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1922
                                  remote_error *rerr,
1923 1924 1925 1926 1927
                                  remote_domain_set_max_memory_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1928
    dom = get_nonnull_domain (conn, args->dom);
1929
    if (dom == NULL) {
1930
        remoteDispatchConnError(rerr, conn);
1931
        return -1;
1932 1933
    }

1934 1935
    if (virDomainSetMaxMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
1936
        remoteDispatchConnError(rerr, conn);
1937
        return -1;
1938 1939
    }
    virDomainFree(dom);
1940 1941 1942 1943
    return 0;
}

static int
1944
remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1945 1946
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1947
                               remote_error *rerr,
1948 1949 1950 1951 1952
                               remote_domain_set_memory_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1953
    dom = get_nonnull_domain (conn, args->dom);
1954
    if (dom == NULL) {
1955
        remoteDispatchConnError(rerr, conn);
1956
        return -1;
1957 1958
    }

1959 1960
    if (virDomainSetMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
1961
        remoteDispatchConnError(rerr, conn);
1962
        return -1;
1963 1964
    }
    virDomainFree(dom);
1965 1966 1967 1968
    return 0;
}

static int
1969
remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1970 1971
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1972
                              remote_error *rerr,
1973 1974 1975 1976 1977
                              remote_domain_set_vcpus_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1978
    dom = get_nonnull_domain (conn, args->dom);
1979
    if (dom == NULL) {
1980
        remoteDispatchConnError(rerr, conn);
1981
        return -1;
1982 1983
    }

1984 1985
    if (virDomainSetVcpus (dom, args->nvcpus) == -1) {
        virDomainFree(dom);
1986
        remoteDispatchConnError(rerr, conn);
1987
        return -1;
1988 1989
    }
    virDomainFree(dom);
1990 1991 1992 1993
    return 0;
}

static int
1994
remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED,
1995 1996
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1997
                              remote_error *rerr,
1998 1999 2000 2001 2002
                              remote_domain_shutdown_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2003
    dom = get_nonnull_domain (conn, args->dom);
2004
    if (dom == NULL) {
2005
        remoteDispatchConnError(rerr, conn);
2006
        return -1;
2007 2008
    }

2009 2010
    if (virDomainShutdown (dom) == -1) {
        virDomainFree(dom);
2011
        remoteDispatchConnError(rerr, conn);
2012
        return -1;
2013 2014
    }
    virDomainFree(dom);
2015 2016 2017 2018
    return 0;
}

static int
2019
remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED,
2020 2021
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2022
                             remote_error *rerr,
2023 2024 2025 2026 2027
                             remote_domain_suspend_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2028
    dom = get_nonnull_domain (conn, args->dom);
2029
    if (dom == NULL) {
2030
        remoteDispatchConnError(rerr, conn);
2031
        return -1;
2032 2033
    }

2034 2035
    if (virDomainSuspend (dom) == -1) {
        virDomainFree(dom);
2036
        remoteDispatchConnError(rerr, conn);
2037
        return -1;
2038 2039
    }
    virDomainFree(dom);
2040 2041 2042 2043
    return 0;
}

static int
2044
remoteDispatchDomainUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2045 2046
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2047
                              remote_error *rerr,
2048 2049 2050 2051 2052
                              remote_domain_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2053
    dom = get_nonnull_domain (conn, args->dom);
2054
    if (dom == NULL) {
2055
        remoteDispatchConnError(rerr, conn);
2056
        return -1;
2057 2058
    }

2059 2060
    if (virDomainUndefine (dom) == -1) {
        virDomainFree(dom);
2061
        remoteDispatchConnError(rerr, conn);
2062
        return -1;
2063 2064
    }
    virDomainFree(dom);
2065 2066 2067 2068
    return 0;
}

static int
2069
remoteDispatchListDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2070 2071
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2072
                                   remote_error *rerr,
2073 2074 2075 2076 2077
                                   remote_list_defined_networks_args *args,
                                   remote_list_defined_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2078 2079 2080
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2081 2082 2083
    }

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

    ret->names.names_len =
2090
        virConnectListDefinedNetworks (conn,
2091
                                       ret->names.names_val, args->maxnames);
2092 2093
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
2094
        remoteDispatchConnError(rerr, conn);
2095 2096
        return -1;
    }
2097 2098 2099 2100 2101

    return 0;
}

static int
2102
remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2103 2104
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
2105
                           remote_error *rerr,
2106 2107 2108 2109 2110
                           remote_list_domains_args *args,
                           remote_list_domains_ret *ret)
{

    if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
2111 2112 2113
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX"));
        return -1;
2114 2115 2116
    }

    /* Allocate return buffer. */
2117
    if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) {
2118 2119
        remoteDispatchOOMError(rerr);
        return -1;
2120
    }
2121

2122
    ret->ids.ids_len = virConnectListDomains (conn,
2123
                                              ret->ids.ids_val, args->maxids);
2124 2125
    if (ret->ids.ids_len == -1) {
        VIR_FREE(ret->ids.ids_val);
2126
        remoteDispatchConnError(rerr, conn);
2127 2128
        return -1;
    }
2129 2130 2131 2132 2133

    return 0;
}

static int
2134
remoteDispatchListNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2135 2136
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2137
                            remote_error *rerr,
2138 2139 2140 2141 2142
                            remote_list_networks_args *args,
                            remote_list_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2143 2144 2145
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2146 2147 2148
    }

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

    ret->names.names_len =
2155
        virConnectListNetworks (conn,
2156
                                ret->names.names_val, args->maxnames);
2157 2158
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
2159
        remoteDispatchConnError(rerr, conn);
2160 2161
        return -1;
    }
2162 2163 2164 2165 2166

    return 0;
}

static int
2167
remoteDispatchNetworkCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
2168 2169
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2170
                             remote_error *rerr,
2171 2172 2173 2174 2175
                             remote_network_create_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2176
    net = get_nonnull_network (conn, args->net);
2177
    if (net == NULL) {
2178
        remoteDispatchConnError(rerr, conn);
2179
        return -1;
2180 2181
    }

2182 2183
    if (virNetworkCreate (net) == -1) {
        virNetworkFree(net);
2184
        remoteDispatchConnError(rerr, conn);
2185
        return -1;
2186 2187
    }
    virNetworkFree(net);
2188 2189 2190 2191
    return 0;
}

static int
2192
remoteDispatchNetworkCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2193 2194
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2195
                                remote_error *rerr,
2196 2197 2198 2199 2200
                                remote_network_create_xml_args *args,
                                remote_network_create_xml_ret *ret)
{
    virNetworkPtr net;

2201
    net = virNetworkCreateXML (conn, args->xml);
2202
    if (net == NULL) {
2203
        remoteDispatchConnError(rerr, conn);
2204 2205
        return -1;
    }
2206 2207

    make_nonnull_network (&ret->net, net);
2208
    virNetworkFree(net);
2209 2210 2211 2212
    return 0;
}

static int
2213
remoteDispatchNetworkDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2214 2215
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2216
                                remote_error *rerr,
2217 2218 2219 2220 2221
                                remote_network_define_xml_args *args,
                                remote_network_define_xml_ret *ret)
{
    virNetworkPtr net;

2222
    net = virNetworkDefineXML (conn, args->xml);
2223
    if (net == NULL) {
2224
        remoteDispatchConnError(rerr, conn);
2225 2226
        return -1;
    }
2227 2228

    make_nonnull_network (&ret->net, net);
2229
    virNetworkFree(net);
2230 2231 2232 2233
    return 0;
}

static int
2234
remoteDispatchNetworkDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
2235 2236
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2237
                              remote_error *rerr,
2238 2239 2240 2241 2242
                              remote_network_destroy_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2243
    net = get_nonnull_network (conn, args->net);
2244
    if (net == NULL) {
2245
        remoteDispatchConnError(rerr, conn);
2246
        return -1;
2247 2248
    }

2249 2250
    if (virNetworkDestroy (net) == -1) {
        virNetworkFree(net);
2251
        remoteDispatchConnError(rerr, conn);
2252
        return -1;
2253 2254
    }
    virNetworkFree(net);
2255 2256 2257 2258
    return 0;
}

static int
2259
remoteDispatchNetworkDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2260 2261
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2262
                              remote_error *rerr,
2263 2264 2265 2266 2267
                              remote_network_dump_xml_args *args,
                              remote_network_dump_xml_ret *ret)
{
    virNetworkPtr net;

2268
    net = get_nonnull_network (conn, args->net);
2269
    if (net == NULL) {
2270
        remoteDispatchConnError(rerr, conn);
2271
        return -1;
2272 2273 2274 2275
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNetworkGetXMLDesc (net, args->flags);
2276 2277
    if (!ret->xml) {
        virNetworkFree(net);
2278
        remoteDispatchConnError(rerr, conn);
2279 2280 2281
        return -1;
    }
    virNetworkFree(net);
2282 2283 2284 2285
    return 0;
}

static int
2286
remoteDispatchNetworkGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2287 2288
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2289
                                   remote_error *rerr,
2290 2291 2292 2293 2294
                                   remote_network_get_autostart_args *args,
                                   remote_network_get_autostart_ret *ret)
{
    virNetworkPtr net;

2295
    net = get_nonnull_network (conn, args->net);
2296
    if (net == NULL) {
2297
        remoteDispatchConnError(rerr, conn);
2298
        return -1;
2299 2300
    }

2301 2302
    if (virNetworkGetAutostart (net, &ret->autostart) == -1) {
        virNetworkFree(net);
2303
        remoteDispatchConnError(rerr, conn);
2304
        return -1;
2305 2306
    }
    virNetworkFree(net);
2307 2308 2309 2310
    return 0;
}

static int
2311
remoteDispatchNetworkGetBridgeName (struct qemud_server *server ATTRIBUTE_UNUSED,
2312 2313
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2314
                                    remote_error *rerr,
2315 2316 2317 2318 2319
                                    remote_network_get_bridge_name_args *args,
                                    remote_network_get_bridge_name_ret *ret)
{
    virNetworkPtr net;

2320
    net = get_nonnull_network (conn, args->net);
2321
    if (net == NULL) {
2322
        remoteDispatchConnError(rerr, conn);
2323
        return -1;
2324 2325 2326 2327
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virNetworkGetBridgeName (net);
2328 2329
    if (!ret->name) {
        virNetworkFree(net);
2330
        remoteDispatchConnError(rerr, conn);
2331 2332 2333
        return -1;
    }
    virNetworkFree(net);
2334 2335 2336 2337
    return 0;
}

static int
2338
remoteDispatchNetworkLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
2339 2340
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2341
                                   remote_error *rerr,
2342 2343 2344 2345 2346
                                   remote_network_lookup_by_name_args *args,
                                   remote_network_lookup_by_name_ret *ret)
{
    virNetworkPtr net;

2347
    net = virNetworkLookupByName (conn, args->name);
2348
    if (net == NULL) {
2349
        remoteDispatchConnError(rerr, conn);
2350 2351
        return -1;
    }
2352 2353

    make_nonnull_network (&ret->net, net);
2354
    virNetworkFree(net);
2355 2356 2357 2358
    return 0;
}

static int
2359
remoteDispatchNetworkLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
2360 2361
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2362
                                   remote_error *rerr,
2363 2364 2365 2366 2367
                                   remote_network_lookup_by_uuid_args *args,
                                   remote_network_lookup_by_uuid_ret *ret)
{
    virNetworkPtr net;

2368
    net = virNetworkLookupByUUID (conn, (unsigned char *) args->uuid);
2369
    if (net == NULL) {
2370
        remoteDispatchConnError(rerr, conn);
2371 2372
        return -1;
    }
2373 2374

    make_nonnull_network (&ret->net, net);
2375
    virNetworkFree(net);
2376 2377 2378 2379
    return 0;
}

static int
2380
remoteDispatchNetworkSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2381 2382
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2383
                                   remote_error *rerr,
2384 2385 2386 2387 2388
                                   remote_network_set_autostart_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2389
    net = get_nonnull_network (conn, args->net);
2390
    if (net == NULL) {
2391
        remoteDispatchConnError(rerr, conn);
2392
        return -1;
2393 2394
    }

2395 2396
    if (virNetworkSetAutostart (net, args->autostart) == -1) {
        virNetworkFree(net);
2397
        remoteDispatchConnError(rerr, conn);
2398
        return -1;
2399 2400
    }
    virNetworkFree(net);
2401 2402 2403 2404
    return 0;
}

static int
2405
remoteDispatchNetworkUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2406 2407
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2408
                               remote_error *rerr,
2409 2410 2411 2412 2413
                               remote_network_undefine_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2414
    net = get_nonnull_network (conn, args->net);
2415
    if (net == NULL) {
2416
        remoteDispatchConnError(rerr, conn);
2417
        return -1;
2418 2419
    }

2420 2421
    if (virNetworkUndefine (net) == -1) {
        virNetworkFree(net);
2422
        remoteDispatchConnError(rerr, conn);
2423
        return -1;
2424 2425
    }
    virNetworkFree(net);
2426 2427 2428 2429
    return 0;
}

static int
2430
remoteDispatchNumOfDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2431 2432
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2433
                                    remote_error *rerr,
2434 2435 2436 2437
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_num_of_defined_networks_ret *ret)
{

2438
    ret->num = virConnectNumOfDefinedNetworks (conn);
2439
    if (ret->num == -1) {
2440
        remoteDispatchConnError(rerr, conn);
2441 2442
        return -1;
    }
2443 2444 2445 2446 2447

    return 0;
}

static int
2448
remoteDispatchNumOfDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2449 2450
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2451
                            remote_error *rerr,
2452 2453 2454 2455
                            void *args ATTRIBUTE_UNUSED,
                            remote_num_of_domains_ret *ret)
{

2456
    ret->num = virConnectNumOfDomains (conn);
2457
    if (ret->num == -1) {
2458
        remoteDispatchConnError(rerr, conn);
2459 2460
        return -1;
    }
2461 2462 2463 2464 2465

    return 0;
}

static int
2466
remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2467 2468
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2469
                             remote_error *rerr,
2470 2471 2472 2473
                             void *args ATTRIBUTE_UNUSED,
                             remote_num_of_networks_ret *ret)
{

2474
    ret->num = virConnectNumOfNetworks (conn);
2475
    if (ret->num == -1) {
2476
        remoteDispatchConnError(rerr, conn);
2477 2478
        return -1;
    }
2479 2480 2481 2482

    return 0;
}

2483 2484

static int
2485
remoteDispatchAuthList (struct qemud_server *server,
2486
                        struct qemud_client *client,
2487
                        virConnectPtr conn ATTRIBUTE_UNUSED,
2488
                        remote_error *rerr,
2489 2490 2491 2492
                        void *args ATTRIBUTE_UNUSED,
                        remote_auth_list_ret *ret)
{
    ret->types.types_len = 1;
2493
    if (VIR_ALLOC_N(ret->types.types_val, ret->types.types_len) < 0) {
2494 2495
        remoteDispatchOOMError(rerr);
        return -1;
2496
    }
2497 2498 2499
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
2500
    ret->types.types_val[0] = client->auth;
2501
    virMutexUnlock(&client->lock);
2502

2503 2504 2505 2506 2507 2508 2509 2510
    return 0;
}


#if HAVE_SASL
/*
 * NB, keep in sync with similar method in src/remote_internal.c
 */
2511
static char *addrToString(remote_error *rerr,
2512 2513 2514 2515 2516 2517 2518 2519 2520
                          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) {
2521 2522 2523
        remoteDispatchFormatError(rerr,
                                  _("Cannot resolve address %d: %s"),
                                  err, gai_strerror(err));
2524 2525 2526
        return NULL;
    }

2527
    if (VIR_ALLOC_N(addr, strlen(host) + 1 + strlen(port) + 1) < 0) {
2528
        remoteDispatchOOMError(rerr);
2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540
        return NULL;
    }

    strcpy(addr, host);
    strcat(addr, ";");
    strcat(addr, port);
    return addr;
}


/*
 * Initializes the SASL session in prepare for authentication
2541
 * and gives the client a list of allowed mechanisms to choose
2542 2543 2544 2545
 *
 * XXX callbacks for stuff like password verification ?
 */
static int
2546
remoteDispatchAuthSaslInit (struct qemud_server *server,
2547
                            struct qemud_client *client,
2548
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2549
                            remote_error *rerr,
2550 2551 2552 2553
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret)
{
    const char *mechlist = NULL;
2554
    sasl_security_properties_t secprops;
2555 2556 2557 2558 2559
    int err;
    struct sockaddr_storage sa;
    socklen_t salen;
    char *localAddr, *remoteAddr;

2560 2561 2562
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
2563

2564 2565 2566
    REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn != NULL) {
2567
        VIR_ERROR0(_("client tried invalid SASL init request"));
2568
        goto authfail;
2569 2570 2571 2572 2573
    }

    /* Get local address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getsockname(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
2574
        remoteDispatchFormatError(rerr,
2575 2576
                                  _("failed to get sock address: %s"),
                                  strerror(errno));
2577
        goto error;
2578
    }
2579
    if ((localAddr = addrToString(rerr, &sa, salen)) == NULL) {
2580
        goto error;
2581 2582 2583 2584 2585
    }

    /* Get remote address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getpeername(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
2586 2587
        remoteDispatchFormatError(rerr, _("failed to get peer address: %s"),
                                  strerror(errno));
2588
        VIR_FREE(localAddr);
2589
        goto error;
2590
    }
2591
    if ((remoteAddr = addrToString(rerr, &sa, salen)) == NULL) {
2592
        VIR_FREE(localAddr);
2593
        goto error;
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603
    }

    err = sasl_server_new("libvirt",
                          NULL, /* FQDN - just delegates to gethostname */
                          NULL, /* User realm */
                          localAddr,
                          remoteAddr,
                          NULL, /* XXX Callbacks */
                          SASL_SUCCESS_DATA,
                          &client->saslconn);
2604 2605
    VIR_FREE(localAddr);
    VIR_FREE(remoteAddr);
2606
    if (err != SASL_OK) {
2607 2608
        VIR_ERROR(_("sasl context setup failed %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2609
        client->saslconn = NULL;
2610
        goto authfail;
2611 2612
    }

2613 2614 2615 2616 2617 2618 2619
    /* 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))) {
2620
            VIR_ERROR0(_("cannot TLS get cipher size"));
2621 2622
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
2623
            goto authfail;
2624 2625 2626 2627 2628
        }
        ssf *= 8; /* tls key size is bytes, sasl wants bits */

        err = sasl_setprop(client->saslconn, SASL_SSF_EXTERNAL, &ssf);
        if (err != SASL_OK) {
2629 2630
            VIR_ERROR(_("cannot set SASL external SSF %d (%s)"),
                      err, sasl_errstring(err, NULL, NULL));
2631 2632
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
2633
            goto authfail;
2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656
        }
    }

    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) {
2657 2658
        VIR_ERROR(_("cannot set SASL security props %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2659 2660
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2661
        goto authfail;
2662 2663
    }

2664 2665 2666 2667 2668 2669 2670 2671 2672
    err = sasl_listmech(client->saslconn,
                        NULL, /* Don't need to set user */
                        "", /* Prefix */
                        ",", /* Separator */
                        "", /* Suffix */
                        &mechlist,
                        NULL,
                        NULL);
    if (err != SASL_OK) {
2673 2674
        VIR_ERROR(_("cannot list SASL mechanisms %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
2675 2676
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2677
        goto authfail;
2678 2679 2680 2681
    }
    REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist);
    ret->mechlist = strdup(mechlist);
    if (!ret->mechlist) {
2682
        VIR_ERROR0(_("cannot allocate mechlist"));
2683 2684
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2685
        goto authfail;
2686 2687
    }

2688
    virMutexUnlock(&client->lock);
2689
    return 0;
2690 2691 2692 2693

authfail:
    remoteDispatchAuthError(rerr);
error:
2694
    virMutexUnlock(&client->lock);
2695
    return -1;
2696 2697 2698
}


2699
/* We asked for an SSF layer, so sanity check that we actually
2700 2701 2702
 * got what we asked for */
static int
remoteSASLCheckSSF (struct qemud_client *client,
2703
                    remote_error *rerr) {
2704 2705 2706 2707 2708 2709 2710 2711 2712
    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) {
2713 2714
        VIR_ERROR(_("cannot query SASL ssf on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2715
        remoteDispatchAuthError(rerr);
2716 2717 2718 2719 2720 2721 2722
        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 */
2723
        VIR_ERROR(_("negotiated SSF %d was not strong enough"), ssf);
2724
        remoteDispatchAuthError(rerr);
2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741
        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;
}

2742 2743 2744
static int
remoteSASLCheckAccess (struct qemud_server *server,
                       struct qemud_client *client,
2745
                       remote_error *rerr) {
2746 2747 2748 2749 2750 2751
    const void *val;
    int err;
    char **wildcards;

    err = sasl_getprop(client->saslconn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
2752 2753
        VIR_ERROR(_("cannot query SASL username on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2754
        remoteDispatchAuthError(rerr);
2755 2756 2757 2758 2759
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    if (val == NULL) {
2760
        VIR_ERROR0(_("no client username was found"));
2761
        remoteDispatchAuthError(rerr);
2762 2763 2764 2765 2766 2767 2768 2769
        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) {
2770
        VIR_ERROR0(_("out of memory copying username"));
2771
        remoteDispatchAuthError(rerr);
2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788
        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 */
2789
    VIR_ERROR(_("SASL client %s not allowed in whitelist"), client->saslUsername);
2790
    remoteDispatchAuthError(rerr);
2791 2792 2793 2794 2795 2796
    sasl_dispose(&client->saslconn);
    client->saslconn = NULL;
    return -1;
}


2797 2798 2799 2800
/*
 * This starts the SASL authentication negotiation.
 */
static int
2801 2802
remoteDispatchAuthSaslStart (struct qemud_server *server,
                             struct qemud_client *client,
2803
                             virConnectPtr conn ATTRIBUTE_UNUSED,
2804
                             remote_error *rerr,
2805 2806 2807 2808 2809 2810 2811
                             remote_auth_sasl_start_args *args,
                             remote_auth_sasl_start_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

2812 2813 2814
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
2815

2816 2817 2818
    REMOTE_DEBUG("Start SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
2819
        VIR_ERROR0(_("client tried invalid SASL start request"));
2820
        goto authfail;
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833
    }

    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) {
2834 2835
        VIR_ERROR(_("sasl start failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
2836 2837
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2838
        goto authfail;
2839 2840
    }
    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
2841
        VIR_ERROR(_("sasl start reply data too long %d"), serveroutlen);
2842 2843
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2844
        goto authfail;
2845 2846 2847 2848
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
2849
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
2850
            remoteDispatchOOMError(rerr);
2851
            goto error;
2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863
        }
        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 {
2864
        if (remoteSASLCheckSSF(client, rerr) < 0)
2865
            goto error;
2866

2867
        /* Check username whitelist ACL */
2868
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
2869
            goto error;
2870

2871 2872 2873 2874 2875
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

2876
    virMutexUnlock(&client->lock);
2877
    return 0;
2878 2879 2880 2881

authfail:
    remoteDispatchAuthError(rerr);
error:
2882
    virMutexUnlock(&client->lock);
2883
    return -1;
2884 2885 2886 2887
}


static int
2888 2889
remoteDispatchAuthSaslStep (struct qemud_server *server,
                            struct qemud_client *client,
2890
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2891
                            remote_error *rerr,
2892 2893 2894 2895 2896 2897 2898
                            remote_auth_sasl_step_args *args,
                            remote_auth_sasl_step_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

2899 2900 2901
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
2902

2903 2904 2905
    REMOTE_DEBUG("Step SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
2906
        VIR_ERROR0(_("client tried invalid SASL start request"));
2907
        goto authfail;
2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919
    }

    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) {
2920 2921
        VIR_ERROR(_("sasl step failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
2922 2923
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2924
        goto authfail;
2925 2926 2927
    }

    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
2928 2929
        VIR_ERROR(_("sasl step reply data too long %d"),
                  serveroutlen);
2930 2931
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2932
        goto authfail;
2933 2934 2935 2936
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
2937
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
2938
            remoteDispatchOOMError(rerr);
2939
            goto error;
2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951
        }
        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 {
2952
        if (remoteSASLCheckSSF(client, rerr) < 0)
2953
            goto error;
2954

2955
        /* Check username whitelist ACL */
2956
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
2957
            goto error;
2958

2959 2960 2961 2962 2963
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

2964
    virMutexUnlock(&client->lock);
2965
    return 0;
2966 2967 2968 2969

authfail:
    remoteDispatchAuthError(rerr);
error:
2970
    virMutexUnlock(&client->lock);
2971
    return -1;
2972 2973 2974 2975 2976
}


#else /* HAVE_SASL */
static int
2977
remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED,
2978 2979
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2980
                            remote_error *rerr,
2981 2982 2983
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED)
{
2984
    VIR_ERROR0(_("client tried unsupported SASL init request"));
2985
    remoteDispatchAuthError(rerr);
2986 2987 2988 2989
    return -1;
}

static int
2990
remoteDispatchAuthSaslStart (struct qemud_server *server ATTRIBUTE_UNUSED,
2991 2992
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn ATTRIBUTE_UNUSED,
2993
                             remote_error *rerr,
2994 2995 2996
                             remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED,
                             remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED)
{
2997
    VIR_ERROR0(_("client tried unsupported SASL start request"));
2998
    remoteDispatchAuthError(rerr);
2999 3000 3001 3002
    return -1;
}

static int
3003
remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
3004 3005
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3006
                            remote_error *rerr,
3007 3008 3009
                            remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED)
{
3010
    VIR_ERROR0(_("client tried unsupported SASL step request"));
3011
    remoteDispatchAuthError(rerr);
3012 3013 3014 3015 3016
    return -1;
}
#endif /* HAVE_SASL */


3017 3018
#if HAVE_POLKIT
static int
3019
remoteDispatchAuthPolkit (struct qemud_server *server,
3020
                          struct qemud_client *client,
3021
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3022
                          remote_error *rerr,
3023 3024 3025 3026 3027
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
    pid_t callerPid;
    uid_t callerUid;
3028 3029 3030 3031 3032 3033
    PolKitCaller *pkcaller = NULL;
    PolKitAction *pkaction = NULL;
    PolKitContext *pkcontext = NULL;
    PolKitError *pkerr = NULL;
    PolKitResult pkresult;
    DBusError err;
3034 3035
    const char *action;

3036 3037 3038
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3039 3040

    action = client->readonly ?
3041 3042
        "org.libvirt.unix.monitor" :
        "org.libvirt.unix.manage";
3043 3044 3045

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

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

3055
    VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
3056 3057 3058
    dbus_error_init(&err);
    if (!(pkcaller = polkit_caller_new_from_pid(server->sysbus,
                                                callerPid, &err))) {
3059
        VIR_ERROR(_("Failed to lookup policy kit caller: %s"), err.message);
3060
        dbus_error_free(&err);
3061
        goto authfail;
3062
    }
3063

3064
    if (!(pkaction = polkit_action_new())) {
3065
        VIR_ERROR(_("Failed to create polkit action %s\n"), strerror(errno));
3066
        polkit_caller_unref(pkcaller);
3067
        goto authfail;
3068 3069 3070 3071 3072
    }
    polkit_action_set_action_id(pkaction, action);

    if (!(pkcontext = polkit_context_new()) ||
        !polkit_context_init(pkcontext, &pkerr)) {
3073 3074 3075
        VIR_ERROR(_("Failed to create polkit context %s\n"),
                  (pkerr ? polkit_error_get_error_message(pkerr)
                   : strerror(errno)));
3076 3077 3078 3079 3080
        if (pkerr)
            polkit_error_free(pkerr);
        polkit_caller_unref(pkcaller);
        polkit_action_unref(pkaction);
        dbus_error_free(&err);
3081
        goto authfail;
3082
    }
3083

3084
#if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
3085 3086 3087 3088 3089 3090
    pkresult = polkit_context_is_caller_authorized(pkcontext,
                                                   pkaction,
                                                   pkcaller,
                                                   0,
                                                   &pkerr);
    if (pkerr && polkit_error_is_set(pkerr)) {
3091 3092 3093
        VIR_ERROR(_("Policy kit failed to check authorization %d %s"),
                  polkit_error_get_error_code(pkerr),
                  polkit_error_get_error_message(pkerr));
3094
        goto authfail;
3095
    }
3096
#else
3097 3098 3099
    pkresult = polkit_context_can_caller_do_action(pkcontext,
                                                   pkaction,
                                                   pkcaller);
3100
#endif
3101 3102 3103 3104
    polkit_context_unref(pkcontext);
    polkit_caller_unref(pkcaller);
    polkit_action_unref(pkaction);
    if (pkresult != POLKIT_RESULT_YES) {
3105 3106 3107
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %s\n"),
                  action, callerPid, callerUid,
                  polkit_result_to_string_representation(pkresult));
3108
        goto authfail;
3109
    }
3110
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d, result %s"),
3111 3112 3113 3114
             action, callerPid, callerUid,
             polkit_result_to_string_representation(pkresult));
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;
3115

3116
    virMutexUnlock(&client->lock);
3117
    return 0;
3118 3119 3120

authfail:
    remoteDispatchAuthError(rerr);
3121
    virMutexUnlock(&client->lock);
3122
    return -1;
3123 3124 3125 3126 3127
}

#else /* HAVE_POLKIT */

static int
3128
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
3129
                          struct qemud_client *client ATTRIBUTE_UNUSED,
3130
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3131 3132 3133
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED)
3134
{
3135
    VIR_ERROR0(_("client tried unsupported PolicyKit init request"));
3136
    remoteDispatchAuthError(rerr);
3137 3138 3139 3140
    return -1;
}
#endif /* HAVE_POLKIT */

3141 3142 3143 3144 3145 3146 3147 3148

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


static int
remoteDispatchListDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3149 3150
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3151
                                       remote_error *rerr,
3152 3153 3154 3155 3156
                                       remote_list_defined_storage_pools_args *args,
                                       remote_list_defined_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
3157 3158
        remoteDispatchFormatError (rerr, "%s",
                            _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
3159
        return -1;
3160 3161 3162
    }

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

    ret->names.names_len =
3169
        virConnectListDefinedStoragePools (conn,
3170 3171 3172
                                           ret->names.names_val, args->maxnames);
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3173
        remoteDispatchConnError(rerr, conn);
3174 3175
        return -1;
    }
3176 3177 3178 3179 3180 3181

    return 0;
}

static int
remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3182 3183
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3184
                                remote_error *rerr,
3185 3186 3187 3188 3189
                                remote_list_storage_pools_args *args,
                                remote_list_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
3190 3191 3192
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX"));
        return -1;
3193 3194 3195
    }

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

    ret->names.names_len =
3202
        virConnectListStoragePools (conn,
3203
                                ret->names.names_val, args->maxnames);
3204 3205
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3206
        remoteDispatchConnError(rerr, conn);
3207 3208
        return -1;
    }
3209 3210 3211 3212

    return 0;
}

3213 3214
static int
remoteDispatchFindStoragePoolSources (struct qemud_server *server ATTRIBUTE_UNUSED,
3215 3216
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3217
                                      remote_error *rerr,
3218 3219 3220 3221
                                      remote_find_storage_pool_sources_args *args,
                                      remote_find_storage_pool_sources_ret *ret)
{
    ret->xml =
3222
        virConnectFindStoragePoolSources (conn,
3223 3224 3225
                                          args->type,
                                          args->srcSpec ? *args->srcSpec : NULL,
                                          args->flags);
3226
    if (ret->xml == NULL) {
3227
        remoteDispatchConnError(rerr, conn);
3228
        return -1;
3229
    }
3230 3231 3232 3233 3234

    return 0;
}


3235 3236
static int
remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
3237 3238
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3239
                                 remote_error *rerr,
3240 3241 3242 3243 3244
                                 remote_storage_pool_create_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3245
    pool = get_nonnull_storage_pool (conn, args->pool);
3246
    if (pool == NULL) {
3247
        remoteDispatchConnError(rerr, conn);
3248
        return -1;
3249 3250 3251 3252
    }

    if (virStoragePoolCreate (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3253
        remoteDispatchConnError(rerr, conn);
3254 3255 3256 3257 3258 3259 3260 3261
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3262 3263
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3264
                                    remote_error *rerr,
3265 3266 3267 3268 3269
                                    remote_storage_pool_create_xml_args *args,
                                    remote_storage_pool_create_xml_ret *ret)
{
    virStoragePoolPtr pool;

3270
    pool = virStoragePoolCreateXML (conn, args->xml, args->flags);
3271
    if (pool == NULL) {
3272
        remoteDispatchConnError(rerr, conn);
3273 3274
        return -1;
    }
3275 3276 3277 3278 3279 3280 3281 3282

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

static int
remoteDispatchStoragePoolDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3283 3284
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3285
                                    remote_error *rerr,
3286 3287 3288 3289 3290
                                    remote_storage_pool_define_xml_args *args,
                                    remote_storage_pool_define_xml_ret *ret)
{
    virStoragePoolPtr pool;

3291
    pool = virStoragePoolDefineXML (conn, args->xml, args->flags);
3292
    if (pool == NULL) {
3293
        remoteDispatchConnError(rerr, conn);
3294 3295
        return -1;
    }
3296 3297 3298 3299 3300 3301 3302 3303

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

static int
remoteDispatchStoragePoolBuild (struct qemud_server *server ATTRIBUTE_UNUSED,
3304 3305
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3306 3307 3308
                                remote_error *rerr,
                                remote_storage_pool_build_args *args,
                                void *ret ATTRIBUTE_UNUSED)
3309 3310 3311
{
    virStoragePoolPtr pool;

3312
    pool = get_nonnull_storage_pool (conn, args->pool);
3313
    if (pool == NULL) {
3314
        remoteDispatchConnError(rerr, conn);
3315
        return -1;
3316 3317 3318 3319
    }

    if (virStoragePoolBuild (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3320
        remoteDispatchConnError(rerr, conn);
3321 3322 3323 3324 3325 3326 3327 3328 3329
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
3330 3331
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3332
                                  remote_error *rerr,
3333 3334 3335 3336 3337
                                  remote_storage_pool_destroy_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3338
    pool = get_nonnull_storage_pool (conn, args->pool);
3339
    if (pool == NULL) {
3340
        remoteDispatchConnError(rerr, conn);
3341
        return -1;
3342 3343 3344 3345
    }

    if (virStoragePoolDestroy (pool) == -1) {
        virStoragePoolFree(pool);
3346
        remoteDispatchConnError(rerr, conn);
3347 3348 3349 3350 3351 3352 3353 3354
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
3355 3356
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3357
                                 remote_error *rerr,
3358 3359 3360 3361 3362
                                 remote_storage_pool_delete_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3363
    pool = get_nonnull_storage_pool (conn, args->pool);
3364
    if (pool == NULL) {
3365
        remoteDispatchConnError(rerr, conn);
3366
        return -1;
3367 3368 3369 3370
    }

    if (virStoragePoolDelete (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3371
        remoteDispatchConnError(rerr, conn);
3372 3373 3374 3375 3376 3377 3378 3379
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolRefresh (struct qemud_server *server ATTRIBUTE_UNUSED,
3380 3381
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3382
                                  remote_error *rerr,
3383 3384 3385 3386 3387
                                  remote_storage_pool_refresh_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3388
    pool = get_nonnull_storage_pool (conn, args->pool);
3389
    if (pool == NULL) {
3390
        remoteDispatchConnError(rerr, conn);
3391
        return -1;
3392 3393 3394 3395
    }

    if (virStoragePoolRefresh (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3396
        remoteDispatchConnError(rerr, conn);
3397 3398 3399 3400 3401 3402 3403 3404
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
3405 3406
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3407
                                  remote_error *rerr,
3408 3409 3410 3411 3412 3413
                                  remote_storage_pool_get_info_args *args,
                                  remote_storage_pool_get_info_ret *ret)
{
    virStoragePoolPtr pool;
    virStoragePoolInfo info;

3414
    pool = get_nonnull_storage_pool (conn, args->pool);
3415
    if (pool == NULL) {
3416
        remoteDispatchConnError(rerr, conn);
3417
        return -1;
3418 3419 3420 3421
    }

    if (virStoragePoolGetInfo (pool, &info) == -1) {
        virStoragePoolFree(pool);
3422
        remoteDispatchConnError(rerr, conn);
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437
        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,
3438 3439
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3440
                                  remote_error *rerr,
3441 3442 3443 3444 3445
                                  remote_storage_pool_dump_xml_args *args,
                                  remote_storage_pool_dump_xml_ret *ret)
{
    virStoragePoolPtr pool;

3446
    pool = get_nonnull_storage_pool (conn, args->pool);
3447
    if (pool == NULL) {
3448
        remoteDispatchConnError(rerr, conn);
3449
        return -1;
3450 3451 3452 3453 3454 3455
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStoragePoolGetXMLDesc (pool, args->flags);
    if (!ret->xml) {
        virStoragePoolFree(pool);
3456
        remoteDispatchConnError(rerr, conn);
3457 3458 3459 3460 3461 3462 3463 3464
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
3465 3466
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3467
                                       remote_error *rerr,
3468 3469 3470 3471 3472
                                       remote_storage_pool_get_autostart_args *args,
                                       remote_storage_pool_get_autostart_ret *ret)
{
    virStoragePoolPtr pool;

3473
    pool = get_nonnull_storage_pool (conn, args->pool);
3474
    if (pool == NULL) {
3475
        remoteDispatchConnError(rerr, conn);
3476
        return -1;
3477 3478 3479 3480
    }

    if (virStoragePoolGetAutostart (pool, &ret->autostart) == -1) {
        virStoragePoolFree(pool);
3481
        remoteDispatchConnError(rerr, conn);
3482 3483 3484 3485 3486 3487 3488 3489 3490
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
3491 3492
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3493
                                       remote_error *rerr,
3494 3495 3496 3497 3498
                                       remote_storage_pool_lookup_by_name_args *args,
                                       remote_storage_pool_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;

3499
    pool = virStoragePoolLookupByName (conn, args->name);
3500
    if (pool == NULL) {
3501
        remoteDispatchConnError(rerr, conn);
3502 3503
        return -1;
    }
3504 3505 3506 3507 3508 3509 3510 3511

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

static int
remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
3512 3513
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3514
                                       remote_error *rerr,
3515 3516 3517 3518 3519
                                       remote_storage_pool_lookup_by_uuid_args *args,
                                       remote_storage_pool_lookup_by_uuid_ret *ret)
{
    virStoragePoolPtr pool;

3520
    pool = virStoragePoolLookupByUUID (conn, (unsigned char *) args->uuid);
3521
    if (pool == NULL) {
3522
        remoteDispatchConnError(rerr, conn);
3523 3524
        return -1;
    }
3525 3526 3527 3528 3529 3530 3531 3532

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

static int
remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server ATTRIBUTE_UNUSED,
3533 3534
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
3535
                                         remote_error *rerr,
3536 3537 3538 3539 3540 3541
                                         remote_storage_pool_lookup_by_volume_args *args,
                                         remote_storage_pool_lookup_by_volume_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

3542
    vol = get_nonnull_storage_vol (conn, args->vol);
3543
    if (vol == NULL) {
3544
        remoteDispatchConnError(rerr, conn);
3545 3546
        return -1;
    }
3547 3548 3549

    pool = virStoragePoolLookupByVolume (vol);
    virStorageVolFree(vol);
3550
    if (pool == NULL) {
3551
        remoteDispatchConnError(rerr, conn);
3552 3553
        return -1;
    }
3554 3555 3556 3557 3558 3559 3560 3561

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

static int
remoteDispatchStoragePoolSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
3562 3563
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3564
                                       remote_error *rerr,
3565 3566 3567 3568 3569
                                       remote_storage_pool_set_autostart_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3570
    pool = get_nonnull_storage_pool (conn, args->pool);
3571
    if (pool == NULL) {
3572
        remoteDispatchConnError(rerr, conn);
3573
        return -1;
3574 3575 3576 3577
    }

    if (virStoragePoolSetAutostart (pool, args->autostart) == -1) {
        virStoragePoolFree(pool);
3578
        remoteDispatchConnError(rerr, conn);
3579 3580 3581 3582 3583 3584 3585 3586
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
3587 3588
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
3589
                                   remote_error *rerr,
3590 3591 3592 3593 3594
                                   remote_storage_pool_undefine_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3595
    pool = get_nonnull_storage_pool (conn, args->pool);
3596
    if (pool == NULL) {
3597
        remoteDispatchConnError(rerr, conn);
3598
        return -1;
3599 3600 3601 3602
    }

    if (virStoragePoolUndefine (pool) == -1) {
        virStoragePoolFree(pool);
3603
        remoteDispatchConnError(rerr, conn);
3604 3605 3606 3607 3608 3609 3610 3611
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchNumOfStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3612 3613
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3614
                                 remote_error *rerr,
3615 3616 3617 3618
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_num_of_storage_pools_ret *ret)
{

3619
    ret->num = virConnectNumOfStoragePools (conn);
3620
    if (ret->num == -1) {
3621
        remoteDispatchConnError(rerr, conn);
3622 3623
        return -1;
    }
3624 3625 3626 3627 3628 3629

    return 0;
}

static int
remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3630 3631
                                        struct qemud_client *client ATTRIBUTE_UNUSED,
                                        virConnectPtr conn,
3632
                                        remote_error *rerr,
3633 3634 3635 3636
                                        void *args ATTRIBUTE_UNUSED,
                                        remote_num_of_defined_storage_pools_ret *ret)
{

3637
    ret->num = virConnectNumOfDefinedStoragePools (conn);
3638
    if (ret->num == -1) {
3639
        remoteDispatchConnError(rerr, conn);
3640 3641
        return -1;
    }
3642 3643 3644 3645 3646 3647

    return 0;
}

static int
remoteDispatchStoragePoolListVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
3648 3649
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3650
                                      remote_error *rerr,
3651 3652 3653 3654 3655 3656
                                      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) {
3657 3658 3659
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX"));
        return -1;
3660 3661
    }

3662
    pool = get_nonnull_storage_pool (conn, args->pool);
3663
    if (pool == NULL) {
3664
        remoteDispatchConnError(rerr, conn);
3665
        return -1;
3666 3667 3668
    }

    /* Allocate return buffer. */
3669 3670
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        virStoragePoolFree(pool);
3671 3672
        remoteDispatchOOMError(rerr);
        return -1;
3673
    }
3674 3675 3676 3677 3678

    ret->names.names_len =
        virStoragePoolListVolumes (pool,
                                   ret->names.names_val, args->maxnames);
    virStoragePoolFree(pool);
3679 3680
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3681
        remoteDispatchConnError(rerr, conn);
3682 3683
        return -1;
    }
3684 3685 3686 3687 3688 3689 3690

    return 0;
}


static int
remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
3691 3692
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3693
                                       remote_error *rerr,
3694 3695 3696 3697 3698
                                       remote_storage_pool_num_of_volumes_args *args,
                                       remote_storage_pool_num_of_volumes_ret *ret)
{
    virStoragePoolPtr pool;

3699
    pool = get_nonnull_storage_pool (conn, args->pool);
3700
    if (pool == NULL) {
3701
        remoteDispatchConnError(rerr, conn);
3702
        return -1;
3703 3704 3705 3706
    }

    ret->num = virStoragePoolNumOfVolumes (pool);
    virStoragePoolFree(pool);
3707
    if (ret->num == -1) {
3708
        remoteDispatchConnError(rerr, conn);
3709 3710
        return -1;
    }
3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723

    return 0;
}


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



static int
remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3724 3725
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
3726
                                   remote_error *rerr,
3727 3728 3729 3730 3731 3732
                                   remote_storage_vol_create_xml_args *args,
                                   remote_storage_vol_create_xml_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

3733
    pool = get_nonnull_storage_pool (conn, args->pool);
3734
    if (pool == NULL) {
3735
        remoteDispatchConnError(rerr, conn);
3736
        return -1;
3737 3738 3739 3740
    }

    vol = virStorageVolCreateXML (pool, args->xml, args->flags);
    virStoragePoolFree(pool);
3741
    if (vol == NULL) {
3742
        remoteDispatchConnError(rerr, conn);
3743 3744
        return -1;
    }
3745 3746 3747 3748 3749 3750 3751 3752 3753

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


static int
remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
3754 3755
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3756
                                remote_error *rerr,
3757 3758 3759 3760 3761
                                remote_storage_vol_delete_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virStorageVolPtr vol;

3762
    vol = get_nonnull_storage_vol (conn, args->vol);
3763
    if (vol == NULL) {
3764
        remoteDispatchConnError(rerr, conn);
3765
        return -1;
3766 3767 3768 3769
    }

    if (virStorageVolDelete (vol, args->flags) == -1) {
        virStorageVolFree(vol);
3770
        remoteDispatchConnError(rerr, conn);
3771 3772 3773 3774 3775 3776 3777 3778
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}

static int
remoteDispatchStorageVolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
3779 3780
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3781
                                 remote_error *rerr,
3782 3783 3784 3785 3786 3787
                                 remote_storage_vol_get_info_args *args,
                                 remote_storage_vol_get_info_ret *ret)
{
    virStorageVolPtr vol;
    virStorageVolInfo info;

3788
    vol = get_nonnull_storage_vol (conn, args->vol);
3789
    if (vol == NULL) {
3790
        remoteDispatchConnError(rerr, conn);
3791
        return -1;
3792 3793 3794 3795
    }

    if (virStorageVolGetInfo (vol, &info) == -1) {
        virStorageVolFree(vol);
3796
        remoteDispatchConnError(rerr, conn);
3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810
        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,
3811 3812
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3813
                                 remote_error *rerr,
3814 3815 3816 3817 3818
                                 remote_storage_vol_dump_xml_args *args,
                                 remote_storage_vol_dump_xml_ret *ret)
{
    virStorageVolPtr vol;

3819
    vol = get_nonnull_storage_vol (conn, args->vol);
3820
    if (vol == NULL) {
3821
        remoteDispatchConnError(rerr, conn);
3822
        return -1;
3823 3824 3825 3826 3827 3828
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStorageVolGetXMLDesc (vol, args->flags);
    if (!ret->xml) {
        virStorageVolFree(vol);
3829
        remoteDispatchConnError(rerr, conn);
3830 3831 3832 3833 3834 3835 3836 3837 3838
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolGetPath (struct qemud_server *server ATTRIBUTE_UNUSED,
3839 3840
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3841
                                 remote_error *rerr,
3842 3843 3844 3845 3846
                                 remote_storage_vol_get_path_args *args,
                                 remote_storage_vol_get_path_ret *ret)
{
    virStorageVolPtr vol;

3847
    vol = get_nonnull_storage_vol (conn, args->vol);
3848
    if (vol == NULL) {
3849
        remoteDispatchConnError(rerr, conn);
3850
        return -1;
3851 3852 3853 3854 3855 3856
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virStorageVolGetPath (vol);
    if (!ret->name) {
        virStorageVolFree(vol);
3857
        remoteDispatchConnError(rerr, conn);
3858 3859 3860 3861 3862 3863 3864 3865 3866
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
3867 3868
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3869
                                      remote_error *rerr,
3870 3871 3872 3873 3874 3875
                                      remote_storage_vol_lookup_by_name_args *args,
                                      remote_storage_vol_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

3876
    pool = get_nonnull_storage_pool (conn, args->pool);
3877
    if (pool == NULL) {
3878
        remoteDispatchConnError(rerr, conn);
3879
        return -1;
3880 3881 3882 3883
    }

    vol = virStorageVolLookupByName (pool, args->name);
    virStoragePoolFree(pool);
3884
    if (vol == NULL) {
3885
        remoteDispatchConnError(rerr, conn);
3886 3887
        return -1;
    }
3888 3889 3890 3891 3892 3893 3894 3895

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

static int
remoteDispatchStorageVolLookupByKey (struct qemud_server *server ATTRIBUTE_UNUSED,
3896 3897
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
3898
                                     remote_error *rerr,
3899 3900 3901 3902 3903
                                     remote_storage_vol_lookup_by_key_args *args,
                                     remote_storage_vol_lookup_by_key_ret *ret)
{
    virStorageVolPtr vol;

3904
    vol = virStorageVolLookupByKey (conn, args->key);
3905
    if (vol == NULL) {
3906
        remoteDispatchConnError(rerr, conn);
3907 3908
        return -1;
    }
3909 3910 3911 3912 3913 3914 3915 3916 3917

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


static int
remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUSED,
3918 3919
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3920
                                      remote_error *rerr,
3921 3922 3923 3924 3925
                                      remote_storage_vol_lookup_by_path_args *args,
                                      remote_storage_vol_lookup_by_path_ret *ret)
{
    virStorageVolPtr vol;

3926
    vol = virStorageVolLookupByPath (conn, args->path);
3927
    if (vol == NULL) {
3928
        remoteDispatchConnError(rerr, conn);
3929 3930
        return -1;
    }
3931 3932 3933 3934 3935 3936 3937

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


3938 3939 3940 3941 3942 3943
/***************************************************************
 *     NODE INFO APIS
 **************************************************************/

static int
remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
3944 3945
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3946
                                remote_error *rerr,
3947 3948 3949 3950 3951
                                remote_node_num_of_devices_args *args,
                                remote_node_num_of_devices_ret *ret)
{
    CHECK_CONN(client);

3952
    ret->num = virNodeNumOfDevices (conn,
3953 3954
                                    args->cap ? *args->cap : NULL,
                                    args->flags);
3955
    if (ret->num == -1) {
3956
        remoteDispatchConnError(rerr, conn);
3957 3958
        return -1;
    }
3959 3960 3961 3962 3963 3964 3965

    return 0;
}


static int
remoteDispatchNodeListDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
3966 3967
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
3968
                               remote_error *rerr,
3969 3970 3971 3972 3973 3974
                               remote_node_list_devices_args *args,
                               remote_node_list_devices_ret *ret)
{
    CHECK_CONN(client);

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
3975 3976 3977
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
3978 3979 3980 3981
    }

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

    ret->names.names_len =
3987
        virNodeListDevices (conn,
3988 3989 3990
                            args->cap ? *args->cap : NULL,
                            ret->names.names_val, args->maxnames, args->flags);
    if (ret->names.names_len == -1) {
3991
        remoteDispatchConnError(rerr, conn);
3992 3993 3994 3995 3996 3997 3998 3999 4000 4001
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4002 4003
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4004
                                      remote_error *rerr,
4005 4006 4007 4008 4009 4010 4011
                                      remote_node_device_lookup_by_name_args *args,
                                      remote_node_device_lookup_by_name_ret *ret)
{
    virNodeDevicePtr dev;

    CHECK_CONN(client);

4012
    dev = virNodeDeviceLookupByName (conn, args->name);
4013
    if (dev == NULL) {
4014
        remoteDispatchConnError(rerr, conn);
4015 4016
        return -1;
    }
4017 4018 4019 4020 4021 4022 4023 4024 4025

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


static int
remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4026 4027
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4028
                                 remote_error *rerr,
4029 4030 4031 4032 4033 4034
                                 remote_node_device_dump_xml_args *args,
                                 remote_node_device_dump_xml_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4035
    dev = virNodeDeviceLookupByName(conn, args->name);
4036
    if (dev == NULL) {
4037 4038
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4039 4040 4041 4042 4043
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags);
    if (!ret->xml) {
4044
        remoteDispatchConnError(rerr, conn);
4045 4046 4047 4048 4049 4050 4051 4052 4053 4054
        virNodeDeviceFree(dev);
        return -1;
    }
    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED,
4055 4056
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4057
                                   remote_error *rerr,
4058 4059 4060 4061 4062 4063 4064
                                   remote_node_device_get_parent_args *args,
                                   remote_node_device_get_parent_ret *ret)
{
    virNodeDevicePtr dev;
    const char *parent;
    CHECK_CONN(client);

4065
    dev = virNodeDeviceLookupByName(conn, args->name);
4066
    if (dev == NULL) {
4067 4068
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4069 4070 4071 4072 4073 4074 4075 4076 4077 4078
    }

    parent = virNodeDeviceGetParent(dev);

    if (parent == NULL) {
        ret->parent = NULL;
    } else {
        /* remoteDispatchClientRequest will free this. */
        char **parent_p;
        if (VIR_ALLOC(parent_p) < 0) {
4079 4080
            remoteDispatchOOMError(rerr);
            return -1;
4081 4082 4083
        }
        *parent_p = strdup(parent);
        if (*parent_p == NULL) {
4084 4085
            remoteDispatchOOMError(rerr);
            return -1;
4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096
        }
        ret->parent = parent_p;
    }

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4097 4098
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4099
                                   remote_error *rerr,
4100 4101 4102 4103 4104 4105
                                   remote_node_device_num_of_caps_args *args,
                                   remote_node_device_num_of_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4106
    dev = virNodeDeviceLookupByName(conn, args->name);
4107
    if (dev == NULL) {
4108 4109
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4110 4111 4112
    }

    ret->num = virNodeDeviceNumOfCaps(dev);
4113
    if (ret->num < 0) {
4114
        remoteDispatchConnError(rerr, conn);
4115 4116
        return -1;
    }
4117 4118 4119 4120 4121 4122 4123 4124

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4125 4126
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4127
                                  remote_error *rerr,
4128 4129 4130 4131 4132 4133
                                  remote_node_device_list_caps_args *args,
                                  remote_node_device_list_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4134
    dev = virNodeDeviceLookupByName(conn, args->name);
4135
    if (dev == NULL) {
4136 4137
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4138 4139 4140
    }

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
4141 4142 4143
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
4144 4145 4146 4147
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
4148 4149
        remoteDispatchOOMError(rerr);
        return -1;
4150 4151 4152 4153 4154 4155
    }

    ret->names.names_len =
        virNodeDeviceListCaps (dev, ret->names.names_val,
                               args->maxnames);
    if (ret->names.names_len == -1) {
4156
        remoteDispatchConnError(rerr, conn);
4157 4158 4159 4160 4161 4162 4163 4164
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


4165 4166 4167 4168 4169 4170
/**************************
 * Async Events
 **************************/
static int
remoteDispatchDomainEvent (struct qemud_server *server ATTRIBUTE_UNUSED,
                           struct qemud_client *client ATTRIBUTE_UNUSED,
4171
                           virConnectPtr conn ATTRIBUTE_UNUSED,
4172
                           remote_error *rerr ATTRIBUTE_UNUSED,
4173 4174 4175 4176 4177 4178 4179
                           void *args ATTRIBUTE_UNUSED,
                           remote_domain_event_ret *ret ATTRIBUTE_UNUSED)
{
    /* This call gets dispatched from a client call.
     * This does not make sense, as this should not be intiated
     * from the client side in generated code.
     */
4180 4181
    remoteDispatchFormatError(rerr, "%s", _("unexpected async event method call"));
    return -1;
4182 4183 4184 4185 4186 4187 4188
}

/***************************
 * Register / deregister events
 ***************************/
static int
remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED,
4189 4190
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
4191
                                    remote_error *rerr ATTRIBUTE_UNUSED,
4192 4193 4194 4195 4196 4197 4198
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_domain_events_register_ret *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);

    /* Register event delivery callback */
    REMOTE_DEBUG("%s","Registering to relay remote events");
4199
    virConnectDomainEventRegister(conn, remoteRelayDomainEvent, client, NULL);
4200 4201 4202 4203 4204 4205 4206 4207

    if(ret)
        ret->cb_registered = 1;
    return 0;
}

static int
remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED,
4208 4209
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4210
                                      remote_error *rerr ATTRIBUTE_UNUSED,
4211 4212 4213 4214 4215 4216 4217
                                      void *args ATTRIBUTE_UNUSED,
                                      remote_domain_events_deregister_ret *ret ATTRIBUTE_UNUSED)
{
    CHECK_CONN(client);

    /* Deregister event delivery callback */
    REMOTE_DEBUG("%s","Deregistering to relay remote events");
4218
    virConnectDomainEventDeregister(conn, remoteRelayDomainEvent);
4219 4220 4221 4222 4223 4224 4225 4226

    if(ret)
        ret->cb_registered = 0;
    return 0;
}

static void
remoteDispatchDomainEventSend (struct qemud_client *client,
4227
                               struct qemud_client_message *msg,
4228 4229 4230
                               virDomainPtr dom,
                               int event,
                               int detail)
4231 4232 4233
{
    remote_message_header rep;
    XDR xdr;
4234
    unsigned int len;
4235 4236
    remote_domain_event_ret data;

4237
    if (!client)
4238 4239 4240 4241 4242 4243 4244 4245 4246 4247
        return;

    rep.prog = REMOTE_PROGRAM;
    rep.vers = REMOTE_PROTOCOL_VERSION;
    rep.proc = REMOTE_PROC_DOMAIN_EVENT;
    rep.direction = REMOTE_MESSAGE;
    rep.serial = 1;
    rep.status = REMOTE_OK;

    /* Serialise the return header and event. */
4248
    xdrmem_create (&xdr, msg->buffer, sizeof msg->buffer, XDR_ENCODE);
4249 4250

    len = 0; /* We'll come back and write this later. */
4251 4252
    if (!xdr_u_int (&xdr, &len)) {
        /*remoteDispatchError (client, NULL, "%s", _("xdr_u_int failed (1)"));*/
4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263
        xdr_destroy (&xdr);
        return;
    }

    if (!xdr_remote_message_header (&xdr, &rep)) {
        xdr_destroy (&xdr);
        return;
    }

    /* build return data */
    make_nonnull_domain (&data.dom, dom);
4264 4265
    data.event = event;
    data.detail = detail;
4266 4267

    if (!xdr_remote_domain_event_ret(&xdr, &data)) {
4268
        /*remoteDispatchError (client, NULL, "%s", _("serialise return struct"));*/
4269 4270 4271 4272 4273 4274
        xdr_destroy (&xdr);
        return;
    }

    len = xdr_getpos (&xdr);
    if (xdr_setpos (&xdr, 0) == 0) {
4275
        /*remoteDispatchError (client, NULL, "%s", _("xdr_setpos failed"));*/
4276 4277 4278 4279
        xdr_destroy (&xdr);
        return;
    }

4280 4281
    if (!xdr_u_int (&xdr, &len)) {
        /*remoteDispatchError (client, NULL, "%s", _("xdr_u_int failed (2)"));*/
4282 4283 4284 4285 4286 4287 4288
        xdr_destroy (&xdr);
        return;
    }

    xdr_destroy (&xdr);

    /* Send it. */
4289 4290 4291 4292
    msg->async = 1;
    msg->bufferLength = len;
    msg->bufferOffset = 0;
    qemudClientMessageQueuePush(&client->tx, msg);
4293
}
4294

4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320
/*----- 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);
}

4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334
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;
}

4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350
/* 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);
}

4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364
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);
}
4365 4366 4367 4368 4369 4370

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