remote.c 135.3 KB
Newer Older
1 2 3
/*
 * remote.c: code handling remote requests (from remote_internal.c)
 *
4
 * Copyright (C) 2007, 2008 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 114
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
                               virDomainPtr dom,
115 116
                               int event,
                               int detail);
117

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

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


215 216 217
/* 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).
218 219 220
 *
 * Server object is unlocked
 * Client object is locked
221
 */
222
unsigned int
223
remoteDispatchClientRequest (struct qemud_server *server,
224 225 226 227
                             struct qemud_client *client)
{
    XDR xdr;
    remote_message_header req, rep;
228
    remote_error rerr;
229 230 231
    dispatch_args args;
    dispatch_ret ret;
    const dispatch_data *data = NULL;
232
    int rv = -1, len;
233
    virConnectPtr conn = NULL;
234

235 236
    memset(&args, 0, sizeof args);
    memset(&ret, 0, sizeof ret);
237
    memset(&rerr, 0, sizeof rerr);
238 239

    /* Parse the header. */
240
    xdrmem_create (&xdr, client->buffer, client->bufferLength, XDR_DECODE);
241

242 243
    if (!xdr_remote_message_header (&xdr, &req))
        goto fatal_error;
244 245 246

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

269 270 271 272 273 274 275
    /* 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 &&
276 277
            req.proc != REMOTE_PROC_AUTH_SASL_STEP &&
            req.proc != REMOTE_PROC_AUTH_POLKIT
278
            ) {
279 280 281 282 283
            /* 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;
284 285 286
        }
    }

287 288
    if (req.proc >= ARRAY_CARDINALITY(dispatch_table) ||
        dispatch_table[req.proc].fn == NULL) {
289 290 291
        remoteDispatchFormatError (&rerr, _("unknown procedure: %d"),
                                   req.proc);
        goto rpc_error;
292 293
    }

294 295 296 297
    data = &(dispatch_table[req.proc]);

    /* De-serialize args off the wire */
    if (!((data->args_filter)(&xdr, &args))) {
298 299
        remoteDispatchFormatError (&rerr, "%s", _("parse args failed"));
        goto rpc_error;
300 301 302
    }

    /* Call function. */
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
    conn = client->conn;
    pthread_mutex_unlock(&client->lock);

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

    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);

322
    xdr_free (data->args_filter, (char*)&args);
323

324 325
rpc_error:
    xdr_destroy (&xdr);
326 327 328 329 330 331 332

    /* Return header. */
    rep.prog = req.prog;
    rep.vers = req.vers;
    rep.proc = req.proc;
    rep.direction = REMOTE_REPLY;
    rep.serial = req.serial;
333
    rep.status = rv < 0 ? REMOTE_ERROR : REMOTE_OK;
334 335 336 337 338 339

    /* Serialise the return header. */
    xdrmem_create (&xdr, client->buffer, sizeof client->buffer, XDR_ENCODE);

    len = 0; /* We'll come back and write this later. */
    if (!xdr_int (&xdr, &len)) {
340
        if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
341
        goto fatal_error;
342 343 344
    }

    if (!xdr_remote_message_header (&xdr, &rep)) {
345
        if (rv == 0) xdr_free (data->ret_filter, (char*)&ret);
346
        goto fatal_error;
347 348 349
    }

    /* If OK, serialise return structure, if error serialise error. */
350 351 352
    if (rv >= 0) {
        if (!((data->ret_filter) (&xdr, &ret)))
            goto fatal_error;
353
        xdr_free (data->ret_filter, (char*)&ret);
354
    } else /* error */ {
355 356 357 358 359
        /* Error was NULL so synthesize an error. */
        if (rerr.code == 0)
            remoteDispatchGenericError(&rerr);
        if (!xdr_remote_error (&xdr, &rerr))
            goto fatal_error;
360 361 362 363
    }

    /* Write the length word. */
    len = xdr_getpos (&xdr);
364 365
    if (xdr_setpos (&xdr, 0) == 0)
        goto fatal_error;
366

367 368
    if (!xdr_int (&xdr, &len))
        goto fatal_error;
369 370

    xdr_destroy (&xdr);
371
    return len;
372

373 374 375
fatal_error:
    /* Seriously bad stuff happened, so we'll kill off this client
       and not send back any RPC error */
376
    xdr_destroy (&xdr);
377
    return 0;
378 379
}

380
int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
381 382 383 384
                            virDomainPtr dom,
                            int event,
                            int detail,
                            void *opaque)
385 386
{
    struct qemud_client *client = opaque;
387
    REMOTE_DEBUG("Relaying domain event %d %d", event, detail);
388 389

    if(client) {
390
        remoteDispatchDomainEventSend (client, dom, event, detail);
391 392 393 394
        qemudDispatchClientWrite(client->server,client);
    }
    return 0;
}
395 396


397 398 399
/*----- Functions. -----*/

static int
400
remoteDispatchOpen (struct qemud_server *server,
401
                    struct qemud_client *client,
402
                    virConnectPtr conn,
403
                    remote_error *rerr,
404 405 406
                    struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED)
{
    const char *name;
407
    int flags, rc;
408 409

    /* Already opened? */
410
    if (conn) {
411 412
        remoteDispatchFormatError (rerr, "%s", _("connection already open"));
        return -1;
413 414
    }

415 416 417 418
    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);

419 420 421 422 423 424 425 426 427 428 429 430 431
    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);

432
    if (client->conn == NULL)
433 434
        remoteDispatchConnError(rerr, NULL);

435 436 437
    rc = client->conn ? 0 : -1;
    pthread_mutex_unlock(&client->lock);
    return rc;
438 439
}

440 441 442 443
#define CHECK_CONN(client)                                              \
    if (!client->conn) {                                                \
        remoteDispatchFormatError (rerr, "%s", _("connection not open")); \
        return -1;                                                      \
444 445 446
    }

static int
447
remoteDispatchClose (struct qemud_server *server ATTRIBUTE_UNUSED,
448 449 450
                     struct qemud_client *client ATTRIBUTE_UNUSED,
                     virConnectPtr conn ATTRIBUTE_UNUSED,
                     remote_error *rerr ATTRIBUTE_UNUSED,
451 452
                     void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
{
453 454 455
    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);
456

457
    client->closing = 1;
458

459
    pthread_mutex_unlock(&client->lock);
460
    return 0;
461 462
}

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

    if (ret->supported == -1) {
473
        remoteDispatchConnError(rerr, conn);
474 475
        return -1;
    }
476 477 478 479

    return 0;
}

480
static int
481
remoteDispatchGetType (struct qemud_server *server ATTRIBUTE_UNUSED,
482 483
                       struct qemud_client *client ATTRIBUTE_UNUSED,
                       virConnectPtr conn,
484
                       remote_error *rerr,
485 486 487 488
                       void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret)
{
    const char *type;

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

    /* We have to strdup because remoteDispatchClientRequest will
     * free this string after it's been serialised.
     */
    ret->type = strdup (type);
    if (!ret->type) {
500 501
        remoteDispatchFormatError (rerr, "%s", _("out of memory in strdup"));
        return -1;
502 503 504 505 506 507
    }

    return 0;
}

static int
508
remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
509 510
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
511
                          remote_error *rerr,
512 513 514 515 516
                          void *args ATTRIBUTE_UNUSED,
                          remote_get_version_ret *ret)
{
    unsigned long hvVer;

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

    ret->hv_ver = hvVer;
    return 0;
}

526
static int
527
remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED,
528 529
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
530
                           remote_error *rerr,
531 532 533 534 535
                           void *args ATTRIBUTE_UNUSED,
                           remote_get_hostname_ret *ret)
{
    char *hostname;

536
    hostname = virConnectGetHostname (conn);
537
    if (hostname == NULL) {
538
        remoteDispatchConnError(rerr, conn);
539 540
        return -1;
    }
541 542 543 544 545

    ret->hostname = hostname;
    return 0;
}

546 547
static int
remoteDispatchGetUri (struct qemud_server *server ATTRIBUTE_UNUSED,
548 549
                      struct qemud_client *client ATTRIBUTE_UNUSED,
                      virConnectPtr conn,
550
                      remote_error *rerr,
551 552 553 554 555 556
                      void *args ATTRIBUTE_UNUSED,
                      remote_get_uri_ret *ret)
{
    char *uri;
    CHECK_CONN(client);

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

    ret->uri = uri;
    return 0;
}

567
static int
568
remoteDispatchGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
569 570
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
571
                           remote_error *rerr,
572 573 574 575 576 577
                           remote_get_max_vcpus_args *args,
                           remote_get_max_vcpus_ret *ret)
{
    char *type;

    type = args->type ? *args->type : NULL;
578
    ret->max_vcpus = virConnectGetMaxVcpus (conn, type);
579
    if (ret->max_vcpus == -1) {
580
        remoteDispatchConnError(rerr, conn);
581 582
        return -1;
    }
583 584 585 586 587

    return 0;
}

static int
588
remoteDispatchNodeGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
589 590
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
591
                           remote_error *rerr,
592 593 594 595 596
                           void *args ATTRIBUTE_UNUSED,
                           remote_node_get_info_ret *ret)
{
    virNodeInfo info;

597 598
    if (virNodeGetInfo (conn, &info) == -1) {
        remoteDispatchConnError(rerr, conn);
599
        return -1;
600
    }
601 602 603 604 605 606 607 608 609 610 611 612 613 614

    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
615
remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED,
616 617
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
618
                               remote_error *rerr,
619 620 621 622 623
                               void *args ATTRIBUTE_UNUSED,
                               remote_get_capabilities_ret *ret)
{
    char *caps;

624
    caps = virConnectGetCapabilities (conn);
625
    if (caps == NULL) {
626
        remoteDispatchConnError(rerr, conn);
627 628
        return -1;
    }
629 630 631 632 633

    ret->capabilities = caps;
    return 0;
}

634 635
static int
remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
636 637
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
638
                                      remote_error *rerr,
639 640 641 642 643
                                      remote_node_get_cells_free_memory_args *args,
                                      remote_node_get_cells_free_memory_ret *ret)
{

    if (args->maxCells > REMOTE_NODE_MAX_CELLS) {
644 645 646
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxCells > REMOTE_NODE_MAX_CELLS"));
        return -1;
647 648 649
    }

    /* Allocate return buffer. */
650
    if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) {
651 652
        remoteDispatchOOMError(rerr);
        return -1;
653
    }
654

655
    ret->freeMems.freeMems_len = virNodeGetCellsFreeMemory(conn,
656 657 658
                                                           (unsigned long long *)ret->freeMems.freeMems_val,
                                                           args->startCell,
                                                           args->maxCells);
659 660
    if (ret->freeMems.freeMems_len == 0) {
        VIR_FREE(ret->freeMems.freeMems_val);
661
        remoteDispatchConnError(rerr, conn);
662
        return -1;
663
    }
664 665 666 667 668 669 670

    return 0;
}


static int
remoteDispatchNodeGetFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
671 672
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
673
                                 remote_error *rerr,
674 675 676 677 678
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_node_get_free_memory_ret *ret)
{
    unsigned long long freeMem;

679
    freeMem = virNodeGetFreeMemory(conn);
680
    if (freeMem == 0) {
681
        remoteDispatchConnError(rerr, conn);
682 683
        return -1;
    }
684 685 686 687 688
    ret->freeMem = freeMem;
    return 0;
}


689
static int
690
remoteDispatchDomainGetSchedulerType (struct qemud_server *server ATTRIBUTE_UNUSED,
691 692
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
693
                                      remote_error *rerr,
694 695 696 697 698 699 700
                                      remote_domain_get_scheduler_type_args *args,
                                      remote_domain_get_scheduler_type_ret *ret)
{
    virDomainPtr dom;
    char *type;
    int nparams;

701
    dom = get_nonnull_domain (conn, args->dom);
702
    if (dom == NULL) {
703
        remoteDispatchConnError(rerr, conn);
704
        return -1;
705 706 707
    }

    type = virDomainGetSchedulerType (dom, &nparams);
708 709
    if (type == NULL) {
        virDomainFree(dom);
710
        remoteDispatchConnError(rerr, conn);
711 712
        return -1;
    }
713 714 715

    ret->type = type;
    ret->nparams = nparams;
716
    virDomainFree(dom);
717 718 719 720
    return 0;
}

static int
721
remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
722 723
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
724
                                            remote_error *rerr,
725 726 727 728 729 730 731 732 733 734
                                            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) {
735 736
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
737
    }
738
    if (VIR_ALLOC_N(params, nparams) < 0) {
739 740
        remoteDispatchOOMError(rerr);
        return -1;
741 742
    }

743
    dom = get_nonnull_domain (conn, args->dom);
744
    if (dom == NULL) {
745
        VIR_FREE(params);
746
        remoteDispatchConnError(rerr, conn);
747
        return -1;
748 749 750 751
    }

    r = virDomainGetSchedulerParameters (dom, params, &nparams);
    if (r == -1) {
752
        virDomainFree(dom);
753
        VIR_FREE(params);
754
        remoteDispatchConnError(rerr, conn);
755 756 757 758 759
        return -1;
    }

    /* Serialise the scheduler parameters. */
    ret->params.params_len = nparams;
760 761
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;
762 763 764 765

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

769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
        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:
784
            remoteDispatchFormatError (rerr, "%s", _("unknown type"));
785
            goto cleanup;
786 787
        }
    }
788
    virDomainFree(dom);
789
    VIR_FREE(params);
790 791

    return 0;
792 793

oom:
794
    remoteDispatchOOMError(rerr);
795 796 797 798 799
cleanup:
    virDomainFree(dom);
    for (i = 0 ; i < nparams ; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
800
    return -1;
801 802 803
}

static int
804
remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
805 806
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
807
                                            remote_error *rerr,
808 809 810 811 812 813 814 815 816 817
                                            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) {
818 819
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
820
    }
821
    if (VIR_ALLOC_N(params, nparams)) {
822 823
        remoteDispatchOOMError(rerr);
        return -1;
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
    }

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

848
    dom = get_nonnull_domain (conn, args->dom);
849
    if (dom == NULL) {
850
        VIR_FREE(params);
851
        remoteDispatchConnError(rerr, conn);
852
        return -1;
853 854 855
    }

    r = virDomainSetSchedulerParameters (dom, params, nparams);
856
    virDomainFree(dom);
857
    VIR_FREE(params);
858
    if (r == -1) {
859
        remoteDispatchConnError(rerr, conn);
860 861
        return -1;
    }
862 863 864 865

    return 0;
}

866
static int
867
remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED,
868 869
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
870
                                remote_error *rerr,
871 872 873 874 875 876 877
                                remote_domain_block_stats_args *args,
                                remote_domain_block_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainBlockStats stats;

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

D
Daniel P. Berrange 已提交
885 886
    if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
887
        remoteDispatchConnError(rerr, conn);
888
        return -1;
D
Daniel P. Berrange 已提交
889 890
    }
    virDomainFree (dom);
891 892 893 894 895 896 897 898 899 900 901

    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
902
remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED,
903 904
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
905
                                    remote_error *rerr,
906 907 908 909 910 911 912
                                    remote_domain_interface_stats_args *args,
                                    remote_domain_interface_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainInterfaceStats stats;

913
    dom = get_nonnull_domain (conn, args->dom);
914
    if (dom == NULL) {
915
        remoteDispatchConnError(rerr, conn);
916
        return -1;
917 918 919
    }
    path = args->path;

D
Daniel P. Berrange 已提交
920 921
    if (virDomainInterfaceStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
922
        remoteDispatchConnError(rerr, conn);
923
        return -1;
D
Daniel P. Berrange 已提交
924 925
    }
    virDomainFree (dom);
926 927 928 929 930 931 932 933 934 935 936 937 938

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

939 940
static int
remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
941 942
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
943
                               remote_error *rerr,
944 945 946 947 948 949 950 951 952
                               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;

953
    dom = get_nonnull_domain (conn, args->dom);
954
    if (dom == NULL) {
955
        remoteDispatchConnError(rerr, conn);
956
        return -1;
957 958 959 960 961 962 963
    }
    path = args->path;
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
964
        virDomainFree (dom);
965 966 967
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
968 969 970
    }

    ret->buffer.buffer_len = size;
971 972
    if (VIR_ALLOC_N(ret->buffer.buffer_val, size) < 0) {
        virDomainFree (dom);
973 974
        remoteDispatchFormatError (rerr, "%s", strerror (errno));
        return -1;
975 976 977 978 979 980
    }

    if (virDomainBlockPeek (dom, path, offset, size,
                            ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
981
        remoteDispatchConnError(rerr, conn);
982 983 984 985 986 987 988
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

R
Richard W.M. Jones 已提交
989 990
static int
remoteDispatchDomainMemoryPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
991 992
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
993
                                remote_error *rerr,
R
Richard W.M. Jones 已提交
994 995 996 997 998 999 1000 1001
                                remote_domain_memory_peek_args *args,
                                remote_domain_memory_peek_ret *ret)
{
    virDomainPtr dom;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

1002
    dom = get_nonnull_domain (conn, args->dom);
R
Richard W.M. Jones 已提交
1003
    if (dom == NULL) {
1004
        remoteDispatchConnError(rerr, conn);
1005
        return -1;
R
Richard W.M. Jones 已提交
1006 1007 1008 1009 1010 1011
    }
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
1012 1013
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
R
Richard W.M. Jones 已提交
1014
        virDomainFree (dom);
1015
        return -1;
R
Richard W.M. Jones 已提交
1016 1017 1018 1019
    }

    ret->buffer.buffer_len = size;
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
1020
        remoteDispatchFormatError (rerr, "%s", strerror (errno));
R
Richard W.M. Jones 已提交
1021
        virDomainFree (dom);
1022
        return -1;
R
Richard W.M. Jones 已提交
1023 1024 1025 1026 1027 1028
    }

    if (virDomainMemoryPeek (dom, offset, size,
                             ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
1029
        remoteDispatchConnError(rerr, conn);
R
Richard W.M. Jones 已提交
1030 1031 1032 1033 1034 1035 1036
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

1037
static int
1038
remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1039 1040
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1041
                                  remote_error *rerr,
1042 1043 1044 1045 1046
                                  remote_domain_attach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1047
    dom = get_nonnull_domain (conn, args->dom);
1048
    if (dom == NULL) {
1049
        remoteDispatchConnError(rerr, conn);
1050
        return -1;
1051 1052
    }

1053 1054
    if (virDomainAttachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
1055
        remoteDispatchConnError(rerr, conn);
1056
        return -1;
1057 1058
    }
    virDomainFree(dom);
1059 1060 1061 1062
    return 0;
}

static int
1063
remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
1064 1065
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1066
                            remote_error *rerr,
1067 1068 1069 1070 1071
                            remote_domain_create_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1072
    dom = get_nonnull_domain (conn, args->dom);
1073
    if (dom == NULL) {
1074
        remoteDispatchConnError(rerr, conn);
1075
        return -1;
1076 1077
    }

1078 1079
    if (virDomainCreate (dom) == -1) {
        virDomainFree(dom);
1080
        remoteDispatchConnError(rerr, conn);
1081
        return -1;
1082 1083
    }
    virDomainFree(dom);
1084 1085 1086 1087
    return 0;
}

static int
1088
remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1089 1090 1091 1092 1093
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_error *rerr,
                               remote_domain_create_xml_args *args,
                               remote_domain_create_xml_ret *ret)
1094 1095 1096
{
    virDomainPtr dom;

1097
    dom = virDomainCreateXML (conn, args->xml_desc, args->flags);
1098
    if (dom == NULL) {
1099
        remoteDispatchConnError(rerr, conn);
1100 1101
        return -1;
    }
1102 1103

    make_nonnull_domain (&ret->dom, dom);
1104
    virDomainFree(dom);
1105 1106 1107 1108 1109

    return 0;
}

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

1119
    dom = virDomainDefineXML (conn, args->xml);
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
remoteDispatchDomainDestroy (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_destroy_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

1147 1148
    if (virDomainDestroy (dom) == -1) {
        virDomainFree(dom);
1149
        remoteDispatchConnError(rerr, conn);
1150
        return -1;
1151 1152
    }
    virDomainFree(dom);
1153 1154 1155 1156
    return 0;
}

static int
1157
remoteDispatchDomainDetachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
1158 1159
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1160
                                  remote_error *rerr,
1161 1162 1163 1164 1165
                                  remote_domain_detach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

1172 1173
    if (virDomainDetachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
1174
        remoteDispatchConnError(rerr, conn);
1175
        return -1;
1176
    }
1177

1178
    virDomainFree(dom);
1179 1180 1181 1182
    return 0;
}

static int
1183
remoteDispatchDomainDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
1184 1185
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1186
                             remote_error *rerr,
1187 1188 1189 1190 1191
                             remote_domain_dump_xml_args *args,
                             remote_domain_dump_xml_ret *ret)
{
    virDomainPtr dom;

1192
    dom = get_nonnull_domain (conn, args->dom);
1193
    if (dom == NULL) {
1194
        remoteDispatchConnError(rerr, conn);
1195
        return -1;
1196 1197 1198 1199
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virDomainGetXMLDesc (dom, args->flags);
1200
    if (!ret->xml) {
1201
        virDomainFree(dom);
1202
        remoteDispatchConnError(rerr, conn);
1203
        return -1;
1204 1205
    }
    virDomainFree(dom);
1206 1207 1208 1209
    return 0;
}

static int
1210
remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1211 1212
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1213
                                  remote_error *rerr,
1214 1215 1216 1217 1218
                                  remote_domain_get_autostart_args *args,
                                  remote_domain_get_autostart_ret *ret)
{
    virDomainPtr dom;

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

1225 1226
    if (virDomainGetAutostart (dom, &ret->autostart) == -1) {
        virDomainFree(dom);
1227
        remoteDispatchConnError(rerr, conn);
1228
        return -1;
1229 1230
    }
    virDomainFree(dom);
1231 1232 1233 1234
    return 0;
}

static int
1235
remoteDispatchDomainGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
1236 1237
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1238
                             remote_error *rerr,
1239 1240 1241 1242 1243 1244
                             remote_domain_get_info_args *args,
                             remote_domain_get_info_ret *ret)
{
    virDomainPtr dom;
    virDomainInfo info;

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

1251 1252
    if (virDomainGetInfo (dom, &info) == -1) {
        virDomainFree(dom);
1253
        remoteDispatchConnError(rerr, conn);
1254
        return -1;
1255
    }
1256 1257 1258 1259 1260 1261 1262

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

1263 1264
    virDomainFree(dom);

1265 1266 1267 1268
    return 0;
}

static int
1269
remoteDispatchDomainGetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1270 1271
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1272
                                  remote_error *rerr,
1273 1274 1275 1276 1277
                                  remote_domain_get_max_memory_args *args,
                                  remote_domain_get_max_memory_ret *ret)
{
    virDomainPtr dom;

1278
    dom = get_nonnull_domain (conn, args->dom);
1279
    if (dom == NULL) {
1280
        remoteDispatchConnError(rerr, conn);
1281
        return -1;
1282 1283 1284
    }

    ret->memory = virDomainGetMaxMemory (dom);
1285 1286
    if (ret->memory == 0) {
        virDomainFree(dom);
1287
        remoteDispatchConnError(rerr, conn);
1288 1289 1290
        return -1;
    }
    virDomainFree(dom);
1291 1292 1293 1294
    return 0;
}

static int
1295
remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1296 1297
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1298
                                 remote_error *rerr,
1299 1300 1301 1302 1303
                                 remote_domain_get_max_vcpus_args *args,
                                 remote_domain_get_max_vcpus_ret *ret)
{
    virDomainPtr dom;

1304
    dom = get_nonnull_domain (conn, args->dom);
1305
    if (dom == NULL) {
1306
        remoteDispatchConnError(rerr, conn);
1307
        return -1;
1308 1309 1310
    }

    ret->num = virDomainGetMaxVcpus (dom);
1311 1312
    if (ret->num == -1) {
        virDomainFree(dom);
1313
        remoteDispatchConnError(rerr, conn);
1314 1315 1316
        return -1;
    }
    virDomainFree(dom);
1317 1318 1319 1320
    return 0;
}

static int
1321
remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED,
1322 1323
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1324
                               remote_error *rerr,
1325 1326 1327 1328 1329
                               remote_domain_get_os_type_args *args,
                               remote_domain_get_os_type_ret *ret)
{
    virDomainPtr dom;

1330
    dom = get_nonnull_domain (conn, args->dom);
1331
    if (dom == NULL) {
1332
        remoteDispatchConnError(rerr, conn);
1333
        return -1;
1334 1335 1336 1337
    }

    /* remoteDispatchClientRequest will free this */
    ret->type = virDomainGetOSType (dom);
1338
    if (ret->type == NULL) {
1339
        virDomainFree(dom);
1340
        remoteDispatchConnError(rerr, conn);
1341
        return -1;
1342 1343
    }
    virDomainFree(dom);
1344 1345 1346 1347
    return 0;
}

static int
1348
remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1349 1350
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1351
                              remote_error *rerr,
1352 1353 1354
                              remote_domain_get_vcpus_args *args,
                              remote_domain_get_vcpus_ret *ret)
{
1355 1356 1357
    virDomainPtr dom = NULL;
    virVcpuInfoPtr info = NULL;
    unsigned char *cpumaps = NULL;
1358 1359
    int info_len, i;

1360
    dom = get_nonnull_domain (conn, args->dom);
1361
    if (dom == NULL) {
1362
        remoteDispatchConnError(rerr, conn);
1363
        return -1;
1364 1365 1366
    }

    if (args->maxinfo > REMOTE_VCPUINFO_MAX) {
1367
        virDomainFree(dom);
1368 1369
        remoteDispatchFormatError (rerr, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX"));
        return -1;
1370 1371
    }

1372
    if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
1373
        virDomainFree(dom);
1374 1375
        remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX"));
        return -1;
1376 1377 1378
    }

    /* Allocate buffers to take the results. */
1379 1380 1381 1382
    if (VIR_ALLOC_N(info, args->maxinfo) < 0)
        goto oom;
    if (VIR_ALLOC_N(cpumaps, args->maxinfo) < 0)
        goto oom;
1383 1384 1385 1386

    info_len = virDomainGetVcpus (dom,
                                  info, args->maxinfo,
                                  cpumaps, args->maplen);
1387
    if (info_len == -1) {
1388 1389
        VIR_FREE(info);
        VIR_FREE(cpumaps);
1390
        virDomainFree(dom);
1391
        remoteDispatchConnError(rerr, conn);
1392 1393
        return -1;
    }
1394 1395 1396

    /* Allocate the return buffer for info. */
    ret->info.info_len = info_len;
1397 1398
    if (VIR_ALLOC_N(ret->info.info_val, info_len) < 0)
        goto oom;
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410

    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.
     */
1411
    ret->cpumaps.cpumaps_len = args->maxinfo * args->maplen;
1412 1413
    ret->cpumaps.cpumaps_val = (char *) cpumaps;

1414
    VIR_FREE(info);
1415
    virDomainFree(dom);
1416
    return 0;
1417 1418 1419 1420 1421

oom:
    VIR_FREE(info);
    VIR_FREE(cpumaps);
    virDomainFree(dom);
1422 1423
    remoteDispatchOOMError(rerr);
    return -1;
1424 1425
}

1426
static int
1427
remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED,
1428 1429
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1430
                                    remote_error *rerr,
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444
                                    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 ... */
1445
    if (VIR_ALLOC(uri_out) < 0) {
1446 1447
        remoteDispatchOOMError(rerr);
        return -1;
1448
    }
1449

1450
    r = virDomainMigratePrepare (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1451 1452
                                 uri_in, uri_out,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1453
    if (r == -1) {
1454
        VIR_FREE(uri_out);
1455
        remoteDispatchConnError(rerr, conn);
D
Daniel P. Berrange 已提交
1456 1457
        return -1;
    }
1458 1459 1460 1461 1462 1463

    /* 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 已提交
1464 1465
    if (*uri_out == NULL) {
        ret->uri_out = NULL;
1466
        VIR_FREE(uri_out);
D
Daniel P. Berrange 已提交
1467 1468 1469
    } else {
        ret->uri_out = uri_out;
    }
1470 1471 1472 1473 1474

    return 0;
}

static int
1475
remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED,
1476 1477
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1478
                                    remote_error *rerr,
1479 1480 1481 1482 1483 1484 1485
                                    remote_domain_migrate_perform_args *args,
                                    void *ret ATTRIBUTE_UNUSED)
{
    int r;
    virDomainPtr dom;
    char *dname;

1486
    dom = get_nonnull_domain (conn, args->dom);
1487
    if (dom == NULL) {
1488
        remoteDispatchConnError(rerr, conn);
1489
        return -1;
1490 1491 1492 1493
    }

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

D
Daniel P. Berrange 已提交
1494 1495 1496 1497 1498
    r = virDomainMigratePerform (dom,
                                 args->cookie.cookie_val,
                                 args->cookie.cookie_len,
                                 args->uri,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1499
    virDomainFree (dom);
1500
    if (r == -1) {
1501
        remoteDispatchConnError(rerr, conn);
1502 1503
        return -1;
    }
1504 1505 1506 1507 1508

    return 0;
}

static int
1509
remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED,
1510 1511
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1512
                                   remote_error *rerr,
1513 1514 1515 1516 1517 1518
                                   remote_domain_migrate_finish_args *args,
                                   remote_domain_migrate_finish_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1519
    ddom = virDomainMigrateFinish (conn, args->dname,
D
Daniel P. Berrange 已提交
1520 1521 1522 1523
                                   args->cookie.cookie_val,
                                   args->cookie.cookie_len,
                                   args->uri,
                                   args->flags);
1524
    if (ddom == NULL) {
1525
        remoteDispatchConnError(rerr, conn);
1526 1527
        return -1;
    }
1528 1529

    make_nonnull_domain (&ret->ddom, ddom);
D
Daniel P. Berrange 已提交
1530
    virDomainFree (ddom);
1531 1532 1533
    return 0;
}

D
Daniel Veillard 已提交
1534 1535
static int
remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1536 1537
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1538
                                     remote_error *rerr,
D
Daniel Veillard 已提交
1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554
                                     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) {
1555 1556
        remoteDispatchOOMError(rerr);
        return -1;
D
Daniel Veillard 已提交
1557 1558
    }

1559
    r = virDomainMigratePrepare2 (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1560 1561 1562
                                  uri_in, uri_out,
                                  args->flags, dname, args->resource,
                                  args->dom_xml);
1563
    if (r == -1) {
1564
        remoteDispatchConnError(rerr, conn);
1565 1566
        return -1;
    }
D
Daniel Veillard 已提交
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579

    /* 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,
1580 1581
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1582
                                    remote_error *rerr,
D
Daniel Veillard 已提交
1583 1584 1585 1586 1587 1588
                                    remote_domain_migrate_finish2_args *args,
                                    remote_domain_migrate_finish2_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1589
    ddom = virDomainMigrateFinish2 (conn, args->dname,
D
Daniel P. Berrange 已提交
1590 1591 1592 1593 1594
                                    args->cookie.cookie_val,
                                    args->cookie.cookie_len,
                                    args->uri,
                                    args->flags,
                                    args->retcode);
1595
    if (ddom == NULL) {
1596
        remoteDispatchConnError(rerr, conn);
1597 1598
        return -1;
    }
D
Daniel Veillard 已提交
1599 1600 1601 1602 1603 1604

    make_nonnull_domain (&ret->ddom, ddom);

    return 0;
}

1605
static int
1606
remoteDispatchListDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1607 1608
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1609
                                  remote_error *rerr,
1610 1611 1612 1613 1614
                                  remote_list_defined_domains_args *args,
                                  remote_list_defined_domains_ret *ret)
{

    if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) {
1615 1616 1617
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX"));
        return -1;
1618 1619 1620
    }

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

    ret->names.names_len =
1627
        virConnectListDefinedDomains (conn,
1628
                                      ret->names.names_val, args->maxnames);
1629 1630
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
1631
        remoteDispatchConnError(rerr, conn);
1632 1633
        return -1;
    }
1634 1635 1636 1637 1638

    return 0;
}

static int
1639
remoteDispatchDomainLookupById (struct qemud_server *server ATTRIBUTE_UNUSED,
1640 1641
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
1642
                                remote_error *rerr,
1643 1644 1645 1646 1647
                                remote_domain_lookup_by_id_args *args,
                                remote_domain_lookup_by_id_ret *ret)
{
    virDomainPtr dom;

1648
    dom = virDomainLookupByID (conn, args->id);
1649
    if (dom == NULL) {
1650
        remoteDispatchConnError(rerr, conn);
1651 1652
        return -1;
    }
1653 1654

    make_nonnull_domain (&ret->dom, dom);
1655
    virDomainFree(dom);
1656 1657 1658 1659
    return 0;
}

static int
1660
remoteDispatchDomainLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
1661 1662
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1663
                                  remote_error *rerr,
1664 1665 1666 1667 1668
                                  remote_domain_lookup_by_name_args *args,
                                  remote_domain_lookup_by_name_ret *ret)
{
    virDomainPtr dom;

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

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

static int
1681
remoteDispatchDomainLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
1682 1683
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1684
                                  remote_error *rerr,
1685 1686 1687 1688 1689
                                  remote_domain_lookup_by_uuid_args *args,
                                  remote_domain_lookup_by_uuid_ret *ret)
{
    virDomainPtr dom;

1690
    dom = virDomainLookupByUUID (conn, (unsigned char *) args->uuid);
1691
    if (dom == NULL) {
1692
        remoteDispatchConnError(rerr, conn);
1693 1694
        return -1;
    }
1695 1696

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

static int
1702
remoteDispatchNumOfDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1703 1704
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1705
                                   remote_error *rerr,
1706 1707 1708 1709
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_num_of_defined_domains_ret *ret)
{

1710
    ret->num = virConnectNumOfDefinedDomains (conn);
1711
    if (ret->num == -1) {
1712
        remoteDispatchConnError(rerr, conn);
1713 1714
        return -1;
    }
1715 1716 1717 1718 1719

    return 0;
}

static int
1720
remoteDispatchDomainPinVcpu (struct qemud_server *server ATTRIBUTE_UNUSED,
1721 1722
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1723
                             remote_error *rerr,
1724 1725 1726 1727 1728 1729
                             remote_domain_pin_vcpu_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int rv;

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

    if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) {
1737
        virDomainFree(dom);
1738 1739
        remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX"));
        return -1;
1740 1741 1742 1743 1744
    }

    rv = virDomainPinVcpu (dom, args->vcpu,
                           (unsigned char *) args->cpumap.cpumap_val,
                           args->cpumap.cpumap_len);
1745 1746
    if (rv == -1) {
        virDomainFree(dom);
1747
        remoteDispatchConnError(rerr, conn);
1748 1749 1750
        return -1;
    }
    virDomainFree(dom);
1751 1752 1753 1754
    return 0;
}

static int
1755
remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED,
1756 1757
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1758
                            remote_error *rerr,
1759 1760 1761 1762 1763
                            remote_domain_reboot_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1764
    dom = get_nonnull_domain (conn, args->dom);
1765
    if (dom == NULL) {
1766
        remoteDispatchConnError(rerr, conn);
1767
        return -1;
1768 1769
    }

1770 1771
    if (virDomainReboot (dom, args->flags) == -1) {
        virDomainFree(dom);
1772
        remoteDispatchConnError(rerr, conn);
1773
        return -1;
1774 1775
    }
    virDomainFree(dom);
1776 1777 1778 1779
    return 0;
}

static int
1780
remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED,
1781 1782
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1783
                             remote_error *rerr,
1784 1785 1786 1787
                             remote_domain_restore_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{

1788 1789
    if (virDomainRestore (conn, args->from) == -1) {
        remoteDispatchConnError(rerr, conn);
1790
        return -1;
1791
    }
1792 1793 1794 1795 1796

    return 0;
}

static int
1797
remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED,
1798 1799
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1800
                            remote_error *rerr,
1801 1802 1803 1804 1805
                            remote_domain_resume_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1806
    dom = get_nonnull_domain (conn, args->dom);
1807
    if (dom == NULL) {
1808
        remoteDispatchConnError(rerr, conn);
1809
        return -1;
1810 1811
    }

1812 1813
    if (virDomainResume (dom) == -1) {
        virDomainFree(dom);
1814
        remoteDispatchConnError(rerr, conn);
1815
        return -1;
1816 1817
    }
    virDomainFree(dom);
1818 1819 1820 1821
    return 0;
}

static int
1822
remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED,
1823 1824
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
1825
                          remote_error *rerr,
1826 1827 1828 1829 1830
                          remote_domain_save_args *args,
                          void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1831
    dom = get_nonnull_domain (conn, args->dom);
1832
    if (dom == NULL) {
1833
        remoteDispatchConnError(rerr, conn);
1834
        return -1;
1835 1836
    }

1837 1838
    if (virDomainSave (dom, args->to) == -1) {
        virDomainFree(dom);
1839
        remoteDispatchConnError(rerr, conn);
1840
        return -1;
1841 1842
    }
    virDomainFree(dom);
1843 1844 1845 1846
    return 0;
}

static int
1847
remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED,
1848 1849
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1850
                              remote_error *rerr,
1851 1852 1853 1854 1855
                              remote_domain_core_dump_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1856
    dom = get_nonnull_domain (conn, args->dom);
1857
    if (dom == NULL) {
1858
        remoteDispatchConnError(rerr, conn);
1859
        return -1;
1860 1861
    }

1862 1863
    if (virDomainCoreDump (dom, args->to, args->flags) == -1) {
        virDomainFree(dom);
1864
        remoteDispatchConnError(rerr, conn);
1865
        return -1;
1866 1867
    }
    virDomainFree(dom);
1868 1869 1870 1871
    return 0;
}

static int
1872
remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1873 1874
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1875
                                  remote_error *rerr,
1876 1877 1878 1879 1880
                                  remote_domain_set_autostart_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

1887 1888
    if (virDomainSetAutostart (dom, args->autostart) == -1) {
        virDomainFree(dom);
1889
        remoteDispatchConnError(rerr, conn);
1890
        return -1;
1891 1892
    }
    virDomainFree(dom);
1893 1894 1895 1896
    return 0;
}

static int
1897
remoteDispatchDomainSetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1898 1899
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1900
                                  remote_error *rerr,
1901 1902 1903 1904 1905
                                  remote_domain_set_max_memory_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1906
    dom = get_nonnull_domain (conn, args->dom);
1907
    if (dom == NULL) {
1908
        remoteDispatchConnError(rerr, conn);
1909
        return -1;
1910 1911
    }

1912 1913
    if (virDomainSetMaxMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
1914
        remoteDispatchConnError(rerr, conn);
1915
        return -1;
1916 1917
    }
    virDomainFree(dom);
1918 1919 1920 1921
    return 0;
}

static int
1922
remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1923 1924
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1925
                               remote_error *rerr,
1926 1927 1928 1929 1930
                               remote_domain_set_memory_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1931
    dom = get_nonnull_domain (conn, args->dom);
1932
    if (dom == NULL) {
1933
        remoteDispatchConnError(rerr, conn);
1934
        return -1;
1935 1936
    }

1937 1938
    if (virDomainSetMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
1939
        remoteDispatchConnError(rerr, conn);
1940
        return -1;
1941 1942
    }
    virDomainFree(dom);
1943 1944 1945 1946
    return 0;
}

static int
1947
remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1948 1949
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1950
                              remote_error *rerr,
1951 1952 1953 1954 1955
                              remote_domain_set_vcpus_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1956
    dom = get_nonnull_domain (conn, args->dom);
1957
    if (dom == NULL) {
1958
        remoteDispatchConnError(rerr, conn);
1959
        return -1;
1960 1961
    }

1962 1963
    if (virDomainSetVcpus (dom, args->nvcpus) == -1) {
        virDomainFree(dom);
1964
        remoteDispatchConnError(rerr, conn);
1965
        return -1;
1966 1967
    }
    virDomainFree(dom);
1968 1969 1970 1971
    return 0;
}

static int
1972
remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED,
1973 1974
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1975
                              remote_error *rerr,
1976 1977 1978 1979 1980
                              remote_domain_shutdown_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1981
    dom = get_nonnull_domain (conn, args->dom);
1982
    if (dom == NULL) {
1983
        remoteDispatchConnError(rerr, conn);
1984
        return -1;
1985 1986
    }

1987 1988
    if (virDomainShutdown (dom) == -1) {
        virDomainFree(dom);
1989
        remoteDispatchConnError(rerr, conn);
1990
        return -1;
1991 1992
    }
    virDomainFree(dom);
1993 1994 1995 1996
    return 0;
}

static int
1997
remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED,
1998 1999
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2000
                             remote_error *rerr,
2001 2002 2003 2004 2005
                             remote_domain_suspend_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2006
    dom = get_nonnull_domain (conn, args->dom);
2007
    if (dom == NULL) {
2008
        remoteDispatchConnError(rerr, conn);
2009
        return -1;
2010 2011
    }

2012 2013
    if (virDomainSuspend (dom) == -1) {
        virDomainFree(dom);
2014
        remoteDispatchConnError(rerr, conn);
2015
        return -1;
2016 2017
    }
    virDomainFree(dom);
2018 2019 2020 2021
    return 0;
}

static int
2022
remoteDispatchDomainUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2023 2024
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2025
                              remote_error *rerr,
2026 2027 2028 2029 2030
                              remote_domain_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

2031
    dom = get_nonnull_domain (conn, args->dom);
2032
    if (dom == NULL) {
2033
        remoteDispatchConnError(rerr, conn);
2034
        return -1;
2035 2036
    }

2037 2038
    if (virDomainUndefine (dom) == -1) {
        virDomainFree(dom);
2039
        remoteDispatchConnError(rerr, conn);
2040
        return -1;
2041 2042
    }
    virDomainFree(dom);
2043 2044 2045 2046
    return 0;
}

static int
2047
remoteDispatchListDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2048 2049
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2050
                                   remote_error *rerr,
2051 2052 2053 2054 2055
                                   remote_list_defined_networks_args *args,
                                   remote_list_defined_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2056 2057 2058
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2059 2060 2061
    }

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

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

    return 0;
}

static int
2080
remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2081 2082
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
2083
                           remote_error *rerr,
2084 2085 2086 2087 2088
                           remote_list_domains_args *args,
                           remote_list_domains_ret *ret)
{

    if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
2089 2090 2091
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX"));
        return -1;
2092 2093 2094
    }

    /* Allocate return buffer. */
2095
    if (VIR_ALLOC_N(ret->ids.ids_val, args->maxids) < 0) {
2096 2097
        remoteDispatchOOMError(rerr);
        return -1;
2098
    }
2099

2100
    ret->ids.ids_len = virConnectListDomains (conn,
2101
                                              ret->ids.ids_val, args->maxids);
2102 2103
    if (ret->ids.ids_len == -1) {
        VIR_FREE(ret->ids.ids_val);
2104
        remoteDispatchConnError(rerr, conn);
2105 2106
        return -1;
    }
2107 2108 2109 2110 2111

    return 0;
}

static int
2112
remoteDispatchListNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2113 2114
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2115
                            remote_error *rerr,
2116 2117 2118 2119 2120
                            remote_list_networks_args *args,
                            remote_list_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2121 2122 2123
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2124 2125 2126
    }

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

    ret->names.names_len =
2133
        virConnectListNetworks (conn,
2134
                                ret->names.names_val, args->maxnames);
2135 2136
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
2137
        remoteDispatchConnError(rerr, conn);
2138 2139
        return -1;
    }
2140 2141 2142 2143 2144

    return 0;
}

static int
2145
remoteDispatchNetworkCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
2146 2147
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2148
                             remote_error *rerr,
2149 2150 2151 2152 2153
                             remote_network_create_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

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

2160 2161
    if (virNetworkCreate (net) == -1) {
        virNetworkFree(net);
2162
        remoteDispatchConnError(rerr, conn);
2163
        return -1;
2164 2165
    }
    virNetworkFree(net);
2166 2167 2168 2169
    return 0;
}

static int
2170
remoteDispatchNetworkCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2171 2172
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2173
                                remote_error *rerr,
2174 2175 2176 2177 2178
                                remote_network_create_xml_args *args,
                                remote_network_create_xml_ret *ret)
{
    virNetworkPtr net;

2179
    net = virNetworkCreateXML (conn, args->xml);
2180
    if (net == NULL) {
2181
        remoteDispatchConnError(rerr, conn);
2182 2183
        return -1;
    }
2184 2185

    make_nonnull_network (&ret->net, net);
2186
    virNetworkFree(net);
2187 2188 2189 2190
    return 0;
}

static int
2191
remoteDispatchNetworkDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2192 2193
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2194
                                remote_error *rerr,
2195 2196 2197 2198 2199
                                remote_network_define_xml_args *args,
                                remote_network_define_xml_ret *ret)
{
    virNetworkPtr net;

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

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

static int
2212
remoteDispatchNetworkDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
2213 2214
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2215
                              remote_error *rerr,
2216 2217 2218 2219 2220
                              remote_network_destroy_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2221
    net = get_nonnull_network (conn, args->net);
2222
    if (net == NULL) {
2223
        remoteDispatchConnError(rerr, conn);
2224
        return -1;
2225 2226
    }

2227 2228
    if (virNetworkDestroy (net) == -1) {
        virNetworkFree(net);
2229
        remoteDispatchConnError(rerr, conn);
2230
        return -1;
2231 2232
    }
    virNetworkFree(net);
2233 2234 2235 2236
    return 0;
}

static int
2237
remoteDispatchNetworkDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2238 2239
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2240
                              remote_error *rerr,
2241 2242 2243 2244 2245
                              remote_network_dump_xml_args *args,
                              remote_network_dump_xml_ret *ret)
{
    virNetworkPtr net;

2246
    net = get_nonnull_network (conn, args->net);
2247
    if (net == NULL) {
2248
        remoteDispatchConnError(rerr, conn);
2249
        return -1;
2250 2251 2252 2253
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNetworkGetXMLDesc (net, args->flags);
2254 2255
    if (!ret->xml) {
        virNetworkFree(net);
2256
        remoteDispatchConnError(rerr, conn);
2257 2258 2259
        return -1;
    }
    virNetworkFree(net);
2260 2261 2262 2263
    return 0;
}

static int
2264
remoteDispatchNetworkGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2265 2266
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2267
                                   remote_error *rerr,
2268 2269 2270 2271 2272
                                   remote_network_get_autostart_args *args,
                                   remote_network_get_autostart_ret *ret)
{
    virNetworkPtr net;

2273
    net = get_nonnull_network (conn, args->net);
2274
    if (net == NULL) {
2275
        remoteDispatchConnError(rerr, conn);
2276
        return -1;
2277 2278
    }

2279 2280
    if (virNetworkGetAutostart (net, &ret->autostart) == -1) {
        virNetworkFree(net);
2281
        remoteDispatchConnError(rerr, conn);
2282
        return -1;
2283 2284
    }
    virNetworkFree(net);
2285 2286 2287 2288
    return 0;
}

static int
2289
remoteDispatchNetworkGetBridgeName (struct qemud_server *server ATTRIBUTE_UNUSED,
2290 2291
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2292
                                    remote_error *rerr,
2293 2294 2295 2296 2297
                                    remote_network_get_bridge_name_args *args,
                                    remote_network_get_bridge_name_ret *ret)
{
    virNetworkPtr net;

2298
    net = get_nonnull_network (conn, args->net);
2299
    if (net == NULL) {
2300
        remoteDispatchConnError(rerr, conn);
2301
        return -1;
2302 2303 2304 2305
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virNetworkGetBridgeName (net);
2306 2307
    if (!ret->name) {
        virNetworkFree(net);
2308
        remoteDispatchConnError(rerr, conn);
2309 2310 2311
        return -1;
    }
    virNetworkFree(net);
2312 2313 2314 2315
    return 0;
}

static int
2316
remoteDispatchNetworkLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
2317 2318
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2319
                                   remote_error *rerr,
2320 2321 2322 2323 2324
                                   remote_network_lookup_by_name_args *args,
                                   remote_network_lookup_by_name_ret *ret)
{
    virNetworkPtr net;

2325
    net = virNetworkLookupByName (conn, args->name);
2326
    if (net == NULL) {
2327
        remoteDispatchConnError(rerr, conn);
2328 2329
        return -1;
    }
2330 2331

    make_nonnull_network (&ret->net, net);
2332
    virNetworkFree(net);
2333 2334 2335 2336
    return 0;
}

static int
2337
remoteDispatchNetworkLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
2338 2339
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2340
                                   remote_error *rerr,
2341 2342 2343 2344 2345
                                   remote_network_lookup_by_uuid_args *args,
                                   remote_network_lookup_by_uuid_ret *ret)
{
    virNetworkPtr net;

2346
    net = virNetworkLookupByUUID (conn, (unsigned char *) args->uuid);
2347
    if (net == NULL) {
2348
        remoteDispatchConnError(rerr, conn);
2349 2350
        return -1;
    }
2351 2352

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

static int
2358
remoteDispatchNetworkSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2359 2360
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2361
                                   remote_error *rerr,
2362 2363 2364 2365 2366
                                   remote_network_set_autostart_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2367
    net = get_nonnull_network (conn, args->net);
2368
    if (net == NULL) {
2369
        remoteDispatchConnError(rerr, conn);
2370
        return -1;
2371 2372
    }

2373 2374
    if (virNetworkSetAutostart (net, args->autostart) == -1) {
        virNetworkFree(net);
2375
        remoteDispatchConnError(rerr, conn);
2376
        return -1;
2377 2378
    }
    virNetworkFree(net);
2379 2380 2381 2382
    return 0;
}

static int
2383
remoteDispatchNetworkUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2384 2385
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2386
                               remote_error *rerr,
2387 2388 2389 2390 2391
                               remote_network_undefine_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2392
    net = get_nonnull_network (conn, args->net);
2393
    if (net == NULL) {
2394
        remoteDispatchConnError(rerr, conn);
2395
        return -1;
2396 2397
    }

2398 2399
    if (virNetworkUndefine (net) == -1) {
        virNetworkFree(net);
2400
        remoteDispatchConnError(rerr, conn);
2401
        return -1;
2402 2403
    }
    virNetworkFree(net);
2404 2405 2406 2407
    return 0;
}

static int
2408
remoteDispatchNumOfDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2409 2410
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2411
                                    remote_error *rerr,
2412 2413 2414 2415
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_num_of_defined_networks_ret *ret)
{

2416
    ret->num = virConnectNumOfDefinedNetworks (conn);
2417
    if (ret->num == -1) {
2418
        remoteDispatchConnError(rerr, conn);
2419 2420
        return -1;
    }
2421 2422 2423 2424 2425

    return 0;
}

static int
2426
remoteDispatchNumOfDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2427 2428
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
2429
                            remote_error *rerr,
2430 2431 2432 2433
                            void *args ATTRIBUTE_UNUSED,
                            remote_num_of_domains_ret *ret)
{

2434
    ret->num = virConnectNumOfDomains (conn);
2435
    if (ret->num == -1) {
2436
        remoteDispatchConnError(rerr, conn);
2437 2438
        return -1;
    }
2439 2440 2441 2442 2443

    return 0;
}

static int
2444
remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2445 2446
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2447
                             remote_error *rerr,
2448 2449 2450 2451
                             void *args ATTRIBUTE_UNUSED,
                             remote_num_of_networks_ret *ret)
{

2452
    ret->num = virConnectNumOfNetworks (conn);
2453
    if (ret->num == -1) {
2454
        remoteDispatchConnError(rerr, conn);
2455 2456
        return -1;
    }
2457 2458 2459 2460

    return 0;
}

2461 2462

static int
2463
remoteDispatchAuthList (struct qemud_server *server,
2464
                        struct qemud_client *client,
2465
                        virConnectPtr conn ATTRIBUTE_UNUSED,
2466
                        remote_error *rerr,
2467 2468 2469 2470
                        void *args ATTRIBUTE_UNUSED,
                        remote_auth_list_ret *ret)
{
    ret->types.types_len = 1;
2471
    if (VIR_ALLOC_N(ret->types.types_val, ret->types.types_len) < 0) {
2472 2473
        remoteDispatchOOMError(rerr);
        return -1;
2474
    }
2475 2476 2477
    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);
2478
    ret->types.types_val[0] = client->auth;
2479 2480
    pthread_mutex_unlock(&client->lock);

2481 2482 2483 2484 2485 2486 2487 2488
    return 0;
}


#if HAVE_SASL
/*
 * NB, keep in sync with similar method in src/remote_internal.c
 */
2489
static char *addrToString(remote_error *rerr,
2490 2491 2492 2493 2494 2495 2496 2497 2498
                          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) {
2499 2500 2501
        remoteDispatchFormatError(rerr,
                                  _("Cannot resolve address %d: %s"),
                                  err, gai_strerror(err));
2502 2503 2504
        return NULL;
    }

2505
    if (VIR_ALLOC_N(addr, strlen(host) + 1 + strlen(port) + 1) < 0) {
2506
        remoteDispatchOOMError(rerr);
2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518
        return NULL;
    }

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


/*
 * Initializes the SASL session in prepare for authentication
2519
 * and gives the client a list of allowed mechanisms to choose
2520 2521 2522 2523
 *
 * XXX callbacks for stuff like password verification ?
 */
static int
2524
remoteDispatchAuthSaslInit (struct qemud_server *server,
2525
                            struct qemud_client *client,
2526
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2527
                            remote_error *rerr,
2528 2529 2530 2531
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret)
{
    const char *mechlist = NULL;
2532
    sasl_security_properties_t secprops;
2533 2534 2535 2536 2537
    int err;
    struct sockaddr_storage sa;
    socklen_t salen;
    char *localAddr, *remoteAddr;

2538 2539 2540 2541
    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);

2542 2543 2544
    REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn != NULL) {
2545
        VIR_ERROR0(_("client tried invalid SASL init request"));
2546
        goto authfail;
2547 2548 2549 2550 2551
    }

    /* Get local address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getsockname(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
2552 2553 2554
        remoteDispatchFormatError(rerr,
                                  _("failed to get sock address %d (%s)"),
                                  errno, strerror(errno));
2555
        goto error;
2556
    }
2557
    if ((localAddr = addrToString(rerr, &sa, salen)) == NULL) {
2558
        goto error;
2559 2560 2561 2562 2563
    }

    /* Get remote address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getpeername(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
2564 2565
        remoteDispatchFormatError(rerr, _("failed to get peer address %d (%s)"),
                                  errno, strerror(errno));
2566
        VIR_FREE(localAddr);
2567
        goto error;
2568
    }
2569
    if ((remoteAddr = addrToString(rerr, &sa, salen)) == NULL) {
2570
        VIR_FREE(localAddr);
2571
        goto error;
2572 2573 2574 2575 2576 2577 2578 2579 2580 2581
    }

    err = sasl_server_new("libvirt",
                          NULL, /* FQDN - just delegates to gethostname */
                          NULL, /* User realm */
                          localAddr,
                          remoteAddr,
                          NULL, /* XXX Callbacks */
                          SASL_SUCCESS_DATA,
                          &client->saslconn);
2582 2583
    VIR_FREE(localAddr);
    VIR_FREE(remoteAddr);
2584
    if (err != SASL_OK) {
2585 2586
        VIR_ERROR(_("sasl context setup failed %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2587
        client->saslconn = NULL;
2588
        goto authfail;
2589 2590
    }

2591 2592 2593 2594 2595 2596 2597
    /* 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))) {
2598
            VIR_ERROR0(_("cannot TLS get cipher size"));
2599 2600
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
2601
            goto authfail;
2602 2603 2604 2605 2606
        }
        ssf *= 8; /* tls key size is bytes, sasl wants bits */

        err = sasl_setprop(client->saslconn, SASL_SSF_EXTERNAL, &ssf);
        if (err != SASL_OK) {
2607 2608
            VIR_ERROR(_("cannot set SASL external SSF %d (%s)"),
                      err, sasl_errstring(err, NULL, NULL));
2609 2610
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
2611
            goto authfail;
2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634
        }
    }

    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) {
2635 2636
        VIR_ERROR(_("cannot set SASL security props %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2637 2638
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2639
        goto authfail;
2640 2641
    }

2642 2643 2644 2645 2646 2647 2648 2649 2650
    err = sasl_listmech(client->saslconn,
                        NULL, /* Don't need to set user */
                        "", /* Prefix */
                        ",", /* Separator */
                        "", /* Suffix */
                        &mechlist,
                        NULL,
                        NULL);
    if (err != SASL_OK) {
2651 2652
        VIR_ERROR(_("cannot list SASL mechanisms %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
2653 2654
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2655
        goto authfail;
2656 2657 2658 2659
    }
    REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist);
    ret->mechlist = strdup(mechlist);
    if (!ret->mechlist) {
2660
        VIR_ERROR0(_("cannot allocate mechlist"));
2661 2662
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2663
        goto authfail;
2664 2665
    }

2666
    pthread_mutex_unlock(&client->lock);
2667
    return 0;
2668 2669 2670 2671 2672 2673

authfail:
    remoteDispatchAuthError(rerr);
error:
    pthread_mutex_unlock(&client->lock);
    return -1;
2674 2675 2676
}


2677
/* We asked for an SSF layer, so sanity check that we actually
2678 2679 2680
 * got what we asked for */
static int
remoteSASLCheckSSF (struct qemud_client *client,
2681
                    remote_error *rerr) {
2682 2683 2684 2685 2686 2687 2688 2689 2690
    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) {
2691 2692
        VIR_ERROR(_("cannot query SASL ssf on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2693
        remoteDispatchAuthError(rerr);
2694 2695 2696 2697 2698 2699 2700
        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 */
2701
        VIR_ERROR(_("negotiated SSF %d was not strong enough"), ssf);
2702
        remoteDispatchAuthError(rerr);
2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719
        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;
}

2720 2721 2722
static int
remoteSASLCheckAccess (struct qemud_server *server,
                       struct qemud_client *client,
2723
                       remote_error *rerr) {
2724 2725 2726 2727 2728 2729
    const void *val;
    int err;
    char **wildcards;

    err = sasl_getprop(client->saslconn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
2730 2731
        VIR_ERROR(_("cannot query SASL username on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2732
        remoteDispatchAuthError(rerr);
2733 2734 2735 2736 2737
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    if (val == NULL) {
2738
        VIR_ERROR0(_("no client username was found"));
2739
        remoteDispatchAuthError(rerr);
2740 2741 2742 2743 2744 2745 2746 2747
        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) {
2748
        VIR_ERROR0(_("out of memory copying username"));
2749
        remoteDispatchAuthError(rerr);
2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766
        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 */
2767
    VIR_ERROR(_("SASL client %s not allowed in whitelist"), client->saslUsername);
2768
    remoteDispatchAuthError(rerr);
2769 2770 2771 2772 2773 2774
    sasl_dispose(&client->saslconn);
    client->saslconn = NULL;
    return -1;
}


2775 2776 2777 2778
/*
 * This starts the SASL authentication negotiation.
 */
static int
2779 2780
remoteDispatchAuthSaslStart (struct qemud_server *server,
                             struct qemud_client *client,
2781
                             virConnectPtr conn ATTRIBUTE_UNUSED,
2782
                             remote_error *rerr,
2783 2784 2785 2786 2787 2788 2789
                             remote_auth_sasl_start_args *args,
                             remote_auth_sasl_start_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

2790 2791 2792 2793
    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);

2794 2795 2796
    REMOTE_DEBUG("Start SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
2797
        VIR_ERROR0(_("client tried invalid SASL start request"));
2798
        goto authfail;
2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811
    }

    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) {
2812 2813
        VIR_ERROR(_("sasl start failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
2814 2815
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2816
        goto authfail;
2817 2818
    }
    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
2819
        VIR_ERROR(_("sasl start reply data too long %d"), serveroutlen);
2820 2821
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2822
        goto authfail;
2823 2824 2825 2826
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
2827
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
2828
            remoteDispatchOOMError(rerr);
2829
            goto error;
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841
        }
        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 {
2842
        if (remoteSASLCheckSSF(client, rerr) < 0)
2843
            goto error;
2844

2845
        /* Check username whitelist ACL */
2846
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
2847
            goto error;
2848

2849 2850 2851 2852 2853
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

2854
    pthread_mutex_unlock(&client->lock);
2855
    return 0;
2856 2857 2858 2859 2860 2861

authfail:
    remoteDispatchAuthError(rerr);
error:
    pthread_mutex_unlock(&client->lock);
    return -1;
2862 2863 2864 2865
}


static int
2866 2867
remoteDispatchAuthSaslStep (struct qemud_server *server,
                            struct qemud_client *client,
2868
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2869
                            remote_error *rerr,
2870 2871 2872 2873 2874 2875 2876
                            remote_auth_sasl_step_args *args,
                            remote_auth_sasl_step_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

2877 2878 2879 2880
    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);

2881 2882 2883
    REMOTE_DEBUG("Step SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
2884
        VIR_ERROR0(_("client tried invalid SASL start request"));
2885
        goto authfail;
2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897
    }

    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) {
2898 2899
        VIR_ERROR(_("sasl step failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
2900 2901
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2902
        goto authfail;
2903 2904 2905
    }

    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
2906 2907
        VIR_ERROR(_("sasl step reply data too long %d"),
                  serveroutlen);
2908 2909
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2910
        goto authfail;
2911 2912 2913 2914
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
2915
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
2916
            remoteDispatchOOMError(rerr);
2917
            goto error;
2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929
        }
        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 {
2930
        if (remoteSASLCheckSSF(client, rerr) < 0)
2931
            goto error;
2932

2933
        /* Check username whitelist ACL */
2934
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
2935
            goto error;
2936

2937 2938 2939 2940 2941
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

2942
    pthread_mutex_unlock(&client->lock);
2943
    return 0;
2944 2945 2946 2947 2948 2949

authfail:
    remoteDispatchAuthError(rerr);
error:
    pthread_mutex_unlock(&client->lock);
    return -1;
2950 2951 2952 2953 2954
}


#else /* HAVE_SASL */
static int
2955
remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED,
2956 2957
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2958
                            remote_error *rerr,
2959 2960 2961
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED)
{
2962
    VIR_ERROR0(_("client tried unsupported SASL init request"));
2963
    remoteDispatchAuthError(rerr);
2964 2965 2966 2967
    return -1;
}

static int
2968
remoteDispatchAuthSaslStart (struct qemud_server *server ATTRIBUTE_UNUSED,
2969 2970
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn ATTRIBUTE_UNUSED,
2971
                             remote_error *rerr,
2972 2973 2974
                             remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED,
                             remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED)
{
2975
    VIR_ERROR0(_("client tried unsupported SASL start request"));
2976
    remoteDispatchAuthError(rerr);
2977 2978 2979 2980
    return -1;
}

static int
2981
remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
2982 2983
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2984
                            remote_error *rerr,
2985 2986 2987
                            remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED)
{
2988
    VIR_ERROR0(_("client tried unsupported SASL step request"));
2989
    remoteDispatchAuthError(rerr);
2990 2991 2992 2993 2994
    return -1;
}
#endif /* HAVE_SASL */


2995 2996
#if HAVE_POLKIT
static int
2997
remoteDispatchAuthPolkit (struct qemud_server *server,
2998
                          struct qemud_client *client,
2999
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3000
                          remote_error *rerr,
3001 3002 3003 3004 3005
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
    pid_t callerPid;
    uid_t callerUid;
3006 3007 3008 3009 3010 3011
    PolKitCaller *pkcaller = NULL;
    PolKitAction *pkaction = NULL;
    PolKitContext *pkcontext = NULL;
    PolKitError *pkerr = NULL;
    PolKitResult pkresult;
    DBusError err;
3012 3013 3014 3015 3016 3017 3018
    const char *action;

    pthread_mutex_lock(&server->lock);
    pthread_mutex_lock(&client->lock);
    pthread_mutex_unlock(&server->lock);

    action = client->readonly ?
3019 3020
        "org.libvirt.unix.monitor" :
        "org.libvirt.unix.manage";
3021 3022 3023

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

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

3033
    VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
3034 3035 3036
    dbus_error_init(&err);
    if (!(pkcaller = polkit_caller_new_from_pid(server->sysbus,
                                                callerPid, &err))) {
3037
        VIR_ERROR(_("Failed to lookup policy kit caller: %s"), err.message);
3038
        dbus_error_free(&err);
3039
        goto authfail;
3040
    }
3041

3042
    if (!(pkaction = polkit_action_new())) {
3043
        VIR_ERROR(_("Failed to create polkit action %s\n"), strerror(errno));
3044
        polkit_caller_unref(pkcaller);
3045
        goto authfail;
3046 3047 3048 3049 3050
    }
    polkit_action_set_action_id(pkaction, action);

    if (!(pkcontext = polkit_context_new()) ||
        !polkit_context_init(pkcontext, &pkerr)) {
3051 3052 3053
        VIR_ERROR(_("Failed to create polkit context %s\n"),
                  (pkerr ? polkit_error_get_error_message(pkerr)
                   : strerror(errno)));
3054 3055 3056 3057 3058
        if (pkerr)
            polkit_error_free(pkerr);
        polkit_caller_unref(pkcaller);
        polkit_action_unref(pkaction);
        dbus_error_free(&err);
3059
        goto authfail;
3060
    }
3061

3062
#if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
3063 3064 3065 3066 3067 3068
    pkresult = polkit_context_is_caller_authorized(pkcontext,
                                                   pkaction,
                                                   pkcaller,
                                                   0,
                                                   &pkerr);
    if (pkerr && polkit_error_is_set(pkerr)) {
3069 3070 3071
        VIR_ERROR(_("Policy kit failed to check authorization %d %s"),
                  polkit_error_get_error_code(pkerr),
                  polkit_error_get_error_message(pkerr));
3072
        goto authfail;
3073
    }
3074
#else
3075 3076 3077
    pkresult = polkit_context_can_caller_do_action(pkcontext,
                                                   pkaction,
                                                   pkcaller);
3078
#endif
3079 3080 3081 3082
    polkit_context_unref(pkcontext);
    polkit_caller_unref(pkcaller);
    polkit_action_unref(pkaction);
    if (pkresult != POLKIT_RESULT_YES) {
3083 3084 3085
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %s\n"),
                  action, callerPid, callerUid,
                  polkit_result_to_string_representation(pkresult));
3086
        goto authfail;
3087
    }
3088
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d, result %s"),
3089 3090 3091 3092
             action, callerPid, callerUid,
             polkit_result_to_string_representation(pkresult));
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;
3093

3094
    pthread_mutex_unlock(&client->lock);
3095
    return 0;
3096 3097 3098 3099 3100

authfail:
    remoteDispatchAuthError(rerr);
    pthread_mutex_unlock(&client->lock);
    return -1;
3101 3102 3103 3104 3105
}

#else /* HAVE_POLKIT */

static int
3106
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
3107
                          struct qemud_client *client ATTRIBUTE_UNUSED,
3108
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3109 3110 3111
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED)
3112
{
3113
    VIR_ERROR0(_("client tried unsupported PolicyKit init request"));
3114
    remoteDispatchAuthError(rerr);
3115 3116 3117 3118
    return -1;
}
#endif /* HAVE_POLKIT */

3119 3120 3121 3122 3123 3124 3125 3126

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


static int
remoteDispatchListDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3127 3128
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3129
                                       remote_error *rerr,
3130 3131 3132 3133 3134
                                       remote_list_defined_storage_pools_args *args,
                                       remote_list_defined_storage_pools_ret *ret)
{

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

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

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

    return 0;
}

static int
remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3160 3161
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3162
                                remote_error *rerr,
3163 3164 3165 3166 3167
                                remote_list_storage_pools_args *args,
                                remote_list_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
3168 3169 3170
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX"));
        return -1;
3171 3172 3173
    }

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

    ret->names.names_len =
3180
        virConnectListStoragePools (conn,
3181
                                ret->names.names_val, args->maxnames);
3182 3183
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3184
        remoteDispatchConnError(rerr, conn);
3185 3186
        return -1;
    }
3187 3188 3189 3190

    return 0;
}

3191 3192
static int
remoteDispatchFindStoragePoolSources (struct qemud_server *server ATTRIBUTE_UNUSED,
3193 3194
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3195
                                      remote_error *rerr,
3196 3197 3198 3199
                                      remote_find_storage_pool_sources_args *args,
                                      remote_find_storage_pool_sources_ret *ret)
{
    ret->xml =
3200
        virConnectFindStoragePoolSources (conn,
3201 3202 3203
                                          args->type,
                                          args->srcSpec ? *args->srcSpec : NULL,
                                          args->flags);
3204
    if (ret->xml == NULL) {
3205
        remoteDispatchConnError(rerr, conn);
3206
        return -1;
3207
    }
3208 3209 3210 3211 3212

    return 0;
}


3213 3214
static int
remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
3215 3216
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3217
                                 remote_error *rerr,
3218 3219 3220 3221 3222
                                 remote_storage_pool_create_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3223
    pool = get_nonnull_storage_pool (conn, args->pool);
3224
    if (pool == NULL) {
3225
        remoteDispatchConnError(rerr, conn);
3226
        return -1;
3227 3228 3229 3230
    }

    if (virStoragePoolCreate (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3231
        remoteDispatchConnError(rerr, conn);
3232 3233 3234 3235 3236 3237 3238 3239
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3240 3241
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3242
                                    remote_error *rerr,
3243 3244 3245 3246 3247
                                    remote_storage_pool_create_xml_args *args,
                                    remote_storage_pool_create_xml_ret *ret)
{
    virStoragePoolPtr pool;

3248
    pool = virStoragePoolCreateXML (conn, args->xml, args->flags);
3249
    if (pool == NULL) {
3250
        remoteDispatchConnError(rerr, conn);
3251 3252
        return -1;
    }
3253 3254 3255 3256 3257 3258 3259 3260

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

static int
remoteDispatchStoragePoolDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3261 3262
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3263
                                    remote_error *rerr,
3264 3265 3266 3267 3268
                                    remote_storage_pool_define_xml_args *args,
                                    remote_storage_pool_define_xml_ret *ret)
{
    virStoragePoolPtr pool;

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

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

static int
remoteDispatchStoragePoolBuild (struct qemud_server *server ATTRIBUTE_UNUSED,
3282 3283
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3284 3285 3286
                                remote_error *rerr,
                                remote_storage_pool_build_args *args,
                                void *ret ATTRIBUTE_UNUSED)
3287 3288 3289
{
    virStoragePoolPtr pool;

3290
    pool = get_nonnull_storage_pool (conn, args->pool);
3291
    if (pool == NULL) {
3292
        remoteDispatchConnError(rerr, conn);
3293
        return -1;
3294 3295 3296 3297
    }

    if (virStoragePoolBuild (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3298
        remoteDispatchConnError(rerr, conn);
3299 3300 3301 3302 3303 3304 3305 3306 3307
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
3308 3309
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3310
                                  remote_error *rerr,
3311 3312 3313 3314 3315
                                  remote_storage_pool_destroy_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

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

    if (virStoragePoolDestroy (pool) == -1) {
        virStoragePoolFree(pool);
3324
        remoteDispatchConnError(rerr, conn);
3325 3326 3327 3328 3329 3330 3331 3332
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
3333 3334
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3335
                                 remote_error *rerr,
3336 3337 3338 3339 3340
                                 remote_storage_pool_delete_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

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

    if (virStoragePoolDelete (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3349
        remoteDispatchConnError(rerr, conn);
3350 3351 3352 3353 3354 3355 3356 3357
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolRefresh (struct qemud_server *server ATTRIBUTE_UNUSED,
3358 3359
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3360
                                  remote_error *rerr,
3361 3362 3363 3364 3365
                                  remote_storage_pool_refresh_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

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

    if (virStoragePoolRefresh (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3374
        remoteDispatchConnError(rerr, conn);
3375 3376 3377 3378 3379 3380 3381 3382
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
3383 3384
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3385
                                  remote_error *rerr,
3386 3387 3388 3389 3390 3391
                                  remote_storage_pool_get_info_args *args,
                                  remote_storage_pool_get_info_ret *ret)
{
    virStoragePoolPtr pool;
    virStoragePoolInfo info;

3392
    pool = get_nonnull_storage_pool (conn, args->pool);
3393
    if (pool == NULL) {
3394
        remoteDispatchConnError(rerr, conn);
3395
        return -1;
3396 3397 3398 3399
    }

    if (virStoragePoolGetInfo (pool, &info) == -1) {
        virStoragePoolFree(pool);
3400
        remoteDispatchConnError(rerr, conn);
3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415
        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,
3416 3417
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3418
                                  remote_error *rerr,
3419 3420 3421 3422 3423
                                  remote_storage_pool_dump_xml_args *args,
                                  remote_storage_pool_dump_xml_ret *ret)
{
    virStoragePoolPtr pool;

3424
    pool = get_nonnull_storage_pool (conn, args->pool);
3425
    if (pool == NULL) {
3426
        remoteDispatchConnError(rerr, conn);
3427
        return -1;
3428 3429 3430 3431 3432 3433
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStoragePoolGetXMLDesc (pool, args->flags);
    if (!ret->xml) {
        virStoragePoolFree(pool);
3434
        remoteDispatchConnError(rerr, conn);
3435 3436 3437 3438 3439 3440 3441 3442
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
3443 3444
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3445
                                       remote_error *rerr,
3446 3447 3448 3449 3450
                                       remote_storage_pool_get_autostart_args *args,
                                       remote_storage_pool_get_autostart_ret *ret)
{
    virStoragePoolPtr pool;

3451
    pool = get_nonnull_storage_pool (conn, args->pool);
3452
    if (pool == NULL) {
3453
        remoteDispatchConnError(rerr, conn);
3454
        return -1;
3455 3456 3457 3458
    }

    if (virStoragePoolGetAutostart (pool, &ret->autostart) == -1) {
        virStoragePoolFree(pool);
3459
        remoteDispatchConnError(rerr, conn);
3460 3461 3462 3463 3464 3465 3466 3467 3468
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
3469 3470
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3471
                                       remote_error *rerr,
3472 3473 3474 3475 3476
                                       remote_storage_pool_lookup_by_name_args *args,
                                       remote_storage_pool_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;

3477
    pool = virStoragePoolLookupByName (conn, args->name);
3478
    if (pool == NULL) {
3479
        remoteDispatchConnError(rerr, conn);
3480 3481
        return -1;
    }
3482 3483 3484 3485 3486 3487 3488 3489

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

static int
remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
3490 3491
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3492
                                       remote_error *rerr,
3493 3494 3495 3496 3497
                                       remote_storage_pool_lookup_by_uuid_args *args,
                                       remote_storage_pool_lookup_by_uuid_ret *ret)
{
    virStoragePoolPtr pool;

3498
    pool = virStoragePoolLookupByUUID (conn, (unsigned char *) args->uuid);
3499
    if (pool == NULL) {
3500
        remoteDispatchConnError(rerr, conn);
3501 3502
        return -1;
    }
3503 3504 3505 3506 3507 3508 3509 3510

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

static int
remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server ATTRIBUTE_UNUSED,
3511 3512
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
3513
                                         remote_error *rerr,
3514 3515 3516 3517 3518 3519
                                         remote_storage_pool_lookup_by_volume_args *args,
                                         remote_storage_pool_lookup_by_volume_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

3520
    vol = get_nonnull_storage_vol (conn, args->vol);
3521
    if (vol == NULL) {
3522
        remoteDispatchConnError(rerr, conn);
3523 3524
        return -1;
    }
3525 3526 3527

    pool = virStoragePoolLookupByVolume (vol);
    virStorageVolFree(vol);
3528
    if (pool == NULL) {
3529
        remoteDispatchConnError(rerr, conn);
3530 3531
        return -1;
    }
3532 3533 3534 3535 3536 3537 3538 3539

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

static int
remoteDispatchStoragePoolSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
3540 3541
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3542
                                       remote_error *rerr,
3543 3544 3545 3546 3547
                                       remote_storage_pool_set_autostart_args *args,
                                       void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3548
    pool = get_nonnull_storage_pool (conn, args->pool);
3549
    if (pool == NULL) {
3550
        remoteDispatchConnError(rerr, conn);
3551
        return -1;
3552 3553 3554 3555
    }

    if (virStoragePoolSetAutostart (pool, args->autostart) == -1) {
        virStoragePoolFree(pool);
3556
        remoteDispatchConnError(rerr, conn);
3557 3558 3559 3560 3561 3562 3563 3564
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
3565 3566
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
3567
                                   remote_error *rerr,
3568 3569 3570 3571 3572
                                   remote_storage_pool_undefine_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

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

    if (virStoragePoolUndefine (pool) == -1) {
        virStoragePoolFree(pool);
3581
        remoteDispatchConnError(rerr, conn);
3582 3583 3584 3585 3586 3587 3588 3589
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchNumOfStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3590 3591
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3592
                                 remote_error *rerr,
3593 3594 3595 3596
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_num_of_storage_pools_ret *ret)
{

3597
    ret->num = virConnectNumOfStoragePools (conn);
3598
    if (ret->num == -1) {
3599
        remoteDispatchConnError(rerr, conn);
3600 3601
        return -1;
    }
3602 3603 3604 3605 3606 3607

    return 0;
}

static int
remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3608 3609
                                        struct qemud_client *client ATTRIBUTE_UNUSED,
                                        virConnectPtr conn,
3610
                                        remote_error *rerr,
3611 3612 3613 3614
                                        void *args ATTRIBUTE_UNUSED,
                                        remote_num_of_defined_storage_pools_ret *ret)
{

3615
    ret->num = virConnectNumOfDefinedStoragePools (conn);
3616
    if (ret->num == -1) {
3617
        remoteDispatchConnError(rerr, conn);
3618 3619
        return -1;
    }
3620 3621 3622 3623 3624 3625

    return 0;
}

static int
remoteDispatchStoragePoolListVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
3626 3627
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3628
                                      remote_error *rerr,
3629 3630 3631 3632 3633 3634
                                      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) {
3635 3636 3637
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX"));
        return -1;
3638 3639
    }

3640
    pool = get_nonnull_storage_pool (conn, args->pool);
3641
    if (pool == NULL) {
3642
        remoteDispatchConnError(rerr, conn);
3643
        return -1;
3644 3645 3646
    }

    /* Allocate return buffer. */
3647 3648
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        virStoragePoolFree(pool);
3649 3650
        remoteDispatchOOMError(rerr);
        return -1;
3651
    }
3652 3653 3654 3655 3656

    ret->names.names_len =
        virStoragePoolListVolumes (pool,
                                   ret->names.names_val, args->maxnames);
    virStoragePoolFree(pool);
3657 3658
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3659
        remoteDispatchConnError(rerr, conn);
3660 3661
        return -1;
    }
3662 3663 3664 3665 3666 3667 3668

    return 0;
}


static int
remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
3669 3670
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3671
                                       remote_error *rerr,
3672 3673 3674 3675 3676
                                       remote_storage_pool_num_of_volumes_args *args,
                                       remote_storage_pool_num_of_volumes_ret *ret)
{
    virStoragePoolPtr pool;

3677
    pool = get_nonnull_storage_pool (conn, args->pool);
3678
    if (pool == NULL) {
3679
        remoteDispatchConnError(rerr, conn);
3680
        return -1;
3681 3682 3683 3684
    }

    ret->num = virStoragePoolNumOfVolumes (pool);
    virStoragePoolFree(pool);
3685
    if (ret->num == -1) {
3686
        remoteDispatchConnError(rerr, conn);
3687 3688
        return -1;
    }
3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701

    return 0;
}


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



static int
remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3702 3703
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
3704
                                   remote_error *rerr,
3705 3706 3707 3708 3709 3710
                                   remote_storage_vol_create_xml_args *args,
                                   remote_storage_vol_create_xml_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

3711
    pool = get_nonnull_storage_pool (conn, args->pool);
3712
    if (pool == NULL) {
3713
        remoteDispatchConnError(rerr, conn);
3714
        return -1;
3715 3716 3717 3718
    }

    vol = virStorageVolCreateXML (pool, args->xml, args->flags);
    virStoragePoolFree(pool);
3719
    if (vol == NULL) {
3720
        remoteDispatchConnError(rerr, conn);
3721 3722
        return -1;
    }
3723 3724 3725 3726 3727 3728 3729 3730 3731

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


static int
remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
3732 3733
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3734
                                remote_error *rerr,
3735 3736 3737 3738 3739
                                remote_storage_vol_delete_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virStorageVolPtr vol;

3740
    vol = get_nonnull_storage_vol (conn, args->vol);
3741
    if (vol == NULL) {
3742
        remoteDispatchConnError(rerr, conn);
3743
        return -1;
3744 3745 3746 3747
    }

    if (virStorageVolDelete (vol, args->flags) == -1) {
        virStorageVolFree(vol);
3748
        remoteDispatchConnError(rerr, conn);
3749 3750 3751 3752 3753 3754 3755 3756
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}

static int
remoteDispatchStorageVolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
3757 3758
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3759
                                 remote_error *rerr,
3760 3761 3762 3763 3764 3765
                                 remote_storage_vol_get_info_args *args,
                                 remote_storage_vol_get_info_ret *ret)
{
    virStorageVolPtr vol;
    virStorageVolInfo info;

3766
    vol = get_nonnull_storage_vol (conn, args->vol);
3767
    if (vol == NULL) {
3768
        remoteDispatchConnError(rerr, conn);
3769
        return -1;
3770 3771 3772 3773
    }

    if (virStorageVolGetInfo (vol, &info) == -1) {
        virStorageVolFree(vol);
3774
        remoteDispatchConnError(rerr, conn);
3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788
        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,
3789 3790
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3791
                                 remote_error *rerr,
3792 3793 3794 3795 3796
                                 remote_storage_vol_dump_xml_args *args,
                                 remote_storage_vol_dump_xml_ret *ret)
{
    virStorageVolPtr vol;

3797
    vol = get_nonnull_storage_vol (conn, args->vol);
3798
    if (vol == NULL) {
3799
        remoteDispatchConnError(rerr, conn);
3800
        return -1;
3801 3802 3803 3804 3805 3806
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStorageVolGetXMLDesc (vol, args->flags);
    if (!ret->xml) {
        virStorageVolFree(vol);
3807
        remoteDispatchConnError(rerr, conn);
3808 3809 3810 3811 3812 3813 3814 3815 3816
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolGetPath (struct qemud_server *server ATTRIBUTE_UNUSED,
3817 3818
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3819
                                 remote_error *rerr,
3820 3821 3822 3823 3824
                                 remote_storage_vol_get_path_args *args,
                                 remote_storage_vol_get_path_ret *ret)
{
    virStorageVolPtr vol;

3825
    vol = get_nonnull_storage_vol (conn, args->vol);
3826
    if (vol == NULL) {
3827
        remoteDispatchConnError(rerr, conn);
3828
        return -1;
3829 3830 3831 3832 3833 3834
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virStorageVolGetPath (vol);
    if (!ret->name) {
        virStorageVolFree(vol);
3835
        remoteDispatchConnError(rerr, conn);
3836 3837 3838 3839 3840 3841 3842 3843 3844
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
3845 3846
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3847
                                      remote_error *rerr,
3848 3849 3850 3851 3852 3853
                                      remote_storage_vol_lookup_by_name_args *args,
                                      remote_storage_vol_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

3854
    pool = get_nonnull_storage_pool (conn, args->pool);
3855
    if (pool == NULL) {
3856
        remoteDispatchConnError(rerr, conn);
3857
        return -1;
3858 3859 3860 3861
    }

    vol = virStorageVolLookupByName (pool, args->name);
    virStoragePoolFree(pool);
3862
    if (vol == NULL) {
3863
        remoteDispatchConnError(rerr, conn);
3864 3865
        return -1;
    }
3866 3867 3868 3869 3870 3871 3872 3873

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

static int
remoteDispatchStorageVolLookupByKey (struct qemud_server *server ATTRIBUTE_UNUSED,
3874 3875
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
3876
                                     remote_error *rerr,
3877 3878 3879 3880 3881
                                     remote_storage_vol_lookup_by_key_args *args,
                                     remote_storage_vol_lookup_by_key_ret *ret)
{
    virStorageVolPtr vol;

3882
    vol = virStorageVolLookupByKey (conn, args->key);
3883
    if (vol == NULL) {
3884
        remoteDispatchConnError(rerr, conn);
3885 3886
        return -1;
    }
3887 3888 3889 3890 3891 3892 3893 3894 3895

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


static int
remoteDispatchStorageVolLookupByPath (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_path_args *args,
                                      remote_storage_vol_lookup_by_path_ret *ret)
{
    virStorageVolPtr vol;

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

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


3916 3917 3918 3919 3920 3921
/***************************************************************
 *     NODE INFO APIS
 **************************************************************/

static int
remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
3922 3923
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3924
                                remote_error *rerr,
3925 3926 3927 3928 3929
                                remote_node_num_of_devices_args *args,
                                remote_node_num_of_devices_ret *ret)
{
    CHECK_CONN(client);

3930
    ret->num = virNodeNumOfDevices (conn,
3931 3932
                                    args->cap ? *args->cap : NULL,
                                    args->flags);
3933
    if (ret->num == -1) {
3934
        remoteDispatchConnError(rerr, conn);
3935 3936
        return -1;
    }
3937 3938 3939 3940 3941 3942 3943

    return 0;
}


static int
remoteDispatchNodeListDevices (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 3952
                               remote_node_list_devices_args *args,
                               remote_node_list_devices_ret *ret)
{
    CHECK_CONN(client);

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
3953 3954 3955
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
3956 3957 3958 3959
    }

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

    ret->names.names_len =
3965
        virNodeListDevices (conn,
3966 3967 3968
                            args->cap ? *args->cap : NULL,
                            ret->names.names_val, args->maxnames, args->flags);
    if (ret->names.names_len == -1) {
3969
        remoteDispatchConnError(rerr, conn);
3970 3971 3972 3973 3974 3975 3976 3977 3978 3979
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
3980 3981
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3982
                                      remote_error *rerr,
3983 3984 3985 3986 3987 3988 3989
                                      remote_node_device_lookup_by_name_args *args,
                                      remote_node_device_lookup_by_name_ret *ret)
{
    virNodeDevicePtr dev;

    CHECK_CONN(client);

3990
    dev = virNodeDeviceLookupByName (conn, args->name);
3991
    if (dev == NULL) {
3992
        remoteDispatchConnError(rerr, conn);
3993 3994
        return -1;
    }
3995 3996 3997 3998 3999 4000 4001 4002 4003

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


static int
remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4004 4005
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4006
                                 remote_error *rerr,
4007 4008 4009 4010 4011 4012
                                 remote_node_device_dump_xml_args *args,
                                 remote_node_device_dump_xml_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4013
    dev = virNodeDeviceLookupByName(conn, args->name);
4014
    if (dev == NULL) {
4015 4016
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4017 4018 4019 4020 4021
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags);
    if (!ret->xml) {
4022
        remoteDispatchConnError(rerr, conn);
4023 4024 4025 4026 4027 4028 4029 4030 4031 4032
        virNodeDeviceFree(dev);
        return -1;
    }
    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED,
4033 4034
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4035
                                   remote_error *rerr,
4036 4037 4038 4039 4040 4041 4042
                                   remote_node_device_get_parent_args *args,
                                   remote_node_device_get_parent_ret *ret)
{
    virNodeDevicePtr dev;
    const char *parent;
    CHECK_CONN(client);

4043
    dev = virNodeDeviceLookupByName(conn, args->name);
4044
    if (dev == NULL) {
4045 4046
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4047 4048 4049 4050 4051 4052 4053 4054 4055 4056
    }

    parent = virNodeDeviceGetParent(dev);

    if (parent == NULL) {
        ret->parent = NULL;
    } else {
        /* remoteDispatchClientRequest will free this. */
        char **parent_p;
        if (VIR_ALLOC(parent_p) < 0) {
4057 4058
            remoteDispatchOOMError(rerr);
            return -1;
4059 4060 4061
        }
        *parent_p = strdup(parent);
        if (*parent_p == NULL) {
4062 4063
            remoteDispatchOOMError(rerr);
            return -1;
4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074
        }
        ret->parent = parent_p;
    }

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4075 4076
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4077
                                   remote_error *rerr,
4078 4079 4080 4081 4082 4083
                                   remote_node_device_num_of_caps_args *args,
                                   remote_node_device_num_of_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4084
    dev = virNodeDeviceLookupByName(conn, args->name);
4085
    if (dev == NULL) {
4086 4087
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4088 4089 4090
    }

    ret->num = virNodeDeviceNumOfCaps(dev);
4091
    if (ret->num < 0) {
4092
        remoteDispatchConnError(rerr, conn);
4093 4094
        return -1;
    }
4095 4096 4097 4098 4099 4100 4101 4102

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4103 4104
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4105
                                  remote_error *rerr,
4106 4107 4108 4109 4110 4111
                                  remote_node_device_list_caps_args *args,
                                  remote_node_device_list_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4112
    dev = virNodeDeviceLookupByName(conn, args->name);
4113
    if (dev == NULL) {
4114 4115
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4116 4117 4118
    }

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
4119 4120 4121
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
4122 4123 4124 4125
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
4126 4127
        remoteDispatchOOMError(rerr);
        return -1;
4128 4129 4130 4131 4132 4133
    }

    ret->names.names_len =
        virNodeDeviceListCaps (dev, ret->names.names_val,
                               args->maxnames);
    if (ret->names.names_len == -1) {
4134
        remoteDispatchConnError(rerr, conn);
4135 4136 4137 4138 4139 4140 4141 4142
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


4143 4144 4145 4146 4147 4148
/**************************
 * Async Events
 **************************/
static int
remoteDispatchDomainEvent (struct qemud_server *server ATTRIBUTE_UNUSED,
                           struct qemud_client *client ATTRIBUTE_UNUSED,
4149
                           virConnectPtr conn ATTRIBUTE_UNUSED,
4150
                           remote_error *rerr ATTRIBUTE_UNUSED,
4151 4152 4153 4154 4155 4156 4157
                           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.
     */
4158 4159
    remoteDispatchFormatError(rerr, "%s", _("unexpected async event method call"));
    return -1;
4160 4161 4162 4163 4164 4165 4166
}

/***************************
 * Register / deregister events
 ***************************/
static int
remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED,
4167 4168
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
4169
                                    remote_error *rerr ATTRIBUTE_UNUSED,
4170 4171 4172 4173 4174 4175 4176
                                    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");
4177
    virConnectDomainEventRegister(conn, remoteRelayDomainEvent, client, NULL);
4178 4179 4180 4181 4182 4183 4184 4185

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

static int
remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED,
4186 4187
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4188
                                      remote_error *rerr ATTRIBUTE_UNUSED,
4189 4190 4191 4192 4193 4194 4195
                                      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");
4196
    virConnectDomainEventDeregister(conn, remoteRelayDomainEvent);
4197 4198 4199 4200 4201 4202 4203 4204

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

static void
remoteDispatchDomainEventSend (struct qemud_client *client,
4205 4206 4207
                               virDomainPtr dom,
                               int event,
                               int detail)
4208 4209 4210 4211 4212 4213
{
    remote_message_header rep;
    XDR xdr;
    int len;
    remote_domain_event_ret data;

4214
    if (!client)
4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228
        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. */
    xdrmem_create (&xdr, client->buffer, sizeof client->buffer, XDR_ENCODE);

    len = 0; /* We'll come back and write this later. */
    if (!xdr_int (&xdr, &len)) {
4229
        /*remoteDispatchError (client, NULL, "%s", _("xdr_int failed (1)"));*/
4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240
        xdr_destroy (&xdr);
        return;
    }

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

    /* build return data */
    make_nonnull_domain (&data.dom, dom);
4241 4242
    data.event = event;
    data.detail = detail;
4243 4244

    if (!xdr_remote_domain_event_ret(&xdr, &data)) {
4245
        /*remoteDispatchError (client, NULL, "%s", _("serialise return struct"));*/
4246 4247 4248 4249 4250 4251
        xdr_destroy (&xdr);
        return;
    }

    len = xdr_getpos (&xdr);
    if (xdr_setpos (&xdr, 0) == 0) {
4252
        /*remoteDispatchError (client, NULL, "%s", _("xdr_setpos failed"));*/
4253 4254 4255 4256 4257
        xdr_destroy (&xdr);
        return;
    }

    if (!xdr_int (&xdr, &len)) {
4258
        /*remoteDispatchError (client, NULL, "%s", _("xdr_int failed (2)"));*/
4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269
        xdr_destroy (&xdr);
        return;
    }

    xdr_destroy (&xdr);

    /* Send it. */
    client->mode = QEMUD_MODE_TX_PACKET;
    client->bufferLength = len;
    client->bufferOffset = 0;
}
4270

4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296
/*----- 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);
}

4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310
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;
}

4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326
/* 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);
}

4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340
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);
}
4341 4342 4343 4344 4345 4346

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