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

#include <config.h>

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

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

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

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

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

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

77

78
#include "remote_dispatch_prototypes.h"
79 80 81 82

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

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

    return &(dispatch_table[proc]);
}

94 95 96
/* Prototypes */
static void
remoteDispatchDomainEventSend (struct qemud_client *client,
97
                               remote_domain_event_msg *data);
98

99
int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED,
100 101 102 103
                            virDomainPtr dom,
                            int event,
                            int detail,
                            void *opaque)
104 105
{
    struct qemud_client *client = opaque;
106
    REMOTE_DEBUG("Relaying domain event %d %d", event, detail);
107

108
    if (client) {
109 110
        remote_domain_event_msg data;

111 112
        virMutexLock(&client->lock);

113 114 115 116 117
        /* build return data */
        memset(&data, 0, sizeof data);
        make_nonnull_domain (&data.dom, dom);
        data.event = event;
        data.detail = detail;
118

119
        remoteDispatchDomainEventSend (client, &data);
120 121

        virMutexUnlock(&client->lock);
122 123 124
    }
    return 0;
}
125 126


127 128 129
/*----- Functions. -----*/

static int
130
remoteDispatchOpen (struct qemud_server *server,
131
                    struct qemud_client *client,
132
                    virConnectPtr conn,
133
                    remote_message_header *hdr ATTRIBUTE_UNUSED,
134
                    remote_error *rerr,
135 136 137
                    struct remote_open_args *args, void *ret ATTRIBUTE_UNUSED)
{
    const char *name;
138
    int flags, rc;
139 140

    /* Already opened? */
141
    if (conn) {
142 143
        remoteDispatchFormatError (rerr, "%s", _("connection already open"));
        return -1;
144 145
    }

146 147 148
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
149

150 151 152 153 154 155 156 157 158 159 160 161 162
    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);

163
    if (client->conn == NULL)
164 165
        remoteDispatchConnError(rerr, NULL);

166
    rc = client->conn ? 0 : -1;
167
    virMutexUnlock(&client->lock);
168
    return rc;
169 170
}

171 172 173 174
#define CHECK_CONN(client)                                              \
    if (!client->conn) {                                                \
        remoteDispatchFormatError (rerr, "%s", _("connection not open")); \
        return -1;                                                      \
175 176 177
    }

static int
178
remoteDispatchClose (struct qemud_server *server ATTRIBUTE_UNUSED,
179 180
                     struct qemud_client *client ATTRIBUTE_UNUSED,
                     virConnectPtr conn ATTRIBUTE_UNUSED,
181
                     remote_message_header *hdr ATTRIBUTE_UNUSED,
182
                     remote_error *rerr ATTRIBUTE_UNUSED,
183 184
                     void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
{
185 186 187
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
188

189
    client->closing = 1;
190

191
    virMutexUnlock(&client->lock);
192
    return 0;
193 194
}

195
static int
196
remoteDispatchSupportsFeature (struct qemud_server *server ATTRIBUTE_UNUSED,
197 198
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
199
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
200
                               remote_error *rerr,
201 202
                               remote_supports_feature_args *args, remote_supports_feature_ret *ret)
{
203
    ret->supported = virDrvSupportsFeature (conn, args->feature);
204 205

    if (ret->supported == -1) {
206
        remoteDispatchConnError(rerr, conn);
207 208
        return -1;
    }
209 210 211 212

    return 0;
}

213
static int
214
remoteDispatchGetType (struct qemud_server *server ATTRIBUTE_UNUSED,
215 216
                       struct qemud_client *client ATTRIBUTE_UNUSED,
                       virConnectPtr conn,
217
                       remote_message_header *hdr ATTRIBUTE_UNUSED,
218
                       remote_error *rerr,
219 220 221 222
                       void *args ATTRIBUTE_UNUSED, remote_get_type_ret *ret)
{
    const char *type;

223
    type = virConnectGetType (conn);
224
    if (type == NULL) {
225
        remoteDispatchConnError(rerr, conn);
226 227
        return -1;
    }
228 229 230 231 232 233

    /* We have to strdup because remoteDispatchClientRequest will
     * free this string after it's been serialised.
     */
    ret->type = strdup (type);
    if (!ret->type) {
234 235
        remoteDispatchFormatError (rerr, "%s", _("out of memory in strdup"));
        return -1;
236 237 238 239 240 241
    }

    return 0;
}

static int
242
remoteDispatchGetVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
243 244
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
245
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
246
                          remote_error *rerr,
247 248 249 250 251
                          void *args ATTRIBUTE_UNUSED,
                          remote_get_version_ret *ret)
{
    unsigned long hvVer;

252 253
    if (virConnectGetVersion (conn, &hvVer) == -1) {
        remoteDispatchConnError(rerr, conn);
254
        return -1;
255
    }
256 257 258 259 260

    ret->hv_ver = hvVer;
    return 0;
}

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
static int
remoteDispatchGetLibVersion (struct qemud_server *server ATTRIBUTE_UNUSED,
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
                             remote_error *rerr,
                             void *args ATTRIBUTE_UNUSED,
                             remote_get_lib_version_ret *ret)
{
    unsigned long libVer;

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

    ret->lib_ver = libVer;
    return 0;
}

281
static int
282
remoteDispatchGetHostname (struct qemud_server *server ATTRIBUTE_UNUSED,
283 284
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
285
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
286
                           remote_error *rerr,
287 288 289 290 291
                           void *args ATTRIBUTE_UNUSED,
                           remote_get_hostname_ret *ret)
{
    char *hostname;

292
    hostname = virConnectGetHostname (conn);
293
    if (hostname == NULL) {
294
        remoteDispatchConnError(rerr, conn);
295 296
        return -1;
    }
297 298 299 300 301

    ret->hostname = hostname;
    return 0;
}

302 303
static int
remoteDispatchGetUri (struct qemud_server *server ATTRIBUTE_UNUSED,
304 305
                      struct qemud_client *client ATTRIBUTE_UNUSED,
                      virConnectPtr conn,
306
                      remote_message_header *hdr ATTRIBUTE_UNUSED,
307
                      remote_error *rerr,
308 309 310 311 312 313
                      void *args ATTRIBUTE_UNUSED,
                      remote_get_uri_ret *ret)
{
    char *uri;
    CHECK_CONN(client);

314
    uri = virConnectGetURI (conn);
315
    if (uri == NULL) {
316
        remoteDispatchConnError(rerr, conn);
317 318
        return -1;
    }
319 320 321 322 323

    ret->uri = uri;
    return 0;
}

324
static int
325
remoteDispatchGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
326 327
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
328
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
329
                           remote_error *rerr,
330 331 332 333 334 335
                           remote_get_max_vcpus_args *args,
                           remote_get_max_vcpus_ret *ret)
{
    char *type;

    type = args->type ? *args->type : NULL;
336
    ret->max_vcpus = virConnectGetMaxVcpus (conn, type);
337
    if (ret->max_vcpus == -1) {
338
        remoteDispatchConnError(rerr, conn);
339 340
        return -1;
    }
341 342 343 344 345

    return 0;
}

static int
346
remoteDispatchNodeGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
347 348
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
349
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
350
                           remote_error *rerr,
351 352 353 354 355
                           void *args ATTRIBUTE_UNUSED,
                           remote_node_get_info_ret *ret)
{
    virNodeInfo info;

356 357
    if (virNodeGetInfo (conn, &info) == -1) {
        remoteDispatchConnError(rerr, conn);
358
        return -1;
359
    }
360 361 362 363 364 365 366 367 368 369 370 371 372 373

    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
374
remoteDispatchGetCapabilities (struct qemud_server *server ATTRIBUTE_UNUSED,
375 376
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
377
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
378
                               remote_error *rerr,
379 380 381 382 383
                               void *args ATTRIBUTE_UNUSED,
                               remote_get_capabilities_ret *ret)
{
    char *caps;

384
    caps = virConnectGetCapabilities (conn);
385
    if (caps == NULL) {
386
        remoteDispatchConnError(rerr, conn);
387 388
        return -1;
    }
389 390 391 392 393

    ret->capabilities = caps;
    return 0;
}

394 395
static int
remoteDispatchNodeGetCellsFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
396 397
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
398
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
399
                                      remote_error *rerr,
400 401 402
                                      remote_node_get_cells_free_memory_args *args,
                                      remote_node_get_cells_free_memory_ret *ret)
{
D
Daniel P. Berrange 已提交
403
    int err;
404 405

    if (args->maxCells > REMOTE_NODE_MAX_CELLS) {
406 407 408
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxCells > REMOTE_NODE_MAX_CELLS"));
        return -1;
409 410 411
    }

    /* Allocate return buffer. */
412
    if (VIR_ALLOC_N(ret->freeMems.freeMems_val, args->maxCells) < 0) {
413 414
        remoteDispatchOOMError(rerr);
        return -1;
415
    }
416

D
Daniel P. Berrange 已提交
417 418 419 420 421
    err = virNodeGetCellsFreeMemory(conn,
                                    (unsigned long long *)ret->freeMems.freeMems_val,
                                    args->startCell,
                                    args->maxCells);
    if (err <= 0) {
422
        VIR_FREE(ret->freeMems.freeMems_val);
423
        remoteDispatchConnError(rerr, conn);
424
        return -1;
425
    }
D
Daniel P. Berrange 已提交
426
    ret->freeMems.freeMems_len = err;
427 428 429 430 431 432 433

    return 0;
}


static int
remoteDispatchNodeGetFreeMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
434 435
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
436
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
437
                                 remote_error *rerr,
438 439 440 441 442
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_node_get_free_memory_ret *ret)
{
    unsigned long long freeMem;

443
    freeMem = virNodeGetFreeMemory(conn);
444
    if (freeMem == 0) {
445
        remoteDispatchConnError(rerr, conn);
446 447
        return -1;
    }
448 449 450 451 452
    ret->freeMem = freeMem;
    return 0;
}


453
static int
454
remoteDispatchDomainGetSchedulerType (struct qemud_server *server ATTRIBUTE_UNUSED,
455 456
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
457
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
458
                                      remote_error *rerr,
459 460 461 462 463 464 465
                                      remote_domain_get_scheduler_type_args *args,
                                      remote_domain_get_scheduler_type_ret *ret)
{
    virDomainPtr dom;
    char *type;
    int nparams;

466
    dom = get_nonnull_domain (conn, args->dom);
467
    if (dom == NULL) {
468
        remoteDispatchConnError(rerr, conn);
469
        return -1;
470 471 472
    }

    type = virDomainGetSchedulerType (dom, &nparams);
473 474
    if (type == NULL) {
        virDomainFree(dom);
475
        remoteDispatchConnError(rerr, conn);
476 477
        return -1;
    }
478 479 480

    ret->type = type;
    ret->nparams = nparams;
481
    virDomainFree(dom);
482 483 484 485
    return 0;
}

static int
486
remoteDispatchDomainGetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
487 488
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
489
                                            remote_message_header *hdr ATTRIBUTE_UNUSED,
490
                                            remote_error *rerr,
491 492 493 494 495 496 497 498 499 500
                                            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) {
501 502
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
503
    }
504
    if (VIR_ALLOC_N(params, nparams) < 0) {
505 506
        remoteDispatchOOMError(rerr);
        return -1;
507 508
    }

509
    dom = get_nonnull_domain (conn, args->dom);
510
    if (dom == NULL) {
511
        VIR_FREE(params);
512
        remoteDispatchConnError(rerr, conn);
513
        return -1;
514 515 516 517
    }

    r = virDomainGetSchedulerParameters (dom, params, &nparams);
    if (r == -1) {
518
        virDomainFree(dom);
519
        VIR_FREE(params);
520
        remoteDispatchConnError(rerr, conn);
521 522 523 524 525
        return -1;
    }

    /* Serialise the scheduler parameters. */
    ret->params.params_len = nparams;
526 527
    if (VIR_ALLOC_N(ret->params.params_val, nparams) < 0)
        goto oom;
528 529 530 531

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

535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
        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:
550
            remoteDispatchFormatError (rerr, "%s", _("unknown type"));
551
            goto cleanup;
552 553
        }
    }
554
    virDomainFree(dom);
555
    VIR_FREE(params);
556 557

    return 0;
558 559

oom:
560
    remoteDispatchOOMError(rerr);
561 562 563 564 565
cleanup:
    virDomainFree(dom);
    for (i = 0 ; i < nparams ; i++)
        VIR_FREE(ret->params.params_val[i].field);
    VIR_FREE(params);
566
    return -1;
567 568 569
}

static int
570
remoteDispatchDomainSetSchedulerParameters (struct qemud_server *server ATTRIBUTE_UNUSED,
571 572
                                            struct qemud_client *client ATTRIBUTE_UNUSED,
                                            virConnectPtr conn,
573
                                            remote_message_header *hdr ATTRIBUTE_UNUSED,
574
                                            remote_error *rerr,
575 576 577 578 579 580 581 582 583 584
                                            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) {
585 586
        remoteDispatchFormatError (rerr, "%s", _("nparams too large"));
        return -1;
587
    }
588
    if (VIR_ALLOC_N(params, nparams) < 0) {
589 590
        remoteDispatchOOMError(rerr);
        return -1;
591 592 593 594
    }

    /* Deserialise parameters. */
    for (i = 0; i < nparams; ++i) {
C
Chris Lalancette 已提交
595 596 597 598 599
        if (virStrcpyStatic(params[i].field, args->params.params_val[i].field) == NULL) {
            remoteDispatchFormatError(rerr, _("Field %s too big for destination"),
                                      args->params.params_val[i].field);
            return -1;
        }
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
        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;
        }
    }

617
    dom = get_nonnull_domain (conn, args->dom);
618
    if (dom == NULL) {
619
        VIR_FREE(params);
620
        remoteDispatchConnError(rerr, conn);
621
        return -1;
622 623 624
    }

    r = virDomainSetSchedulerParameters (dom, params, nparams);
625
    virDomainFree(dom);
626
    VIR_FREE(params);
627
    if (r == -1) {
628
        remoteDispatchConnError(rerr, conn);
629 630
        return -1;
    }
631 632 633 634

    return 0;
}

635
static int
636
remoteDispatchDomainBlockStats (struct qemud_server *server ATTRIBUTE_UNUSED,
637 638
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
639
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
640
                                remote_error *rerr,
641 642 643 644 645 646 647
                                remote_domain_block_stats_args *args,
                                remote_domain_block_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainBlockStats stats;

648
    dom = get_nonnull_domain (conn, args->dom);
649
    if (dom == NULL) {
650
        remoteDispatchConnError(rerr, conn);
651
        return -1;
652 653 654
    }
    path = args->path;

D
Daniel P. Berrange 已提交
655 656
    if (virDomainBlockStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
657
        remoteDispatchConnError(rerr, conn);
658
        return -1;
D
Daniel P. Berrange 已提交
659 660
    }
    virDomainFree (dom);
661 662 663 664 665 666 667 668 669 670 671

    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
672
remoteDispatchDomainInterfaceStats (struct qemud_server *server ATTRIBUTE_UNUSED,
673 674
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
675
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
676
                                    remote_error *rerr,
677 678 679 680 681 682 683
                                    remote_domain_interface_stats_args *args,
                                    remote_domain_interface_stats_ret *ret)
{
    virDomainPtr dom;
    char *path;
    struct _virDomainInterfaceStats stats;

684
    dom = get_nonnull_domain (conn, args->dom);
685
    if (dom == NULL) {
686
        remoteDispatchConnError(rerr, conn);
687
        return -1;
688 689 690
    }
    path = args->path;

D
Daniel P. Berrange 已提交
691 692
    if (virDomainInterfaceStats (dom, path, &stats, sizeof stats) == -1) {
        virDomainFree (dom);
693
        remoteDispatchConnError(rerr, conn);
694
        return -1;
D
Daniel P. Berrange 已提交
695 696
    }
    virDomainFree (dom);
697 698 699 700 701 702 703 704 705 706 707 708 709

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

710 711
static int
remoteDispatchDomainBlockPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
712 713
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
714
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
715
                               remote_error *rerr,
716 717 718 719 720 721 722 723 724
                               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;

725
    dom = get_nonnull_domain (conn, args->dom);
726
    if (dom == NULL) {
727
        remoteDispatchConnError(rerr, conn);
728
        return -1;
729 730 731 732 733 734 735
    }
    path = args->path;
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
736
        virDomainFree (dom);
737 738 739
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
740 741 742
    }

    ret->buffer.buffer_len = size;
743
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
744
        virDomainFree (dom);
745
        remoteDispatchOOMError(rerr);
746
        return -1;
747 748 749 750 751 752
    }

    if (virDomainBlockPeek (dom, path, offset, size,
                            ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
753
        remoteDispatchConnError(rerr, conn);
754 755 756 757 758 759 760
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

R
Richard W.M. Jones 已提交
761 762
static int
remoteDispatchDomainMemoryPeek (struct qemud_server *server ATTRIBUTE_UNUSED,
763 764
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
765
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
766
                                remote_error *rerr,
R
Richard W.M. Jones 已提交
767 768 769 770 771 772 773 774
                                remote_domain_memory_peek_args *args,
                                remote_domain_memory_peek_ret *ret)
{
    virDomainPtr dom;
    unsigned long long offset;
    size_t size;
    unsigned int flags;

775
    dom = get_nonnull_domain (conn, args->dom);
R
Richard W.M. Jones 已提交
776
    if (dom == NULL) {
777
        remoteDispatchConnError(rerr, conn);
778
        return -1;
R
Richard W.M. Jones 已提交
779 780 781 782 783 784
    }
    offset = args->offset;
    size = args->size;
    flags = args->flags;

    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
785
        virDomainFree (dom);
786 787 788
        remoteDispatchFormatError (rerr,
                                   "%s", _("size > maximum buffer size"));
        return -1;
R
Richard W.M. Jones 已提交
789 790 791 792 793
    }

    ret->buffer.buffer_len = size;
    if (VIR_ALLOC_N (ret->buffer.buffer_val, size) < 0) {
        virDomainFree (dom);
794
        remoteDispatchOOMError(rerr);
795
        return -1;
R
Richard W.M. Jones 已提交
796 797 798 799 800 801
    }

    if (virDomainMemoryPeek (dom, offset, size,
                             ret->buffer.buffer_val, flags) == -1) {
        /* free (ret->buffer.buffer_val); - caller frees */
        virDomainFree (dom);
802
        remoteDispatchConnError(rerr, conn);
R
Richard W.M. Jones 已提交
803 804 805 806 807 808 809
        return -1;
    }
    virDomainFree (dom);

    return 0;
}

810
static int
811
remoteDispatchDomainAttachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
812 813
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
814
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
815
                                  remote_error *rerr,
816 817 818 819 820
                                  remote_domain_attach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

827 828
    if (virDomainAttachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
829
        remoteDispatchConnError(rerr, conn);
830
        return -1;
831 832
    }
    virDomainFree(dom);
833 834 835 836
    return 0;
}

static int
837
remoteDispatchDomainCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
838 839
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
840
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
841
                            remote_error *rerr,
842 843 844 845 846
                            remote_domain_create_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

853 854
    if (virDomainCreate (dom) == -1) {
        virDomainFree(dom);
855
        remoteDispatchConnError(rerr, conn);
856
        return -1;
857 858
    }
    virDomainFree(dom);
859 860 861 862
    return 0;
}

static int
863
remoteDispatchDomainCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
864 865
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
866
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
867 868 869
                               remote_error *rerr,
                               remote_domain_create_xml_args *args,
                               remote_domain_create_xml_ret *ret)
870 871 872
{
    virDomainPtr dom;

873
    dom = virDomainCreateXML (conn, args->xml_desc, args->flags);
874
    if (dom == NULL) {
875
        remoteDispatchConnError(rerr, conn);
876 877
        return -1;
    }
878 879

    make_nonnull_domain (&ret->dom, dom);
880
    virDomainFree(dom);
881 882 883 884 885

    return 0;
}

static int
886
remoteDispatchDomainDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
887 888
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
889
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
890
                               remote_error *rerr,
891 892 893 894 895
                               remote_domain_define_xml_args *args,
                               remote_domain_define_xml_ret *ret)
{
    virDomainPtr dom;

896
    dom = virDomainDefineXML (conn, args->xml);
897
    if (dom == NULL) {
898
        remoteDispatchConnError(rerr, conn);
899 900
        return -1;
    }
901 902

    make_nonnull_domain (&ret->dom, dom);
903
    virDomainFree(dom);
904 905 906 907 908

    return 0;
}

static int
909
remoteDispatchDomainDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
910 911
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
912
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
913
                             remote_error *rerr,
914 915 916 917 918
                             remote_domain_destroy_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

919
    dom = get_nonnull_domain (conn, args->dom);
920
    if (dom == NULL) {
921
        remoteDispatchConnError(rerr, conn);
922
        return -1;
923 924
    }

925 926
    if (virDomainDestroy (dom) == -1) {
        virDomainFree(dom);
927
        remoteDispatchConnError(rerr, conn);
928
        return -1;
929 930
    }
    virDomainFree(dom);
931 932 933 934
    return 0;
}

static int
935
remoteDispatchDomainDetachDevice (struct qemud_server *server ATTRIBUTE_UNUSED,
936 937
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
938
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
939
                                  remote_error *rerr,
940 941 942 943 944
                                  remote_domain_detach_device_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

951 952
    if (virDomainDetachDevice (dom, args->xml) == -1) {
        virDomainFree(dom);
953
        remoteDispatchConnError(rerr, conn);
954
        return -1;
955
    }
956

957
    virDomainFree(dom);
958 959 960 961
    return 0;
}

static int
962
remoteDispatchDomainDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
963 964
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
965
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
966
                             remote_error *rerr,
967 968 969 970 971
                             remote_domain_dump_xml_args *args,
                             remote_domain_dump_xml_ret *ret)
{
    virDomainPtr dom;

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

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virDomainGetXMLDesc (dom, args->flags);
980
    if (!ret->xml) {
981
        virDomainFree(dom);
982
        remoteDispatchConnError(rerr, conn);
983
        return -1;
984 985
    }
    virDomainFree(dom);
986 987 988
    return 0;
}

989 990 991 992
static int
remoteDispatchDomainXmlFromNative (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
993
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
                                   remote_error *rerr,
                                   remote_domain_xml_from_native_args *args,
                                   remote_domain_xml_from_native_ret *ret)
{
    /* remoteDispatchClientRequest will free this. */
    ret->domainXml = virConnectDomainXMLFromNative (conn,
                                                    args->nativeFormat,
                                                    args->nativeConfig,
                                                    args->flags);
    if (!ret->domainXml) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}

static int
remoteDispatchDomainXmlToNative (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1014
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
                                 remote_error *rerr,
                                 remote_domain_xml_to_native_args *args,
                                 remote_domain_xml_to_native_ret *ret)
{
    /* remoteDispatchClientRequest will free this. */
    ret->nativeConfig = virConnectDomainXMLToNative (conn,
                                                     args->nativeFormat,
                                                     args->domainXml,
                                                     args->flags);
    if (!ret->nativeConfig) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
    return 0;
}


1032
static int
1033
remoteDispatchDomainGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1034 1035
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1036
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1037
                                  remote_error *rerr,
1038 1039 1040 1041 1042
                                  remote_domain_get_autostart_args *args,
                                  remote_domain_get_autostart_ret *ret)
{
    virDomainPtr dom;

1043
    dom = get_nonnull_domain (conn, args->dom);
1044
    if (dom == NULL) {
1045
        remoteDispatchConnError(rerr, conn);
1046
        return -1;
1047 1048
    }

1049 1050
    if (virDomainGetAutostart (dom, &ret->autostart) == -1) {
        virDomainFree(dom);
1051
        remoteDispatchConnError(rerr, conn);
1052
        return -1;
1053 1054
    }
    virDomainFree(dom);
1055 1056 1057 1058
    return 0;
}

static int
1059
remoteDispatchDomainGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
1060 1061
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1062
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1063
                             remote_error *rerr,
1064 1065 1066 1067 1068 1069
                             remote_domain_get_info_args *args,
                             remote_domain_get_info_ret *ret)
{
    virDomainPtr dom;
    virDomainInfo info;

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

1076 1077
    if (virDomainGetInfo (dom, &info) == -1) {
        virDomainFree(dom);
1078
        remoteDispatchConnError(rerr, conn);
1079
        return -1;
1080
    }
1081 1082 1083 1084 1085 1086 1087

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

1088 1089
    virDomainFree(dom);

1090 1091 1092 1093
    return 0;
}

static int
1094
remoteDispatchDomainGetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1095 1096
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1097
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1098
                                  remote_error *rerr,
1099 1100 1101 1102 1103
                                  remote_domain_get_max_memory_args *args,
                                  remote_domain_get_max_memory_ret *ret)
{
    virDomainPtr dom;

1104
    dom = get_nonnull_domain (conn, args->dom);
1105
    if (dom == NULL) {
1106
        remoteDispatchConnError(rerr, conn);
1107
        return -1;
1108 1109 1110
    }

    ret->memory = virDomainGetMaxMemory (dom);
1111 1112
    if (ret->memory == 0) {
        virDomainFree(dom);
1113
        remoteDispatchConnError(rerr, conn);
1114 1115 1116
        return -1;
    }
    virDomainFree(dom);
1117 1118 1119 1120
    return 0;
}

static int
1121
remoteDispatchDomainGetMaxVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1122 1123
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
1124
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
1125
                                 remote_error *rerr,
1126 1127 1128 1129 1130
                                 remote_domain_get_max_vcpus_args *args,
                                 remote_domain_get_max_vcpus_ret *ret)
{
    virDomainPtr dom;

1131
    dom = get_nonnull_domain (conn, args->dom);
1132
    if (dom == NULL) {
1133
        remoteDispatchConnError(rerr, conn);
1134
        return -1;
1135 1136 1137
    }

    ret->num = virDomainGetMaxVcpus (dom);
1138 1139
    if (ret->num == -1) {
        virDomainFree(dom);
1140
        remoteDispatchConnError(rerr, conn);
1141 1142 1143
        return -1;
    }
    virDomainFree(dom);
1144 1145 1146
    return 0;
}

1147 1148 1149 1150
static int
remoteDispatchDomainGetSecurityLabel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1151
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167
                                     remote_error *rerr,
                                     remote_domain_get_security_label_args *args,
                                     remote_domain_get_security_label_ret *ret)
{
    virDomainPtr dom;
    virSecurityLabel seclabel;

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

    memset(&seclabel, 0, sizeof seclabel);
    if (virDomainGetSecurityLabel(dom, &seclabel) == -1) {
        virDomainFree(dom);
1168
        remoteDispatchConnError(rerr, conn);
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
        return -1;
    }

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

    return 0;
}

static int
remoteDispatchNodeGetSecurityModel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1189
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1190 1191 1192 1193 1194 1195 1196 1197
                                   remote_error *rerr,
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_node_get_security_model_ret *ret)
{
    virSecurityModel secmodel;

    memset(&secmodel, 0, sizeof secmodel);
    if (virNodeGetSecurityModel(conn, &secmodel) == -1) {
1198
        remoteDispatchConnError(rerr, conn);
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
        return -1;
    }

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

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

    return 0;
}

1219
static int
1220
remoteDispatchDomainGetOsType (struct qemud_server *server ATTRIBUTE_UNUSED,
1221 1222
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1223
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1224
                               remote_error *rerr,
1225 1226 1227 1228 1229
                               remote_domain_get_os_type_args *args,
                               remote_domain_get_os_type_ret *ret)
{
    virDomainPtr dom;

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

    /* remoteDispatchClientRequest will free this */
    ret->type = virDomainGetOSType (dom);
1238
    if (ret->type == NULL) {
1239
        virDomainFree(dom);
1240
        remoteDispatchConnError(rerr, conn);
1241
        return -1;
1242 1243
    }
    virDomainFree(dom);
1244 1245 1246 1247
    return 0;
}

static int
1248
remoteDispatchDomainGetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1249 1250
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1251
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
1252
                              remote_error *rerr,
1253 1254 1255
                              remote_domain_get_vcpus_args *args,
                              remote_domain_get_vcpus_ret *ret)
{
1256 1257 1258
    virDomainPtr dom = NULL;
    virVcpuInfoPtr info = NULL;
    unsigned char *cpumaps = NULL;
1259 1260
    int info_len, i;

1261
    dom = get_nonnull_domain (conn, args->dom);
1262
    if (dom == NULL) {
1263
        remoteDispatchConnError(rerr, conn);
1264
        return -1;
1265 1266 1267
    }

    if (args->maxinfo > REMOTE_VCPUINFO_MAX) {
1268
        virDomainFree(dom);
1269 1270
        remoteDispatchFormatError (rerr, "%s", _("maxinfo > REMOTE_VCPUINFO_MAX"));
        return -1;
1271 1272
    }

1273
    if (args->maxinfo * args->maplen > REMOTE_CPUMAPS_MAX) {
1274
        virDomainFree(dom);
1275 1276
        remoteDispatchFormatError (rerr, "%s", _("maxinfo * maplen > REMOTE_CPUMAPS_MAX"));
        return -1;
1277 1278 1279
    }

    /* Allocate buffers to take the results. */
1280 1281
    if (VIR_ALLOC_N(info, args->maxinfo) < 0)
        goto oom;
1282 1283
    if (args->maplen > 0 &&
        VIR_ALLOC_N(cpumaps, args->maxinfo * args->maplen) < 0)
1284
        goto oom;
1285 1286 1287 1288

    info_len = virDomainGetVcpus (dom,
                                  info, args->maxinfo,
                                  cpumaps, args->maplen);
1289
    if (info_len == -1) {
1290 1291
        VIR_FREE(info);
        VIR_FREE(cpumaps);
1292
        virDomainFree(dom);
1293
        remoteDispatchConnError(rerr, conn);
1294 1295
        return -1;
    }
1296 1297 1298

    /* Allocate the return buffer for info. */
    ret->info.info_len = info_len;
1299 1300
    if (VIR_ALLOC_N(ret->info.info_val, info_len) < 0)
        goto oom;
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312

    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.
     */
1313
    ret->cpumaps.cpumaps_len = args->maxinfo * args->maplen;
1314 1315
    ret->cpumaps.cpumaps_val = (char *) cpumaps;

1316
    VIR_FREE(info);
1317
    virDomainFree(dom);
1318
    return 0;
1319 1320 1321 1322 1323

oom:
    VIR_FREE(info);
    VIR_FREE(cpumaps);
    virDomainFree(dom);
1324 1325
    remoteDispatchOOMError(rerr);
    return -1;
1326 1327
}

1328
static int
1329
remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED,
1330 1331
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1332
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1333
                                    remote_error *rerr,
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
                                    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 ... */
1348
    if (VIR_ALLOC(uri_out) < 0) {
1349 1350
        remoteDispatchOOMError(rerr);
        return -1;
1351
    }
1352

1353
    r = virDomainMigratePrepare (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1354 1355
                                 uri_in, uri_out,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1356
    if (r == -1) {
1357
        VIR_FREE(uri_out);
1358
        remoteDispatchConnError(rerr, conn);
D
Daniel P. Berrange 已提交
1359 1360
        return -1;
    }
1361 1362 1363 1364 1365 1366

    /* 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 已提交
1367 1368
    if (*uri_out == NULL) {
        ret->uri_out = NULL;
1369
        VIR_FREE(uri_out);
D
Daniel P. Berrange 已提交
1370 1371 1372
    } else {
        ret->uri_out = uri_out;
    }
1373 1374 1375 1376 1377

    return 0;
}

static int
1378
remoteDispatchDomainMigratePerform (struct qemud_server *server ATTRIBUTE_UNUSED,
1379 1380
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1381
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1382
                                    remote_error *rerr,
1383 1384 1385 1386 1387 1388 1389
                                    remote_domain_migrate_perform_args *args,
                                    void *ret ATTRIBUTE_UNUSED)
{
    int r;
    virDomainPtr dom;
    char *dname;

1390
    dom = get_nonnull_domain (conn, args->dom);
1391
    if (dom == NULL) {
1392
        remoteDispatchConnError(rerr, conn);
1393
        return -1;
1394 1395 1396 1397
    }

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

D
Daniel P. Berrange 已提交
1398 1399 1400 1401 1402
    r = virDomainMigratePerform (dom,
                                 args->cookie.cookie_val,
                                 args->cookie.cookie_len,
                                 args->uri,
                                 args->flags, dname, args->resource);
D
Daniel P. Berrange 已提交
1403
    virDomainFree (dom);
1404
    if (r == -1) {
1405
        remoteDispatchConnError(rerr, conn);
1406 1407
        return -1;
    }
1408 1409 1410 1411 1412

    return 0;
}

static int
1413
remoteDispatchDomainMigrateFinish (struct qemud_server *server ATTRIBUTE_UNUSED,
1414 1415
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1416
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1417
                                   remote_error *rerr,
1418 1419 1420 1421 1422 1423
                                   remote_domain_migrate_finish_args *args,
                                   remote_domain_migrate_finish_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1424
    ddom = virDomainMigrateFinish (conn, args->dname,
D
Daniel P. Berrange 已提交
1425 1426 1427 1428
                                   args->cookie.cookie_val,
                                   args->cookie.cookie_len,
                                   args->uri,
                                   args->flags);
1429
    if (ddom == NULL) {
1430
        remoteDispatchConnError(rerr, conn);
1431 1432
        return -1;
    }
1433 1434

    make_nonnull_domain (&ret->ddom, ddom);
D
Daniel P. Berrange 已提交
1435
    virDomainFree (ddom);
1436 1437 1438
    return 0;
}

D
Daniel Veillard 已提交
1439 1440
static int
remoteDispatchDomainMigratePrepare2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1441 1442
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
1443
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
1444
                                     remote_error *rerr,
D
Daniel Veillard 已提交
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
                                     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) {
1461 1462
        remoteDispatchOOMError(rerr);
        return -1;
D
Daniel Veillard 已提交
1463 1464
    }

1465
    r = virDomainMigratePrepare2 (conn, &cookie, &cookielen,
D
Daniel P. Berrange 已提交
1466 1467 1468
                                  uri_in, uri_out,
                                  args->flags, dname, args->resource,
                                  args->dom_xml);
1469
    if (r == -1) {
1470
        remoteDispatchConnError(rerr, conn);
1471 1472
        return -1;
    }
D
Daniel Veillard 已提交
1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485

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

    return 0;
}

static int
remoteDispatchDomainMigrateFinish2 (struct qemud_server *server ATTRIBUTE_UNUSED,
1486 1487
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
1488
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
1489
                                    remote_error *rerr,
D
Daniel Veillard 已提交
1490 1491 1492 1493 1494 1495
                                    remote_domain_migrate_finish2_args *args,
                                    remote_domain_migrate_finish2_ret *ret)
{
    virDomainPtr ddom;
    CHECK_CONN (client);

1496
    ddom = virDomainMigrateFinish2 (conn, args->dname,
D
Daniel P. Berrange 已提交
1497 1498 1499 1500 1501
                                    args->cookie.cookie_val,
                                    args->cookie.cookie_len,
                                    args->uri,
                                    args->flags,
                                    args->retcode);
1502
    if (ddom == NULL) {
1503
        remoteDispatchConnError(rerr, conn);
1504 1505
        return -1;
    }
D
Daniel Veillard 已提交
1506 1507 1508 1509 1510 1511

    make_nonnull_domain (&ret->ddom, ddom);

    return 0;
}

C
Chris Lalancette 已提交
1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
static int
remoteDispatchDomainMigratePrepareTunnel(struct qemud_server *server ATTRIBUTE_UNUSED,
                                         struct qemud_client *client,
                                         virConnectPtr conn,
                                         remote_message_header *hdr,
                                         remote_error *rerr,
                                         remote_domain_migrate_prepare_tunnel_args *args,
                                         void *ret ATTRIBUTE_UNUSED)
{
    int r;
    char *dname;
    struct qemud_client_stream *stream;
    CHECK_CONN (client);

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

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

1534
    r = virDomainMigratePrepareTunnel(conn, stream->st,
C
Chris Lalancette 已提交
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
                                      args->flags, dname, args->resource,
                                      args->dom_xml);
    if (r == -1) {
        remoteFreeClientStream(client, stream);
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

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

    return 0;
}

1553
static int
1554
remoteDispatchListDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1555 1556
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1557
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1558
                                  remote_error *rerr,
1559 1560 1561 1562 1563
                                  remote_list_defined_domains_args *args,
                                  remote_list_defined_domains_ret *ret)
{

    if (args->maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) {
1564 1565 1566
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_DOMAIN_NAME_LIST_MAX"));
        return -1;
1567 1568 1569
    }

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

    ret->names.names_len =
1576
        virConnectListDefinedDomains (conn,
1577
                                      ret->names.names_val, args->maxnames);
1578 1579
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
1580
        remoteDispatchConnError(rerr, conn);
1581 1582
        return -1;
    }
1583 1584 1585 1586 1587

    return 0;
}

static int
1588
remoteDispatchDomainLookupById (struct qemud_server *server ATTRIBUTE_UNUSED,
1589 1590
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
1591
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
1592
                                remote_error *rerr,
1593 1594 1595 1596 1597
                                remote_domain_lookup_by_id_args *args,
                                remote_domain_lookup_by_id_ret *ret)
{
    virDomainPtr dom;

1598
    dom = virDomainLookupByID (conn, args->id);
1599
    if (dom == NULL) {
1600
        remoteDispatchConnError(rerr, conn);
1601 1602
        return -1;
    }
1603 1604

    make_nonnull_domain (&ret->dom, dom);
1605
    virDomainFree(dom);
1606 1607 1608 1609
    return 0;
}

static int
1610
remoteDispatchDomainLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
1611 1612
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1613
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1614
                                  remote_error *rerr,
1615 1616 1617 1618 1619
                                  remote_domain_lookup_by_name_args *args,
                                  remote_domain_lookup_by_name_ret *ret)
{
    virDomainPtr dom;

1620
    dom = virDomainLookupByName (conn, args->name);
1621
    if (dom == NULL) {
1622
        remoteDispatchConnError(rerr, conn);
1623 1624
        return -1;
    }
1625 1626

    make_nonnull_domain (&ret->dom, dom);
1627
    virDomainFree(dom);
1628 1629 1630 1631
    return 0;
}

static int
1632
remoteDispatchDomainLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
1633 1634
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1635
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1636
                                  remote_error *rerr,
1637 1638 1639 1640 1641
                                  remote_domain_lookup_by_uuid_args *args,
                                  remote_domain_lookup_by_uuid_ret *ret)
{
    virDomainPtr dom;

1642
    dom = virDomainLookupByUUID (conn, (unsigned char *) args->uuid);
1643
    if (dom == NULL) {
1644
        remoteDispatchConnError(rerr, conn);
1645 1646
        return -1;
    }
1647 1648

    make_nonnull_domain (&ret->dom, dom);
1649
    virDomainFree(dom);
1650 1651 1652 1653
    return 0;
}

static int
1654
remoteDispatchNumOfDefinedDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
1655 1656
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
1657
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
1658
                                   remote_error *rerr,
1659 1660 1661 1662
                                   void *args ATTRIBUTE_UNUSED,
                                   remote_num_of_defined_domains_ret *ret)
{

1663
    ret->num = virConnectNumOfDefinedDomains (conn);
1664
    if (ret->num == -1) {
1665
        remoteDispatchConnError(rerr, conn);
1666 1667
        return -1;
    }
1668 1669 1670 1671 1672

    return 0;
}

static int
1673
remoteDispatchDomainPinVcpu (struct qemud_server *server ATTRIBUTE_UNUSED,
1674 1675
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1676
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1677
                             remote_error *rerr,
1678 1679 1680 1681 1682 1683
                             remote_domain_pin_vcpu_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;
    int rv;

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

    if (args->cpumap.cpumap_len > REMOTE_CPUMAP_MAX) {
1691
        virDomainFree(dom);
1692 1693
        remoteDispatchFormatError (rerr, "%s", _("cpumap_len > REMOTE_CPUMAP_MAX"));
        return -1;
1694 1695 1696 1697 1698
    }

    rv = virDomainPinVcpu (dom, args->vcpu,
                           (unsigned char *) args->cpumap.cpumap_val,
                           args->cpumap.cpumap_len);
1699 1700
    if (rv == -1) {
        virDomainFree(dom);
1701
        remoteDispatchConnError(rerr, conn);
1702 1703 1704
        return -1;
    }
    virDomainFree(dom);
1705 1706 1707 1708
    return 0;
}

static int
1709
remoteDispatchDomainReboot (struct qemud_server *server ATTRIBUTE_UNUSED,
1710 1711
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1712
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
1713
                            remote_error *rerr,
1714 1715 1716 1717 1718
                            remote_domain_reboot_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1719
    dom = get_nonnull_domain (conn, args->dom);
1720
    if (dom == NULL) {
1721
        remoteDispatchConnError(rerr, conn);
1722
        return -1;
1723 1724
    }

1725 1726
    if (virDomainReboot (dom, args->flags) == -1) {
        virDomainFree(dom);
1727
        remoteDispatchConnError(rerr, conn);
1728
        return -1;
1729 1730
    }
    virDomainFree(dom);
1731 1732 1733 1734
    return 0;
}

static int
1735
remoteDispatchDomainRestore (struct qemud_server *server ATTRIBUTE_UNUSED,
1736 1737
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1738
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1739
                             remote_error *rerr,
1740 1741 1742 1743
                             remote_domain_restore_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{

1744 1745
    if (virDomainRestore (conn, args->from) == -1) {
        remoteDispatchConnError(rerr, conn);
1746
        return -1;
1747
    }
1748 1749 1750 1751 1752

    return 0;
}

static int
1753
remoteDispatchDomainResume (struct qemud_server *server ATTRIBUTE_UNUSED,
1754 1755
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn,
1756
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
1757
                            remote_error *rerr,
1758 1759 1760 1761 1762
                            remote_domain_resume_args *args,
                            void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

1769 1770
    if (virDomainResume (dom) == -1) {
        virDomainFree(dom);
1771
        remoteDispatchConnError(rerr, conn);
1772
        return -1;
1773 1774
    }
    virDomainFree(dom);
1775 1776 1777 1778
    return 0;
}

static int
1779
remoteDispatchDomainSave (struct qemud_server *server ATTRIBUTE_UNUSED,
1780 1781
                          struct qemud_client *client ATTRIBUTE_UNUSED,
                          virConnectPtr conn,
1782
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
1783
                          remote_error *rerr,
1784 1785 1786 1787 1788
                          remote_domain_save_args *args,
                          void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1789
    dom = get_nonnull_domain (conn, args->dom);
1790
    if (dom == NULL) {
1791
        remoteDispatchConnError(rerr, conn);
1792
        return -1;
1793 1794
    }

1795 1796
    if (virDomainSave (dom, args->to) == -1) {
        virDomainFree(dom);
1797
        remoteDispatchConnError(rerr, conn);
1798
        return -1;
1799 1800
    }
    virDomainFree(dom);
1801 1802 1803 1804
    return 0;
}

static int
1805
remoteDispatchDomainCoreDump (struct qemud_server *server ATTRIBUTE_UNUSED,
1806 1807
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1808
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
1809
                              remote_error *rerr,
1810 1811 1812 1813 1814
                              remote_domain_core_dump_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

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

1821 1822
    if (virDomainCoreDump (dom, args->to, args->flags) == -1) {
        virDomainFree(dom);
1823
        remoteDispatchConnError(rerr, conn);
1824
        return -1;
1825 1826
    }
    virDomainFree(dom);
1827 1828 1829 1830
    return 0;
}

static int
1831
remoteDispatchDomainSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
1832 1833
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1834
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1835
                                  remote_error *rerr,
1836 1837 1838 1839 1840
                                  remote_domain_set_autostart_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1841
    dom = get_nonnull_domain (conn, args->dom);
1842
    if (dom == NULL) {
1843
        remoteDispatchConnError(rerr, conn);
1844
        return -1;
1845 1846
    }

1847 1848
    if (virDomainSetAutostart (dom, args->autostart) == -1) {
        virDomainFree(dom);
1849
        remoteDispatchConnError(rerr, conn);
1850
        return -1;
1851 1852
    }
    virDomainFree(dom);
1853 1854 1855 1856
    return 0;
}

static int
1857
remoteDispatchDomainSetMaxMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1858 1859
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
1860
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
1861
                                  remote_error *rerr,
1862 1863 1864 1865 1866
                                  remote_domain_set_max_memory_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1867
    dom = get_nonnull_domain (conn, args->dom);
1868
    if (dom == NULL) {
1869
        remoteDispatchConnError(rerr, conn);
1870
        return -1;
1871 1872
    }

1873 1874
    if (virDomainSetMaxMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
1875
        remoteDispatchConnError(rerr, conn);
1876
        return -1;
1877 1878
    }
    virDomainFree(dom);
1879 1880 1881 1882
    return 0;
}

static int
1883
remoteDispatchDomainSetMemory (struct qemud_server *server ATTRIBUTE_UNUSED,
1884 1885
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
1886
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
1887
                               remote_error *rerr,
1888 1889 1890 1891 1892
                               remote_domain_set_memory_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1893
    dom = get_nonnull_domain (conn, args->dom);
1894
    if (dom == NULL) {
1895
        remoteDispatchConnError(rerr, conn);
1896
        return -1;
1897 1898
    }

1899 1900
    if (virDomainSetMemory (dom, args->memory) == -1) {
        virDomainFree(dom);
1901
        remoteDispatchConnError(rerr, conn);
1902
        return -1;
1903 1904
    }
    virDomainFree(dom);
1905 1906 1907 1908
    return 0;
}

static int
1909
remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED,
1910 1911
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1912
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
1913
                              remote_error *rerr,
1914 1915 1916 1917 1918
                              remote_domain_set_vcpus_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1919
    dom = get_nonnull_domain (conn, args->dom);
1920
    if (dom == NULL) {
1921
        remoteDispatchConnError(rerr, conn);
1922
        return -1;
1923 1924
    }

1925 1926
    if (virDomainSetVcpus (dom, args->nvcpus) == -1) {
        virDomainFree(dom);
1927
        remoteDispatchConnError(rerr, conn);
1928
        return -1;
1929 1930
    }
    virDomainFree(dom);
1931 1932 1933 1934
    return 0;
}

static int
1935
remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED,
1936 1937
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1938
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
1939
                              remote_error *rerr,
1940 1941 1942 1943 1944
                              remote_domain_shutdown_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1945
    dom = get_nonnull_domain (conn, args->dom);
1946
    if (dom == NULL) {
1947
        remoteDispatchConnError(rerr, conn);
1948
        return -1;
1949 1950
    }

1951 1952
    if (virDomainShutdown (dom) == -1) {
        virDomainFree(dom);
1953
        remoteDispatchConnError(rerr, conn);
1954
        return -1;
1955 1956
    }
    virDomainFree(dom);
1957 1958 1959 1960
    return 0;
}

static int
1961
remoteDispatchDomainSuspend (struct qemud_server *server ATTRIBUTE_UNUSED,
1962 1963
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
1964
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
1965
                             remote_error *rerr,
1966 1967 1968 1969 1970
                             remote_domain_suspend_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1971
    dom = get_nonnull_domain (conn, args->dom);
1972
    if (dom == NULL) {
1973
        remoteDispatchConnError(rerr, conn);
1974
        return -1;
1975 1976
    }

1977 1978
    if (virDomainSuspend (dom) == -1) {
        virDomainFree(dom);
1979
        remoteDispatchConnError(rerr, conn);
1980
        return -1;
1981 1982
    }
    virDomainFree(dom);
1983 1984 1985 1986
    return 0;
}

static int
1987
remoteDispatchDomainUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
1988 1989
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
1990
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
1991
                              remote_error *rerr,
1992 1993 1994 1995 1996
                              remote_domain_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virDomainPtr dom;

1997
    dom = get_nonnull_domain (conn, args->dom);
1998
    if (dom == NULL) {
1999
        remoteDispatchConnError(rerr, conn);
2000
        return -1;
2001 2002
    }

2003 2004
    if (virDomainUndefine (dom) == -1) {
        virDomainFree(dom);
2005
        remoteDispatchConnError(rerr, conn);
2006
        return -1;
2007 2008
    }
    virDomainFree(dom);
2009 2010 2011 2012
    return 0;
}

static int
2013
remoteDispatchListDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2014 2015
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2016
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2017
                                   remote_error *rerr,
2018 2019 2020 2021 2022
                                   remote_list_defined_networks_args *args,
                                   remote_list_defined_networks_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2023 2024 2025
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2026 2027 2028
    }

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

    ret->names.names_len =
2035
        virConnectListDefinedNetworks (conn,
2036
                                       ret->names.names_val, args->maxnames);
2037 2038
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
2039
        remoteDispatchConnError(rerr, conn);
2040 2041
        return -1;
    }
2042 2043 2044 2045 2046

    return 0;
}

static int
2047
remoteDispatchListDomains (struct qemud_server *server ATTRIBUTE_UNUSED,
2048 2049
                           struct qemud_client *client ATTRIBUTE_UNUSED,
                           virConnectPtr conn,
2050
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
2051
                           remote_error *rerr,
2052 2053 2054 2055 2056
                           remote_list_domains_args *args,
                           remote_list_domains_ret *ret)
{

    if (args->maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
2057 2058 2059
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxids > REMOTE_DOMAIN_ID_LIST_MAX"));
        return -1;
2060 2061 2062
    }

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

2068
    ret->ids.ids_len = virConnectListDomains (conn,
2069
                                              ret->ids.ids_val, args->maxids);
2070 2071
    if (ret->ids.ids_len == -1) {
        VIR_FREE(ret->ids.ids_val);
2072
        remoteDispatchConnError(rerr, conn);
2073 2074
        return -1;
    }
2075 2076 2077 2078 2079

    return 0;
}

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

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
2090 2091 2092
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
        return -1;
2093 2094 2095
    }

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

    ret->names.names_len =
2102
        virConnectListNetworks (conn,
2103
                                ret->names.names_val, args->maxnames);
2104 2105
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_len);
2106
        remoteDispatchConnError(rerr, conn);
2107 2108
        return -1;
    }
2109 2110 2111 2112 2113

    return 0;
}

static int
2114
remoteDispatchNetworkCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
2115 2116
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn,
2117
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
2118
                             remote_error *rerr,
2119 2120 2121 2122 2123
                             remote_network_create_args *args,
                             void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2124
    net = get_nonnull_network (conn, args->net);
2125
    if (net == NULL) {
2126
        remoteDispatchConnError(rerr, conn);
2127
        return -1;
2128 2129
    }

2130 2131
    if (virNetworkCreate (net) == -1) {
        virNetworkFree(net);
2132
        remoteDispatchConnError(rerr, conn);
2133
        return -1;
2134 2135
    }
    virNetworkFree(net);
2136 2137 2138 2139
    return 0;
}

static int
2140
remoteDispatchNetworkCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2141 2142
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2143
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
2144
                                remote_error *rerr,
2145 2146 2147 2148 2149
                                remote_network_create_xml_args *args,
                                remote_network_create_xml_ret *ret)
{
    virNetworkPtr net;

2150
    net = virNetworkCreateXML (conn, args->xml);
2151
    if (net == NULL) {
2152
        remoteDispatchConnError(rerr, conn);
2153 2154
        return -1;
    }
2155 2156

    make_nonnull_network (&ret->net, net);
2157
    virNetworkFree(net);
2158 2159 2160 2161
    return 0;
}

static int
2162
remoteDispatchNetworkDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2163 2164
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
2165
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
2166
                                remote_error *rerr,
2167 2168 2169 2170 2171
                                remote_network_define_xml_args *args,
                                remote_network_define_xml_ret *ret)
{
    virNetworkPtr net;

2172
    net = virNetworkDefineXML (conn, args->xml);
2173
    if (net == NULL) {
2174
        remoteDispatchConnError(rerr, conn);
2175 2176
        return -1;
    }
2177 2178

    make_nonnull_network (&ret->net, net);
2179
    virNetworkFree(net);
2180 2181 2182 2183
    return 0;
}

static int
2184
remoteDispatchNetworkDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
2185 2186
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2187
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2188
                              remote_error *rerr,
2189 2190 2191 2192 2193
                              remote_network_destroy_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2194
    net = get_nonnull_network (conn, args->net);
2195
    if (net == NULL) {
2196
        remoteDispatchConnError(rerr, conn);
2197
        return -1;
2198 2199
    }

2200 2201
    if (virNetworkDestroy (net) == -1) {
        virNetworkFree(net);
2202
        remoteDispatchConnError(rerr, conn);
2203
        return -1;
2204 2205
    }
    virNetworkFree(net);
2206 2207 2208 2209
    return 0;
}

static int
2210
remoteDispatchNetworkDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
2211 2212
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2213
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
2214
                              remote_error *rerr,
2215 2216 2217 2218 2219
                              remote_network_dump_xml_args *args,
                              remote_network_dump_xml_ret *ret)
{
    virNetworkPtr net;

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

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNetworkGetXMLDesc (net, args->flags);
2228 2229
    if (!ret->xml) {
        virNetworkFree(net);
2230
        remoteDispatchConnError(rerr, conn);
2231 2232 2233
        return -1;
    }
    virNetworkFree(net);
2234 2235 2236 2237
    return 0;
}

static int
2238
remoteDispatchNetworkGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2239 2240
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2241
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2242
                                   remote_error *rerr,
2243 2244 2245 2246 2247
                                   remote_network_get_autostart_args *args,
                                   remote_network_get_autostart_ret *ret)
{
    virNetworkPtr net;

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

2254 2255
    if (virNetworkGetAutostart (net, &ret->autostart) == -1) {
        virNetworkFree(net);
2256
        remoteDispatchConnError(rerr, conn);
2257
        return -1;
2258 2259
    }
    virNetworkFree(net);
2260 2261 2262 2263
    return 0;
}

static int
2264
remoteDispatchNetworkGetBridgeName (struct qemud_server *server ATTRIBUTE_UNUSED,
2265 2266
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2267
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
2268
                                    remote_error *rerr,
2269 2270 2271 2272 2273
                                    remote_network_get_bridge_name_args *args,
                                    remote_network_get_bridge_name_ret *ret)
{
    virNetworkPtr net;

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

    /* remoteDispatchClientRequest will free this. */
    ret->name = virNetworkGetBridgeName (net);
2282 2283
    if (!ret->name) {
        virNetworkFree(net);
2284
        remoteDispatchConnError(rerr, conn);
2285 2286 2287
        return -1;
    }
    virNetworkFree(net);
2288 2289 2290 2291
    return 0;
}

static int
2292
remoteDispatchNetworkLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
2293 2294
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2295
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2296
                                   remote_error *rerr,
2297 2298 2299 2300 2301
                                   remote_network_lookup_by_name_args *args,
                                   remote_network_lookup_by_name_ret *ret)
{
    virNetworkPtr net;

2302
    net = virNetworkLookupByName (conn, args->name);
2303
    if (net == NULL) {
2304
        remoteDispatchConnError(rerr, conn);
2305 2306
        return -1;
    }
2307 2308

    make_nonnull_network (&ret->net, net);
2309
    virNetworkFree(net);
2310 2311 2312 2313
    return 0;
}

static int
2314
remoteDispatchNetworkLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
2315 2316
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2317
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2318
                                   remote_error *rerr,
2319 2320 2321 2322 2323
                                   remote_network_lookup_by_uuid_args *args,
                                   remote_network_lookup_by_uuid_ret *ret)
{
    virNetworkPtr net;

2324
    net = virNetworkLookupByUUID (conn, (unsigned char *) args->uuid);
2325
    if (net == NULL) {
2326
        remoteDispatchConnError(rerr, conn);
2327 2328
        return -1;
    }
2329 2330

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

static int
2336
remoteDispatchNetworkSetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
2337 2338
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2339
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
2340
                                   remote_error *rerr,
2341 2342 2343 2344 2345
                                   remote_network_set_autostart_args *args,
                                   void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2346
    net = get_nonnull_network (conn, args->net);
2347
    if (net == NULL) {
2348
        remoteDispatchConnError(rerr, conn);
2349
        return -1;
2350 2351
    }

2352 2353
    if (virNetworkSetAutostart (net, args->autostart) == -1) {
        virNetworkFree(net);
2354
        remoteDispatchConnError(rerr, conn);
2355
        return -1;
2356 2357
    }
    virNetworkFree(net);
2358 2359 2360 2361
    return 0;
}

static int
2362
remoteDispatchNetworkUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2363 2364
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2365
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
2366
                               remote_error *rerr,
2367 2368 2369 2370 2371
                               remote_network_undefine_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNetworkPtr net;

2372
    net = get_nonnull_network (conn, args->net);
2373
    if (net == NULL) {
2374
        remoteDispatchConnError(rerr, conn);
2375
        return -1;
2376 2377
    }

2378 2379
    if (virNetworkUndefine (net) == -1) {
        virNetworkFree(net);
2380
        remoteDispatchConnError(rerr, conn);
2381
        return -1;
2382 2383
    }
    virNetworkFree(net);
2384 2385 2386 2387
    return 0;
}

static int
2388
remoteDispatchNumOfDefinedNetworks (struct qemud_server *server ATTRIBUTE_UNUSED,
2389 2390
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
2391
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
2392
                                    remote_error *rerr,
2393 2394 2395 2396
                                    void *args ATTRIBUTE_UNUSED,
                                    remote_num_of_defined_networks_ret *ret)
{

2397
    ret->num = virConnectNumOfDefinedNetworks (conn);
2398
    if (ret->num == -1) {
2399
        remoteDispatchConnError(rerr, conn);
2400 2401
        return -1;
    }
2402 2403 2404 2405 2406

    return 0;
}

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

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

    return 0;
}

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

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

    return 0;
}

2444

D
Daniel Veillard 已提交
2445 2446 2447 2448 2449
/*-------------------------------------------------------------*/
static int
remoteDispatchNumOfInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
2450
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468
                               remote_error *rerr,
                               void *args ATTRIBUTE_UNUSED,
                               remote_num_of_interfaces_ret *ret)
{

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

    return 0;
}

static int
remoteDispatchListInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
                              virConnectPtr conn,
2469
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498
                              remote_error *rerr,
                              remote_list_interfaces_args *args,
                              remote_list_interfaces_ret *ret)
{

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

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

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

    return 0;
}

2499 2500 2501 2502
static int
remoteDispatchNumOfDefinedInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
2503
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521
                                      remote_error *rerr,
                                      void *args ATTRIBUTE_UNUSED,
                                      remote_num_of_defined_interfaces_ret *ret)
{

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

    return 0;
}

static int
remoteDispatchListDefinedInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
2522
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551
                                     remote_error *rerr,
                                     remote_list_defined_interfaces_args *args,
                                     remote_list_defined_interfaces_ret *ret)
{

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

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

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

    return 0;
}

D
Daniel Veillard 已提交
2552 2553 2554 2555
static int
remoteDispatchInterfaceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
2556
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2557 2558 2559 2560
                                     remote_error *rerr,
                                     remote_interface_lookup_by_name_args *args,
                                     remote_interface_lookup_by_name_ret *ret)
{
2561
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2562

2563 2564
    iface = virInterfaceLookupByName (conn, args->name);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2565 2566 2567 2568
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2569 2570
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2571 2572 2573 2574 2575 2576 2577
    return 0;
}

static int
remoteDispatchInterfaceLookupByMacString (struct qemud_server *server ATTRIBUTE_UNUSED,
                                          struct qemud_client *client ATTRIBUTE_UNUSED,
                                          virConnectPtr conn,
2578
                                          remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2579 2580 2581 2582
                                          remote_error *rerr,
                                          remote_interface_lookup_by_mac_string_args *args,
                                          remote_interface_lookup_by_mac_string_ret *ret)
{
2583
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2584

2585 2586
    iface = virInterfaceLookupByMACString (conn, args->mac);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2587 2588 2589 2590
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2591 2592
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2593 2594 2595 2596 2597 2598 2599
    return 0;
}

static int
remoteDispatchInterfaceGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
2600
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2601 2602 2603 2604
                                   remote_error *rerr,
                                   remote_interface_get_xml_desc_args *args,
                                   remote_interface_get_xml_desc_ret *ret)
{
2605
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2606

2607 2608
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2609 2610 2611 2612 2613
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    /* remoteDispatchClientRequest will free this. */
2614
    ret->xml = virInterfaceGetXMLDesc (iface, args->flags);
D
Daniel Veillard 已提交
2615
    if (!ret->xml) {
2616
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
2617 2618 2619
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
2620
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2621 2622 2623 2624 2625 2626 2627
    return 0;
}

static int
remoteDispatchInterfaceDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
2628
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
D
Daniel Veillard 已提交
2629 2630 2631 2632
                                  remote_error *rerr,
                                  remote_interface_define_xml_args *args,
                                  remote_interface_define_xml_ret *ret)
{
2633
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2634

2635 2636
    iface = virInterfaceDefineXML (conn, args->xml, args->flags);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2637 2638 2639 2640
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2641 2642
    make_nonnull_interface (&ret->iface, iface);
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2643 2644 2645 2646 2647
    return 0;
}

static int
remoteDispatchInterfaceUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
2648 2649 2650 2651 2652 2653
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
                                 remote_error *rerr,
                                 remote_interface_undefine_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
D
Daniel Veillard 已提交
2654
{
2655
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2656

2657 2658
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2659 2660 2661 2662
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2663 2664
    if (virInterfaceUndefine (iface) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
2665 2666 2667
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
2668
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2669 2670 2671 2672 2673
    return 0;
}

static int
remoteDispatchInterfaceCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
2674 2675 2676 2677 2678 2679
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *rerr,
                               remote_interface_create_args *args,
                               void *ret ATTRIBUTE_UNUSED)
D
Daniel Veillard 已提交
2680
{
2681
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2682

2683 2684
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2685 2686 2687 2688
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2689 2690
    if (virInterfaceCreate (iface, args->flags) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
2691 2692 2693
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
2694
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2695 2696 2697 2698 2699
    return 0;
}

static int
remoteDispatchInterfaceDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
2700 2701 2702 2703 2704 2705
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *rerr,
                                remote_interface_destroy_args *args,
                                void *ret ATTRIBUTE_UNUSED)
D
Daniel Veillard 已提交
2706
{
2707
    virInterfacePtr iface;
D
Daniel Veillard 已提交
2708

2709 2710
    iface = get_nonnull_interface (conn, args->iface);
    if (iface == NULL) {
D
Daniel Veillard 已提交
2711 2712 2713 2714
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

2715 2716
    if (virInterfaceDestroy (iface, args->flags) == -1) {
        virInterfaceFree(iface);
D
Daniel Veillard 已提交
2717 2718 2719
        remoteDispatchConnError(rerr, conn);
        return -1;
    }
2720
    virInterfaceFree(iface);
D
Daniel Veillard 已提交
2721 2722 2723 2724 2725
    return 0;
}

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

2726
static int
2727
remoteDispatchAuthList (struct qemud_server *server,
2728
                        struct qemud_client *client,
2729
                        virConnectPtr conn ATTRIBUTE_UNUSED,
2730
                        remote_message_header *hdr ATTRIBUTE_UNUSED,
2731
                        remote_error *rerr,
2732 2733 2734 2735
                        void *args ATTRIBUTE_UNUSED,
                        remote_auth_list_ret *ret)
{
    ret->types.types_len = 1;
2736
    if (VIR_ALLOC_N(ret->types.types_val, ret->types.types_len) < 0) {
2737 2738
        remoteDispatchOOMError(rerr);
        return -1;
2739
    }
2740 2741 2742
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
2743
    ret->types.types_val[0] = client->auth;
2744
    virMutexUnlock(&client->lock);
2745

2746 2747 2748 2749 2750 2751 2752 2753
    return 0;
}


#if HAVE_SASL
/*
 * NB, keep in sync with similar method in src/remote_internal.c
 */
2754
static char *addrToString(remote_error *rerr,
2755 2756 2757 2758 2759 2760 2761 2762 2763
                          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) {
2764 2765 2766
        remoteDispatchFormatError(rerr,
                                  _("Cannot resolve address %d: %s"),
                                  err, gai_strerror(err));
2767 2768 2769
        return NULL;
    }

2770 2771
    if (virAsprintf(&addr, "%s;%s", host, port) == -1) {
        virReportOOMError(NULL);
2772 2773 2774 2775 2776 2777 2778 2779 2780
        return NULL;
    }

    return addr;
}


/*
 * Initializes the SASL session in prepare for authentication
2781
 * and gives the client a list of allowed mechanisms to choose
2782 2783 2784 2785
 *
 * XXX callbacks for stuff like password verification ?
 */
static int
2786
remoteDispatchAuthSaslInit (struct qemud_server *server,
2787
                            struct qemud_client *client,
2788
                            virConnectPtr conn ATTRIBUTE_UNUSED,
2789
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
2790
                            remote_error *rerr,
2791 2792 2793 2794
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret)
{
    const char *mechlist = NULL;
2795
    sasl_security_properties_t secprops;
2796 2797 2798 2799 2800
    int err;
    struct sockaddr_storage sa;
    socklen_t salen;
    char *localAddr, *remoteAddr;

2801 2802 2803
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
2804

2805 2806 2807
    REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn != NULL) {
2808
        VIR_ERROR0(_("client tried invalid SASL init request"));
2809
        goto authfail;
2810 2811 2812 2813 2814
    }

    /* Get local address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getsockname(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
2815
        char ebuf[1024];
2816
        remoteDispatchFormatError(rerr,
2817
                                  _("failed to get sock address: %s"),
2818
                                  virStrerror(errno, ebuf, sizeof ebuf));
2819
        goto error;
2820
    }
2821
    if ((localAddr = addrToString(rerr, &sa, salen)) == NULL) {
2822
        goto error;
2823 2824 2825 2826 2827
    }

    /* Get remote address in form  IPADDR:PORT */
    salen = sizeof(sa);
    if (getpeername(client->fd, (struct sockaddr*)&sa, &salen) < 0) {
2828
        char ebuf[1024];
2829
        remoteDispatchFormatError(rerr, _("failed to get peer address: %s"),
2830
                                  virStrerror(errno, ebuf, sizeof ebuf));
2831
        VIR_FREE(localAddr);
2832
        goto error;
2833
    }
2834
    if ((remoteAddr = addrToString(rerr, &sa, salen)) == NULL) {
2835
        VIR_FREE(localAddr);
2836
        goto error;
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
    }

    err = sasl_server_new("libvirt",
                          NULL, /* FQDN - just delegates to gethostname */
                          NULL, /* User realm */
                          localAddr,
                          remoteAddr,
                          NULL, /* XXX Callbacks */
                          SASL_SUCCESS_DATA,
                          &client->saslconn);
2847 2848
    VIR_FREE(localAddr);
    VIR_FREE(remoteAddr);
2849
    if (err != SASL_OK) {
2850 2851
        VIR_ERROR(_("sasl context setup failed %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2852
        client->saslconn = NULL;
2853
        goto authfail;
2854 2855
    }

2856 2857 2858 2859 2860 2861 2862
    /* Inform SASL that we've got an external SSF layer from TLS */
    if (client->type == QEMUD_SOCK_TYPE_TLS) {
        gnutls_cipher_algorithm_t cipher;
        sasl_ssf_t ssf;

        cipher = gnutls_cipher_get(client->tlssession);
        if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) {
D
Daniel Veillard 已提交
2863
            VIR_ERROR0(_("cannot get TLS cipher size"));
2864 2865
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
2866
            goto authfail;
2867 2868 2869 2870 2871
        }
        ssf *= 8; /* tls key size is bytes, sasl wants bits */

        err = sasl_setprop(client->saslconn, SASL_SSF_EXTERNAL, &ssf);
        if (err != SASL_OK) {
2872 2873
            VIR_ERROR(_("cannot set SASL external SSF %d (%s)"),
                      err, sasl_errstring(err, NULL, NULL));
2874 2875
            sasl_dispose(&client->saslconn);
            client->saslconn = NULL;
2876
            goto authfail;
2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899
        }
    }

    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) {
2900 2901
        VIR_ERROR(_("cannot set SASL security props %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2902 2903
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2904
        goto authfail;
2905 2906
    }

2907 2908 2909 2910 2911 2912 2913 2914 2915
    err = sasl_listmech(client->saslconn,
                        NULL, /* Don't need to set user */
                        "", /* Prefix */
                        ",", /* Separator */
                        "", /* Suffix */
                        &mechlist,
                        NULL,
                        NULL);
    if (err != SASL_OK) {
2916 2917
        VIR_ERROR(_("cannot list SASL mechanisms %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
2918 2919
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2920
        goto authfail;
2921 2922 2923 2924
    }
    REMOTE_DEBUG("Available mechanisms for client: '%s'", mechlist);
    ret->mechlist = strdup(mechlist);
    if (!ret->mechlist) {
2925
        VIR_ERROR0(_("cannot allocate mechlist"));
2926 2927
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
2928
        goto authfail;
2929 2930
    }

2931
    virMutexUnlock(&client->lock);
2932
    return 0;
2933 2934 2935 2936

authfail:
    remoteDispatchAuthError(rerr);
error:
2937
    virMutexUnlock(&client->lock);
2938
    return -1;
2939 2940 2941
}


2942
/* We asked for an SSF layer, so sanity check that we actually
2943 2944 2945
 * got what we asked for */
static int
remoteSASLCheckSSF (struct qemud_client *client,
2946
                    remote_error *rerr) {
2947 2948 2949 2950 2951 2952 2953 2954 2955
    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) {
2956 2957
        VIR_ERROR(_("cannot query SASL ssf on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2958
        remoteDispatchAuthError(rerr);
2959 2960 2961 2962 2963 2964 2965
        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 */
2966
        VIR_ERROR(_("negotiated SSF %d was not strong enough"), ssf);
2967
        remoteDispatchAuthError(rerr);
2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984
        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;
}

2985 2986 2987
static int
remoteSASLCheckAccess (struct qemud_server *server,
                       struct qemud_client *client,
2988
                       remote_error *rerr) {
2989 2990 2991 2992 2993 2994
    const void *val;
    int err;
    char **wildcards;

    err = sasl_getprop(client->saslconn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
2995 2996
        VIR_ERROR(_("cannot query SASL username on connection %d (%s)"),
                  err, sasl_errstring(err, NULL, NULL));
2997
        remoteDispatchAuthError(rerr);
2998 2999 3000 3001 3002
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
        return -1;
    }
    if (val == NULL) {
3003
        VIR_ERROR0(_("no client username was found"));
3004
        remoteDispatchAuthError(rerr);
3005 3006 3007 3008 3009 3010 3011 3012
        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) {
3013
        VIR_ERROR0(_("out of memory copying username"));
3014
        remoteDispatchAuthError(rerr);
3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031
        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 */
3032
    VIR_ERROR(_("SASL client %s not allowed in whitelist"), client->saslUsername);
3033
    remoteDispatchAuthError(rerr);
3034 3035 3036 3037 3038 3039
    sasl_dispose(&client->saslconn);
    client->saslconn = NULL;
    return -1;
}


3040 3041 3042 3043
/*
 * This starts the SASL authentication negotiation.
 */
static int
3044 3045
remoteDispatchAuthSaslStart (struct qemud_server *server,
                             struct qemud_client *client,
3046
                             virConnectPtr conn ATTRIBUTE_UNUSED,
3047
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
3048
                             remote_error *rerr,
3049 3050 3051 3052 3053 3054 3055
                             remote_auth_sasl_start_args *args,
                             remote_auth_sasl_start_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

3056 3057 3058
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3059

3060 3061 3062
    REMOTE_DEBUG("Start SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
3063
        VIR_ERROR0(_("client tried invalid SASL start request"));
3064
        goto authfail;
3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077
    }

    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) {
3078 3079
        VIR_ERROR(_("sasl start failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3080 3081
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3082
        goto authfail;
3083 3084
    }
    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
3085
        VIR_ERROR(_("sasl start reply data too long %d"), serveroutlen);
3086 3087
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3088
        goto authfail;
3089 3090 3091 3092
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
3093
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
3094
            remoteDispatchOOMError(rerr);
3095
            goto error;
3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107
        }
        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 {
3108
        if (remoteSASLCheckSSF(client, rerr) < 0)
3109
            goto error;
3110

3111
        /* Check username whitelist ACL */
3112
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
3113
            goto error;
3114

3115 3116 3117 3118 3119
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

3120
    virMutexUnlock(&client->lock);
3121
    return 0;
3122 3123 3124 3125

authfail:
    remoteDispatchAuthError(rerr);
error:
3126
    virMutexUnlock(&client->lock);
3127
    return -1;
3128 3129 3130 3131
}


static int
3132 3133
remoteDispatchAuthSaslStep (struct qemud_server *server,
                            struct qemud_client *client,
3134
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3135
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3136
                            remote_error *rerr,
3137 3138 3139 3140 3141 3142 3143
                            remote_auth_sasl_step_args *args,
                            remote_auth_sasl_step_ret *ret)
{
    const char *serverout;
    unsigned int serveroutlen;
    int err;

3144 3145 3146
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3147

3148 3149 3150
    REMOTE_DEBUG("Step SASL auth %d", client->fd);
    if (client->auth != REMOTE_AUTH_SASL ||
        client->saslconn == NULL) {
3151
        VIR_ERROR0(_("client tried invalid SASL start request"));
3152
        goto authfail;
3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164
    }

    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) {
3165 3166
        VIR_ERROR(_("sasl step failed %d (%s)"),
                  err, sasl_errdetail(client->saslconn));
3167 3168
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3169
        goto authfail;
3170 3171 3172
    }

    if (serveroutlen > REMOTE_AUTH_SASL_DATA_MAX) {
3173 3174
        VIR_ERROR(_("sasl step reply data too long %d"),
                  serveroutlen);
3175 3176
        sasl_dispose(&client->saslconn);
        client->saslconn = NULL;
3177
        goto authfail;
3178 3179 3180 3181
    }

    /* NB, distinction of NULL vs "" is *critical* in SASL */
    if (serverout) {
3182
        if (VIR_ALLOC_N(ret->data.data_val, serveroutlen) < 0) {
3183
            remoteDispatchOOMError(rerr);
3184
            goto error;
3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196
        }
        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 {
3197
        if (remoteSASLCheckSSF(client, rerr) < 0)
3198
            goto error;
3199

3200
        /* Check username whitelist ACL */
3201
        if (remoteSASLCheckAccess(server, client, rerr) < 0)
3202
            goto error;
3203

3204 3205 3206 3207 3208
        REMOTE_DEBUG("Authentication successful %d", client->fd);
        ret->complete = 1;
        client->auth = REMOTE_AUTH_NONE;
    }

3209
    virMutexUnlock(&client->lock);
3210
    return 0;
3211 3212 3213 3214

authfail:
    remoteDispatchAuthError(rerr);
error:
3215
    virMutexUnlock(&client->lock);
3216
    return -1;
3217 3218 3219 3220 3221
}


#else /* HAVE_SASL */
static int
3222
remoteDispatchAuthSaslInit (struct qemud_server *server ATTRIBUTE_UNUSED,
3223 3224
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3225
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3226
                            remote_error *rerr,
3227 3228 3229
                            void *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_init_ret *ret ATTRIBUTE_UNUSED)
{
3230
    VIR_ERROR0(_("client tried unsupported SASL init request"));
3231
    remoteDispatchAuthError(rerr);
3232 3233 3234 3235
    return -1;
}

static int
3236
remoteDispatchAuthSaslStart (struct qemud_server *server ATTRIBUTE_UNUSED,
3237 3238
                             struct qemud_client *client ATTRIBUTE_UNUSED,
                             virConnectPtr conn ATTRIBUTE_UNUSED,
3239
                             remote_message_header *hdr ATTRIBUTE_UNUSED,
3240
                             remote_error *rerr,
3241 3242 3243
                             remote_auth_sasl_start_args *args ATTRIBUTE_UNUSED,
                             remote_auth_sasl_start_ret *ret ATTRIBUTE_UNUSED)
{
3244
    VIR_ERROR0(_("client tried unsupported SASL start request"));
3245
    remoteDispatchAuthError(rerr);
3246 3247 3248 3249
    return -1;
}

static int
3250
remoteDispatchAuthSaslStep (struct qemud_server *server ATTRIBUTE_UNUSED,
3251 3252
                            struct qemud_client *client ATTRIBUTE_UNUSED,
                            virConnectPtr conn ATTRIBUTE_UNUSED,
3253
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
3254
                            remote_error *rerr,
3255 3256 3257
                            remote_auth_sasl_step_args *args ATTRIBUTE_UNUSED,
                            remote_auth_sasl_step_ret *ret ATTRIBUTE_UNUSED)
{
3258
    VIR_ERROR0(_("client tried unsupported SASL step request"));
3259
    remoteDispatchAuthError(rerr);
3260 3261 3262 3263 3264
    return -1;
}
#endif /* HAVE_SASL */


3265 3266 3267 3268 3269
#if HAVE_POLKIT1
static int
remoteDispatchAuthPolkit (struct qemud_server *server,
                          struct qemud_client *client,
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3270
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
    pid_t callerPid;
    uid_t callerUid;
    const char *action;
    int status = -1;
    char pidbuf[50];
    int rv;

    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);

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

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

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

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

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

    rv = snprintf(pidbuf, sizeof pidbuf, "%d", callerPid);
    if (rv < 0 || rv >= sizeof pidbuf) {
        VIR_ERROR(_("Caller PID was too large %d"), callerPid);
3314
        goto authfail;
3315 3316 3317 3318
    }

    if (virRun(NULL, pkcheck, &status) < 0) {
        VIR_ERROR(_("Cannot invoke %s"), PKCHECK_PATH);
3319
        goto authfail;
3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339
    }
    if (status != 0) {
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %d\n"),
                  action, callerPid, callerUid, status);
        goto authfail;
    }
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d"),
             action, callerPid, callerUid);
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;

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

authfail:
    remoteDispatchAuthError(rerr);
    virMutexUnlock(&client->lock);
    return -1;
}
#elif HAVE_POLKIT0
3340
static int
3341
remoteDispatchAuthPolkit (struct qemud_server *server,
3342
                          struct qemud_client *client,
3343
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3344
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3345
                          remote_error *rerr,
3346 3347 3348 3349 3350
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret)
{
    pid_t callerPid;
    uid_t callerUid;
3351 3352 3353 3354 3355 3356
    PolKitCaller *pkcaller = NULL;
    PolKitAction *pkaction = NULL;
    PolKitContext *pkcontext = NULL;
    PolKitError *pkerr = NULL;
    PolKitResult pkresult;
    DBusError err;
3357 3358
    const char *action;

3359 3360 3361
    virMutexLock(&server->lock);
    virMutexLock(&client->lock);
    virMutexUnlock(&server->lock);
3362 3363

    action = client->readonly ?
3364 3365
        "org.libvirt.unix.monitor" :
        "org.libvirt.unix.manage";
3366 3367 3368

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

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

3378
    VIR_INFO(_("Checking PID %d running as %d"), callerPid, callerUid);
3379 3380 3381
    dbus_error_init(&err);
    if (!(pkcaller = polkit_caller_new_from_pid(server->sysbus,
                                                callerPid, &err))) {
3382
        VIR_ERROR(_("Failed to lookup policy kit caller: %s"), err.message);
3383
        dbus_error_free(&err);
3384
        goto authfail;
3385
    }
3386

3387
    if (!(pkaction = polkit_action_new())) {
3388 3389 3390
        char ebuf[1024];
        VIR_ERROR(_("Failed to create polkit action %s\n"),
                  virStrerror(errno, ebuf, sizeof ebuf));
3391
        polkit_caller_unref(pkcaller);
3392
        goto authfail;
3393 3394 3395 3396 3397
    }
    polkit_action_set_action_id(pkaction, action);

    if (!(pkcontext = polkit_context_new()) ||
        !polkit_context_init(pkcontext, &pkerr)) {
3398
        char ebuf[1024];
3399 3400
        VIR_ERROR(_("Failed to create polkit context %s\n"),
                  (pkerr ? polkit_error_get_error_message(pkerr)
3401
                   : virStrerror(errno, ebuf, sizeof ebuf)));
3402 3403 3404 3405 3406
        if (pkerr)
            polkit_error_free(pkerr);
        polkit_caller_unref(pkcaller);
        polkit_action_unref(pkaction);
        dbus_error_free(&err);
3407
        goto authfail;
3408
    }
3409

3410
#if HAVE_POLKIT_CONTEXT_IS_CALLER_AUTHORIZED
3411 3412 3413 3414 3415 3416
    pkresult = polkit_context_is_caller_authorized(pkcontext,
                                                   pkaction,
                                                   pkcaller,
                                                   0,
                                                   &pkerr);
    if (pkerr && polkit_error_is_set(pkerr)) {
3417 3418 3419
        VIR_ERROR(_("Policy kit failed to check authorization %d %s"),
                  polkit_error_get_error_code(pkerr),
                  polkit_error_get_error_message(pkerr));
3420
        goto authfail;
3421
    }
3422
#else
3423 3424 3425
    pkresult = polkit_context_can_caller_do_action(pkcontext,
                                                   pkaction,
                                                   pkcaller);
3426
#endif
3427 3428 3429 3430
    polkit_context_unref(pkcontext);
    polkit_caller_unref(pkcaller);
    polkit_action_unref(pkaction);
    if (pkresult != POLKIT_RESULT_YES) {
3431 3432 3433
        VIR_ERROR(_("Policy kit denied action %s from pid %d, uid %d, result: %s\n"),
                  action, callerPid, callerUid,
                  polkit_result_to_string_representation(pkresult));
3434
        goto authfail;
3435
    }
3436
    VIR_INFO(_("Policy allowed action %s from pid %d, uid %d, result %s"),
3437 3438 3439 3440
             action, callerPid, callerUid,
             polkit_result_to_string_representation(pkresult));
    ret->complete = 1;
    client->auth = REMOTE_AUTH_NONE;
3441

3442
    virMutexUnlock(&client->lock);
3443
    return 0;
3444 3445 3446

authfail:
    remoteDispatchAuthError(rerr);
3447
    virMutexUnlock(&client->lock);
3448
    return -1;
3449 3450
}

3451
#else /* !HAVE_POLKIT0 & !HAVE_POLKIT1*/
3452 3453

static int
3454
remoteDispatchAuthPolkit (struct qemud_server *server ATTRIBUTE_UNUSED,
3455
                          struct qemud_client *client ATTRIBUTE_UNUSED,
3456
                          virConnectPtr conn ATTRIBUTE_UNUSED,
3457
                          remote_message_header *hdr ATTRIBUTE_UNUSED,
3458 3459 3460
                          remote_error *rerr,
                          void *args ATTRIBUTE_UNUSED,
                          remote_auth_polkit_ret *ret ATTRIBUTE_UNUSED)
3461
{
3462
    VIR_ERROR0(_("client tried unsupported PolicyKit init request"));
3463
    remoteDispatchAuthError(rerr);
3464 3465
    return -1;
}
3466
#endif /* HAVE_POLKIT1 */
3467

3468 3469 3470 3471 3472 3473 3474 3475

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


static int
remoteDispatchListDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3476 3477
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3478
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
3479
                                       remote_error *rerr,
3480 3481 3482 3483 3484
                                       remote_list_defined_storage_pools_args *args,
                                       remote_list_defined_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
3485 3486
        remoteDispatchFormatError (rerr, "%s",
                            _("maxnames > REMOTE_NETWORK_NAME_LIST_MAX"));
3487
        return -1;
3488 3489 3490
    }

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

    ret->names.names_len =
3497
        virConnectListDefinedStoragePools (conn,
3498 3499 3500
                                           ret->names.names_val, args->maxnames);
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3501
        remoteDispatchConnError(rerr, conn);
3502 3503
        return -1;
    }
3504 3505 3506 3507 3508 3509

    return 0;
}

static int
remoteDispatchListStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3510 3511
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3512
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
3513
                                remote_error *rerr,
3514 3515 3516 3517 3518
                                remote_list_storage_pools_args *args,
                                remote_list_storage_pools_ret *ret)
{

    if (args->maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
3519 3520 3521
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX"));
        return -1;
3522 3523 3524
    }

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

    ret->names.names_len =
3531
        virConnectListStoragePools (conn,
3532
                                ret->names.names_val, args->maxnames);
3533 3534
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
3535
        remoteDispatchConnError(rerr, conn);
3536 3537
        return -1;
    }
3538 3539 3540 3541

    return 0;
}

3542 3543
static int
remoteDispatchFindStoragePoolSources (struct qemud_server *server ATTRIBUTE_UNUSED,
3544 3545
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3546
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
3547
                                      remote_error *rerr,
3548 3549 3550 3551
                                      remote_find_storage_pool_sources_args *args,
                                      remote_find_storage_pool_sources_ret *ret)
{
    ret->xml =
3552
        virConnectFindStoragePoolSources (conn,
3553 3554 3555
                                          args->type,
                                          args->srcSpec ? *args->srcSpec : NULL,
                                          args->flags);
3556
    if (ret->xml == NULL) {
3557
        remoteDispatchConnError(rerr, conn);
3558
        return -1;
3559
    }
3560 3561 3562 3563 3564

    return 0;
}


3565 3566
static int
remoteDispatchStoragePoolCreate (struct qemud_server *server ATTRIBUTE_UNUSED,
3567 3568
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3569
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
3570
                                 remote_error *rerr,
3571 3572 3573 3574 3575
                                 remote_storage_pool_create_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

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

    if (virStoragePoolCreate (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3584
        remoteDispatchConnError(rerr, conn);
3585 3586 3587 3588 3589 3590 3591 3592
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3593 3594
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3595
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
3596
                                    remote_error *rerr,
3597 3598 3599 3600 3601
                                    remote_storage_pool_create_xml_args *args,
                                    remote_storage_pool_create_xml_ret *ret)
{
    virStoragePoolPtr pool;

3602
    pool = virStoragePoolCreateXML (conn, args->xml, args->flags);
3603
    if (pool == NULL) {
3604
        remoteDispatchConnError(rerr, conn);
3605 3606
        return -1;
    }
3607 3608 3609 3610 3611 3612 3613 3614

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

static int
remoteDispatchStoragePoolDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
3615 3616
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
3617
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
3618
                                    remote_error *rerr,
3619 3620 3621 3622 3623
                                    remote_storage_pool_define_xml_args *args,
                                    remote_storage_pool_define_xml_ret *ret)
{
    virStoragePoolPtr pool;

3624
    pool = virStoragePoolDefineXML (conn, args->xml, args->flags);
3625
    if (pool == NULL) {
3626
        remoteDispatchConnError(rerr, conn);
3627 3628
        return -1;
    }
3629 3630 3631 3632 3633 3634 3635 3636

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

static int
remoteDispatchStoragePoolBuild (struct qemud_server *server ATTRIBUTE_UNUSED,
3637 3638
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
3639
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
3640 3641 3642
                                remote_error *rerr,
                                remote_storage_pool_build_args *args,
                                void *ret ATTRIBUTE_UNUSED)
3643 3644 3645
{
    virStoragePoolPtr pool;

3646
    pool = get_nonnull_storage_pool (conn, args->pool);
3647
    if (pool == NULL) {
3648
        remoteDispatchConnError(rerr, conn);
3649
        return -1;
3650 3651 3652 3653
    }

    if (virStoragePoolBuild (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3654
        remoteDispatchConnError(rerr, conn);
3655 3656 3657 3658 3659 3660 3661 3662 3663
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolDestroy (struct qemud_server *server ATTRIBUTE_UNUSED,
3664 3665
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3666
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
3667
                                  remote_error *rerr,
3668 3669 3670 3671 3672
                                  remote_storage_pool_destroy_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3673
    pool = get_nonnull_storage_pool (conn, args->pool);
3674
    if (pool == NULL) {
3675
        remoteDispatchConnError(rerr, conn);
3676
        return -1;
3677 3678 3679 3680
    }

    if (virStoragePoolDestroy (pool) == -1) {
        virStoragePoolFree(pool);
3681
        remoteDispatchConnError(rerr, conn);
3682 3683 3684 3685 3686 3687 3688 3689
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
3690 3691
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3692
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
3693
                                 remote_error *rerr,
3694 3695 3696 3697 3698
                                 remote_storage_pool_delete_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

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

    if (virStoragePoolDelete (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3707
        remoteDispatchConnError(rerr, conn);
3708 3709 3710 3711 3712 3713 3714 3715
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolRefresh (struct qemud_server *server ATTRIBUTE_UNUSED,
3716 3717
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3718
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
3719
                                  remote_error *rerr,
3720 3721 3722 3723 3724
                                  remote_storage_pool_refresh_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virStoragePoolPtr pool;

3725
    pool = get_nonnull_storage_pool (conn, args->pool);
3726
    if (pool == NULL) {
3727
        remoteDispatchConnError(rerr, conn);
3728
        return -1;
3729 3730 3731 3732
    }

    if (virStoragePoolRefresh (pool, args->flags) == -1) {
        virStoragePoolFree(pool);
3733
        remoteDispatchConnError(rerr, conn);
3734 3735 3736 3737 3738 3739 3740 3741
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
3742 3743
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3744
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
3745
                                  remote_error *rerr,
3746 3747 3748 3749 3750 3751
                                  remote_storage_pool_get_info_args *args,
                                  remote_storage_pool_get_info_ret *ret)
{
    virStoragePoolPtr pool;
    virStoragePoolInfo info;

3752
    pool = get_nonnull_storage_pool (conn, args->pool);
3753
    if (pool == NULL) {
3754
        remoteDispatchConnError(rerr, conn);
3755
        return -1;
3756 3757 3758 3759
    }

    if (virStoragePoolGetInfo (pool, &info) == -1) {
        virStoragePoolFree(pool);
3760
        remoteDispatchConnError(rerr, conn);
3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775
        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,
3776 3777
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
3778
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
3779
                                  remote_error *rerr,
3780 3781 3782 3783 3784
                                  remote_storage_pool_dump_xml_args *args,
                                  remote_storage_pool_dump_xml_ret *ret)
{
    virStoragePoolPtr pool;

3785
    pool = get_nonnull_storage_pool (conn, args->pool);
3786
    if (pool == NULL) {
3787
        remoteDispatchConnError(rerr, conn);
3788
        return -1;
3789 3790 3791 3792 3793 3794
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStoragePoolGetXMLDesc (pool, args->flags);
    if (!ret->xml) {
        virStoragePoolFree(pool);
3795
        remoteDispatchConnError(rerr, conn);
3796 3797 3798 3799 3800 3801 3802 3803
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchStoragePoolGetAutostart (struct qemud_server *server ATTRIBUTE_UNUSED,
3804 3805
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3806
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
3807
                                       remote_error *rerr,
3808 3809 3810 3811 3812
                                       remote_storage_pool_get_autostart_args *args,
                                       remote_storage_pool_get_autostart_ret *ret)
{
    virStoragePoolPtr pool;

3813
    pool = get_nonnull_storage_pool (conn, args->pool);
3814
    if (pool == NULL) {
3815
        remoteDispatchConnError(rerr, conn);
3816
        return -1;
3817 3818 3819 3820
    }

    if (virStoragePoolGetAutostart (pool, &ret->autostart) == -1) {
        virStoragePoolFree(pool);
3821
        remoteDispatchConnError(rerr, conn);
3822 3823 3824 3825 3826 3827 3828 3829 3830
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}


static int
remoteDispatchStoragePoolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
3831 3832
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3833
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
3834
                                       remote_error *rerr,
3835 3836 3837 3838 3839
                                       remote_storage_pool_lookup_by_name_args *args,
                                       remote_storage_pool_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;

3840
    pool = virStoragePoolLookupByName (conn, args->name);
3841
    if (pool == NULL) {
3842
        remoteDispatchConnError(rerr, conn);
3843 3844
        return -1;
    }
3845 3846 3847 3848 3849 3850 3851 3852

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

static int
remoteDispatchStoragePoolLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
3853 3854
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
3855
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
3856
                                       remote_error *rerr,
3857 3858 3859 3860 3861
                                       remote_storage_pool_lookup_by_uuid_args *args,
                                       remote_storage_pool_lookup_by_uuid_ret *ret)
{
    virStoragePoolPtr pool;

3862
    pool = virStoragePoolLookupByUUID (conn, (unsigned char *) args->uuid);
3863
    if (pool == NULL) {
3864
        remoteDispatchConnError(rerr, conn);
3865 3866
        return -1;
    }
3867 3868 3869 3870 3871 3872 3873 3874

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

static int
remoteDispatchStoragePoolLookupByVolume (struct qemud_server *server ATTRIBUTE_UNUSED,
3875 3876
                                         struct qemud_client *client ATTRIBUTE_UNUSED,
                                         virConnectPtr conn,
3877
                                         remote_message_header *hdr ATTRIBUTE_UNUSED,
3878
                                         remote_error *rerr,
3879 3880 3881 3882 3883 3884
                                         remote_storage_pool_lookup_by_volume_args *args,
                                         remote_storage_pool_lookup_by_volume_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

3885
    vol = get_nonnull_storage_vol (conn, args->vol);
3886
    if (vol == NULL) {
3887
        remoteDispatchConnError(rerr, conn);
3888 3889
        return -1;
    }
3890 3891 3892

    pool = virStoragePoolLookupByVolume (vol);
    virStorageVolFree(vol);
3893
    if (pool == NULL) {
3894
        remoteDispatchConnError(rerr, conn);
3895 3896
        return -1;
    }
3897 3898 3899 3900 3901 3902 3903 3904

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

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

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

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

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

3940
    pool = get_nonnull_storage_pool (conn, args->pool);
3941
    if (pool == NULL) {
3942
        remoteDispatchConnError(rerr, conn);
3943
        return -1;
3944 3945 3946 3947
    }

    if (virStoragePoolUndefine (pool) == -1) {
        virStoragePoolFree(pool);
3948
        remoteDispatchConnError(rerr, conn);
3949 3950 3951 3952 3953 3954 3955 3956
        return -1;
    }
    virStoragePoolFree(pool);
    return 0;
}

static int
remoteDispatchNumOfStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3957 3958
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
3959
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
3960
                                 remote_error *rerr,
3961 3962 3963 3964
                                 void *args ATTRIBUTE_UNUSED,
                                 remote_num_of_storage_pools_ret *ret)
{

3965
    ret->num = virConnectNumOfStoragePools (conn);
3966
    if (ret->num == -1) {
3967
        remoteDispatchConnError(rerr, conn);
3968 3969
        return -1;
    }
3970 3971 3972 3973 3974 3975

    return 0;
}

static int
remoteDispatchNumOfDefinedStoragePools (struct qemud_server *server ATTRIBUTE_UNUSED,
3976 3977
                                        struct qemud_client *client ATTRIBUTE_UNUSED,
                                        virConnectPtr conn,
3978
                                        remote_message_header *hdr ATTRIBUTE_UNUSED,
3979
                                        remote_error *rerr,
3980 3981 3982 3983
                                        void *args ATTRIBUTE_UNUSED,
                                        remote_num_of_defined_storage_pools_ret *ret)
{

3984
    ret->num = virConnectNumOfDefinedStoragePools (conn);
3985
    if (ret->num == -1) {
3986
        remoteDispatchConnError(rerr, conn);
3987 3988
        return -1;
    }
3989 3990 3991 3992 3993 3994

    return 0;
}

static int
remoteDispatchStoragePoolListVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
3995 3996
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
3997
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
3998
                                      remote_error *rerr,
3999 4000 4001 4002 4003 4004
                                      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) {
4005 4006 4007
        remoteDispatchFormatError (rerr,
                                   "%s", _("maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX"));
        return -1;
4008 4009
    }

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

    /* Allocate return buffer. */
4017 4018
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
        virStoragePoolFree(pool);
4019 4020
        remoteDispatchOOMError(rerr);
        return -1;
4021
    }
4022 4023 4024 4025 4026

    ret->names.names_len =
        virStoragePoolListVolumes (pool,
                                   ret->names.names_val, args->maxnames);
    virStoragePoolFree(pool);
4027 4028
    if (ret->names.names_len == -1) {
        VIR_FREE(ret->names.names_val);
4029
        remoteDispatchConnError(rerr, conn);
4030 4031
        return -1;
    }
4032 4033 4034 4035 4036 4037 4038

    return 0;
}


static int
remoteDispatchStoragePoolNumOfVolumes (struct qemud_server *server ATTRIBUTE_UNUSED,
4039 4040
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4041
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4042
                                       remote_error *rerr,
4043 4044 4045 4046 4047
                                       remote_storage_pool_num_of_volumes_args *args,
                                       remote_storage_pool_num_of_volumes_ret *ret)
{
    virStoragePoolPtr pool;

4048
    pool = get_nonnull_storage_pool (conn, args->pool);
4049
    if (pool == NULL) {
4050
        remoteDispatchConnError(rerr, conn);
4051
        return -1;
4052 4053 4054 4055
    }

    ret->num = virStoragePoolNumOfVolumes (pool);
    virStoragePoolFree(pool);
4056
    if (ret->num == -1) {
4057
        remoteDispatchConnError(rerr, conn);
4058 4059
        return -1;
    }
4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072

    return 0;
}


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



static int
remoteDispatchStorageVolCreateXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4073 4074
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4075
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4076
                                   remote_error *rerr,
4077 4078 4079 4080 4081 4082
                                   remote_storage_vol_create_xml_args *args,
                                   remote_storage_vol_create_xml_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

4083
    pool = get_nonnull_storage_pool (conn, args->pool);
4084
    if (pool == NULL) {
4085
        remoteDispatchConnError(rerr, conn);
4086
        return -1;
4087 4088 4089 4090
    }

    vol = virStorageVolCreateXML (pool, args->xml, args->flags);
    virStoragePoolFree(pool);
4091
    if (vol == NULL) {
4092
        remoteDispatchConnError(rerr, conn);
4093 4094
        return -1;
    }
4095 4096 4097 4098 4099 4100

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

4101 4102 4103 4104
static int
remoteDispatchStorageVolCreateXmlFrom (struct qemud_server *server ATTRIBUTE_UNUSED,
                                       struct qemud_client *client ATTRIBUTE_UNUSED,
                                       virConnectPtr conn,
4105
                                       remote_message_header *hdr ATTRIBUTE_UNUSED,
4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135
                                       remote_error *rerr,
                                       remote_storage_vol_create_xml_from_args *args,
                                       remote_storage_vol_create_xml_from_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr clonevol, newvol;

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

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

    newvol = virStorageVolCreateXMLFrom (pool, args->xml, clonevol,
                                         args->flags);
    if (newvol == NULL) {
        remoteDispatchConnError(rerr, conn);
        return -1;
    }

    make_nonnull_storage_vol (&ret->vol, newvol);
    virStorageVolFree(newvol);
    return 0;
}
4136 4137 4138

static int
remoteDispatchStorageVolDelete (struct qemud_server *server ATTRIBUTE_UNUSED,
4139 4140
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4141
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4142
                                remote_error *rerr,
4143 4144 4145 4146 4147
                                remote_storage_vol_delete_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virStorageVolPtr vol;

4148
    vol = get_nonnull_storage_vol (conn, args->vol);
4149
    if (vol == NULL) {
4150
        remoteDispatchConnError(rerr, conn);
4151
        return -1;
4152 4153 4154 4155
    }

    if (virStorageVolDelete (vol, args->flags) == -1) {
        virStorageVolFree(vol);
4156
        remoteDispatchConnError(rerr, conn);
4157 4158 4159 4160 4161 4162 4163 4164
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}

static int
remoteDispatchStorageVolGetInfo (struct qemud_server *server ATTRIBUTE_UNUSED,
4165 4166
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4167
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4168
                                 remote_error *rerr,
4169 4170 4171 4172 4173 4174
                                 remote_storage_vol_get_info_args *args,
                                 remote_storage_vol_get_info_ret *ret)
{
    virStorageVolPtr vol;
    virStorageVolInfo info;

4175
    vol = get_nonnull_storage_vol (conn, args->vol);
4176
    if (vol == NULL) {
4177
        remoteDispatchConnError(rerr, conn);
4178
        return -1;
4179 4180 4181 4182
    }

    if (virStorageVolGetInfo (vol, &info) == -1) {
        virStorageVolFree(vol);
4183
        remoteDispatchConnError(rerr, conn);
4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197
        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,
4198 4199
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4200
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4201
                                 remote_error *rerr,
4202 4203 4204 4205 4206
                                 remote_storage_vol_dump_xml_args *args,
                                 remote_storage_vol_dump_xml_ret *ret)
{
    virStorageVolPtr vol;

4207
    vol = get_nonnull_storage_vol (conn, args->vol);
4208
    if (vol == NULL) {
4209
        remoteDispatchConnError(rerr, conn);
4210
        return -1;
4211 4212 4213 4214 4215 4216
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virStorageVolGetXMLDesc (vol, args->flags);
    if (!ret->xml) {
        virStorageVolFree(vol);
4217
        remoteDispatchConnError(rerr, conn);
4218 4219 4220 4221 4222 4223 4224 4225 4226
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolGetPath (struct qemud_server *server ATTRIBUTE_UNUSED,
4227 4228
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4229
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4230
                                 remote_error *rerr,
4231 4232 4233 4234 4235
                                 remote_storage_vol_get_path_args *args,
                                 remote_storage_vol_get_path_ret *ret)
{
    virStorageVolPtr vol;

4236
    vol = get_nonnull_storage_vol (conn, args->vol);
4237
    if (vol == NULL) {
4238
        remoteDispatchConnError(rerr, conn);
4239
        return -1;
4240 4241 4242 4243 4244 4245
    }

    /* remoteDispatchClientRequest will free this. */
    ret->name = virStorageVolGetPath (vol);
    if (!ret->name) {
        virStorageVolFree(vol);
4246
        remoteDispatchConnError(rerr, conn);
4247 4248 4249 4250 4251 4252 4253 4254 4255
        return -1;
    }
    virStorageVolFree(vol);
    return 0;
}


static int
remoteDispatchStorageVolLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4256 4257
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4258
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4259
                                      remote_error *rerr,
4260 4261 4262 4263 4264 4265
                                      remote_storage_vol_lookup_by_name_args *args,
                                      remote_storage_vol_lookup_by_name_ret *ret)
{
    virStoragePoolPtr pool;
    virStorageVolPtr vol;

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

    vol = virStorageVolLookupByName (pool, args->name);
    virStoragePoolFree(pool);
4274
    if (vol == NULL) {
4275
        remoteDispatchConnError(rerr, conn);
4276 4277
        return -1;
    }
4278 4279 4280 4281 4282 4283 4284 4285

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

static int
remoteDispatchStorageVolLookupByKey (struct qemud_server *server ATTRIBUTE_UNUSED,
4286 4287
                                     struct qemud_client *client ATTRIBUTE_UNUSED,
                                     virConnectPtr conn,
4288
                                     remote_message_header *hdr ATTRIBUTE_UNUSED,
4289
                                     remote_error *rerr,
4290 4291 4292 4293 4294
                                     remote_storage_vol_lookup_by_key_args *args,
                                     remote_storage_vol_lookup_by_key_ret *ret)
{
    virStorageVolPtr vol;

4295
    vol = virStorageVolLookupByKey (conn, args->key);
4296
    if (vol == NULL) {
4297
        remoteDispatchConnError(rerr, conn);
4298 4299
        return -1;
    }
4300 4301 4302 4303 4304 4305 4306 4307 4308

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


static int
remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUSED,
4309 4310
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4311
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4312
                                      remote_error *rerr,
4313 4314 4315 4316 4317
                                      remote_storage_vol_lookup_by_path_args *args,
                                      remote_storage_vol_lookup_by_path_ret *ret)
{
    virStorageVolPtr vol;

4318
    vol = virStorageVolLookupByPath (conn, args->path);
4319
    if (vol == NULL) {
4320
        remoteDispatchConnError(rerr, conn);
4321 4322
        return -1;
    }
4323 4324 4325 4326 4327 4328 4329

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


4330 4331 4332 4333 4334 4335
/***************************************************************
 *     NODE INFO APIS
 **************************************************************/

static int
remoteDispatchNodeNumOfDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
4336 4337
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4338
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4339
                                remote_error *rerr,
4340 4341 4342 4343 4344
                                remote_node_num_of_devices_args *args,
                                remote_node_num_of_devices_ret *ret)
{
    CHECK_CONN(client);

4345
    ret->num = virNodeNumOfDevices (conn,
4346 4347
                                    args->cap ? *args->cap : NULL,
                                    args->flags);
4348
    if (ret->num == -1) {
4349
        remoteDispatchConnError(rerr, conn);
4350 4351
        return -1;
    }
4352 4353 4354 4355 4356 4357 4358

    return 0;
}


static int
remoteDispatchNodeListDevices (struct qemud_server *server ATTRIBUTE_UNUSED,
4359 4360
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
4361
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
4362
                               remote_error *rerr,
4363 4364 4365 4366 4367 4368
                               remote_node_list_devices_args *args,
                               remote_node_list_devices_ret *ret)
{
    CHECK_CONN(client);

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
4369 4370 4371
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
4372 4373 4374 4375
    }

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

    ret->names.names_len =
4381
        virNodeListDevices (conn,
4382 4383 4384
                            args->cap ? *args->cap : NULL,
                            ret->names.names_val, args->maxnames, args->flags);
    if (ret->names.names_len == -1) {
4385
        remoteDispatchConnError(rerr, conn);
4386 4387 4388 4389 4390 4391 4392 4393 4394 4395
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


static int
remoteDispatchNodeDeviceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED,
4396 4397
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4398
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4399
                                      remote_error *rerr,
4400 4401 4402 4403 4404 4405 4406
                                      remote_node_device_lookup_by_name_args *args,
                                      remote_node_device_lookup_by_name_ret *ret)
{
    virNodeDevicePtr dev;

    CHECK_CONN(client);

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

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


static int
remoteDispatchNodeDeviceDumpXml (struct qemud_server *server ATTRIBUTE_UNUSED,
4421 4422
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4423
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4424
                                 remote_error *rerr,
4425 4426 4427 4428 4429 4430
                                 remote_node_device_dump_xml_args *args,
                                 remote_node_device_dump_xml_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4431
    dev = virNodeDeviceLookupByName(conn, args->name);
4432
    if (dev == NULL) {
4433 4434
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4435 4436 4437 4438 4439
    }

    /* remoteDispatchClientRequest will free this. */
    ret->xml = virNodeDeviceGetXMLDesc (dev, args->flags);
    if (!ret->xml) {
4440
        remoteDispatchConnError(rerr, conn);
4441 4442 4443 4444 4445 4446 4447 4448 4449 4450
        virNodeDeviceFree(dev);
        return -1;
    }
    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceGetParent (struct qemud_server *server ATTRIBUTE_UNUSED,
4451 4452
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4453
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4454
                                   remote_error *rerr,
4455 4456 4457 4458 4459 4460 4461
                                   remote_node_device_get_parent_args *args,
                                   remote_node_device_get_parent_ret *ret)
{
    virNodeDevicePtr dev;
    const char *parent;
    CHECK_CONN(client);

4462
    dev = virNodeDeviceLookupByName(conn, args->name);
4463
    if (dev == NULL) {
4464 4465
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4466 4467 4468 4469 4470 4471 4472 4473 4474 4475
    }

    parent = virNodeDeviceGetParent(dev);

    if (parent == NULL) {
        ret->parent = NULL;
    } else {
        /* remoteDispatchClientRequest will free this. */
        char **parent_p;
        if (VIR_ALLOC(parent_p) < 0) {
4476 4477
            remoteDispatchOOMError(rerr);
            return -1;
4478 4479 4480
        }
        *parent_p = strdup(parent);
        if (*parent_p == NULL) {
4481 4482
            remoteDispatchOOMError(rerr);
            return -1;
4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493
        }
        ret->parent = parent_p;
    }

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceNumOfCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4494 4495
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
                                   virConnectPtr conn,
4496
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
4497
                                   remote_error *rerr,
4498 4499 4500 4501 4502 4503
                                   remote_node_device_num_of_caps_args *args,
                                   remote_node_device_num_of_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4504
    dev = virNodeDeviceLookupByName(conn, args->name);
4505
    if (dev == NULL) {
4506 4507
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4508 4509 4510
    }

    ret->num = virNodeDeviceNumOfCaps(dev);
4511
    if (ret->num < 0) {
4512
        remoteDispatchConnError(rerr, conn);
4513 4514
        return -1;
    }
4515 4516 4517 4518 4519 4520 4521 4522

    virNodeDeviceFree(dev);
    return 0;
}


static int
remoteDispatchNodeDeviceListCaps (struct qemud_server *server ATTRIBUTE_UNUSED,
4523 4524
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4525
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4526
                                  remote_error *rerr,
4527 4528 4529 4530 4531 4532
                                  remote_node_device_list_caps_args *args,
                                  remote_node_device_list_caps_ret *ret)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

4533
    dev = virNodeDeviceLookupByName(conn, args->name);
4534
    if (dev == NULL) {
4535 4536
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
4537 4538 4539
    }

    if (args->maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
4540 4541 4542
        remoteDispatchFormatError(rerr,
                                  "%s", _("maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX"));
        return -1;
4543 4544 4545 4546
    }

    /* Allocate return buffer. */
    if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) {
4547 4548
        remoteDispatchOOMError(rerr);
        return -1;
4549 4550 4551 4552 4553 4554
    }

    ret->names.names_len =
        virNodeDeviceListCaps (dev, ret->names.names_val,
                               args->maxnames);
    if (ret->names.names_len == -1) {
4555
        remoteDispatchConnError(rerr, conn);
4556 4557 4558 4559 4560 4561 4562 4563
        VIR_FREE(ret->names.names_val);
        return -1;
    }

    return 0;
}


4564 4565 4566 4567
static int
remoteDispatchNodeDeviceDettach (struct qemud_server *server ATTRIBUTE_UNUSED,
                                 struct qemud_client *client ATTRIBUTE_UNUSED,
                                 virConnectPtr conn,
4568
                                 remote_message_header *hdr ATTRIBUTE_UNUSED,
4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594
                                 remote_error *rerr,
                                 remote_node_device_dettach_args *args,
                                 void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
    }

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

    return 0;
}


static int
remoteDispatchNodeDeviceReAttach (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4595
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621
                                  remote_error *rerr,
                                  remote_node_device_re_attach_args *args,
                                  void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
    }

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

    return 0;
}


static int
remoteDispatchNodeDeviceReset (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
                               virConnectPtr conn,
4622
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644
                               remote_error *rerr,
                               remote_node_device_reset_args *args,
                               void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;
    CHECK_CONN(client);

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
    }

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

    return 0;
}


4645 4646 4647 4648
static int
remoteDispatchNodeDeviceCreateXml(struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
                                  virConnectPtr conn,
4649
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672
                                  remote_error *rerr,
                                  remote_node_device_create_xml_args *args,
                                  remote_node_device_create_xml_ret *ret)
{
    virNodeDevicePtr dev;

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

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

    return 0;
}


static int
remoteDispatchNodeDeviceDestroy(struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
                                virConnectPtr conn,
4673
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694
                                remote_error *rerr,
                                remote_node_device_destroy_args *args,
                                void *ret ATTRIBUTE_UNUSED)
{
    virNodeDevicePtr dev;

    dev = virNodeDeviceLookupByName(conn, args->name);
    if (dev == NULL) {
        remoteDispatchFormatError(rerr, "%s", _("node_device not found"));
        return -1;
    }

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

    return 0;
}


4695 4696 4697 4698 4699 4700

/***************************
 * Register / deregister events
 ***************************/
static int
remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED,
4701 4702
                                    struct qemud_client *client ATTRIBUTE_UNUSED,
                                    virConnectPtr conn,
4703
                                    remote_message_header *hdr ATTRIBUTE_UNUSED,
4704
                                    remote_error *rerr ATTRIBUTE_UNUSED,
4705 4706 4707 4708 4709 4710 4711
                                    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");
4712
    virConnectDomainEventRegister(conn, remoteRelayDomainEvent, client, NULL);
4713 4714 4715 4716 4717 4718 4719 4720

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

static int
remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED,
4721 4722
                                      struct qemud_client *client ATTRIBUTE_UNUSED,
                                      virConnectPtr conn,
4723
                                      remote_message_header *hdr ATTRIBUTE_UNUSED,
4724
                                      remote_error *rerr ATTRIBUTE_UNUSED,
4725 4726 4727 4728 4729 4730 4731
                                      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");
4732
    virConnectDomainEventDeregister(conn, remoteRelayDomainEvent);
4733 4734 4735 4736 4737 4738 4739 4740

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

static void
remoteDispatchDomainEventSend (struct qemud_client *client,
4741
                               remote_domain_event_msg *data)
4742
{
4743
    struct qemud_client_message *msg = NULL;
4744
    XDR xdr;
4745
    unsigned int len;
4746

4747
    if (VIR_ALLOC(msg) < 0)
4748 4749
        return;

4750 4751 4752
    msg->hdr.prog = REMOTE_PROGRAM;
    msg->hdr.vers = REMOTE_PROTOCOL_VERSION;
    msg->hdr.proc = REMOTE_PROC_DOMAIN_EVENT;
4753
    msg->hdr.type = REMOTE_MESSAGE;
4754 4755
    msg->hdr.serial = 1;
    msg->hdr.status = REMOTE_OK;
4756

4757 4758
    if (remoteEncodeClientMessageHeader(msg) < 0)
        goto error;
4759

4760 4761
    /* Serialise the return header and event. */
    xdrmem_create (&xdr,
4762 4763
                   msg->buffer,
                   msg->bufferLength,
4764
                   XDR_ENCODE);
4765

4766 4767
    /* Skip over the header we just wrote */
    if (xdr_setpos (&xdr, msg->bufferOffset) == 0)
4768
        goto xdr_error;
4769

4770 4771
    if (!xdr_remote_domain_event_msg(&xdr, data))
        goto xdr_error;
4772

4773 4774
    /* Update length word to include payload*/
    len = msg->bufferOffset = xdr_getpos (&xdr);
4775 4776
    if (xdr_setpos (&xdr, 0) == 0)
        goto xdr_error;
4777

4778 4779
    if (!xdr_u_int (&xdr, &len))
        goto xdr_error;
4780 4781

    /* Send it. */
4782 4783 4784 4785
    msg->async = 1;
    msg->bufferLength = len;
    msg->bufferOffset = 0;
    qemudClientMessageQueuePush(&client->tx, msg);
4786
    qemudUpdateClientEvent(client);
4787 4788 4789 4790 4791 4792 4793 4794

    xdr_destroy (&xdr);
    return;

xdr_error:
    xdr_destroy(&xdr);
error:
    VIR_FREE(msg);
4795
}
4796

4797 4798 4799
static int
remoteDispatchNumOfSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
                            struct qemud_client *client ATTRIBUTE_UNUSED,
4800 4801 4802
                            virConnectPtr conn,
                            remote_message_header *hdr ATTRIBUTE_UNUSED,
                            remote_error *err,
4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817
                            void *args ATTRIBUTE_UNUSED,
                            remote_num_of_secrets_ret *ret)
{
    ret->num = virConnectNumOfSecrets (conn);
    if (ret->num == -1) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

    return 0;
}

static int
remoteDispatchListSecrets (struct qemud_server *server ATTRIBUTE_UNUSED,
                           struct qemud_client *client ATTRIBUTE_UNUSED,
4818 4819 4820
                           virConnectPtr conn,
                           remote_message_header *hdr ATTRIBUTE_UNUSED,
                           remote_error *err,
4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848
                           remote_list_secrets_args *args,
                           remote_list_secrets_ret *ret)
{
    if (args->maxuuids > REMOTE_SECRET_UUID_LIST_MAX) {
        remoteDispatchFormatError (err, "%s",
                                   _("maxuuids > REMOTE_SECRET_UUID_LIST_MAX"));
        return -1;
    }

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

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

    return 0;
}

static int
remoteDispatchSecretDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED,
                               struct qemud_client *client ATTRIBUTE_UNUSED,
4849 4850 4851
                               virConnectPtr conn,
                               remote_message_header *hdr ATTRIBUTE_UNUSED,
                               remote_error *err,
4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870
                               remote_secret_define_xml_args *args,
                               remote_secret_define_xml_ret *ret)
{
    virSecretPtr secret;

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

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

static int
remoteDispatchSecretGetValue (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
4871 4872 4873
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902
                              remote_secret_get_value_args *args,
                              remote_secret_get_value_ret *ret)
{
    virSecretPtr secret;
    size_t value_size;
    unsigned char *value;

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

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

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

static int
remoteDispatchSecretGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED,
                                struct qemud_client *client ATTRIBUTE_UNUSED,
4903 4904 4905
                                virConnectPtr conn,
                                remote_message_header *hdr ATTRIBUTE_UNUSED,
                                remote_error *err,
4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926
                                remote_secret_get_xml_desc_args *args,
                                remote_secret_get_xml_desc_ret *ret)
{
    virSecretPtr secret;

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

static int
4927 4928
remoteDispatchSecretLookupByUuid (struct qemud_server *server ATTRIBUTE_UNUSED,
                                  struct qemud_client *client ATTRIBUTE_UNUSED,
4929 4930 4931
                                  virConnectPtr conn,
                                  remote_message_header *hdr ATTRIBUTE_UNUSED,
                                  remote_error *err,
4932 4933
                                  remote_secret_lookup_by_uuid_args *args,
                                  remote_secret_lookup_by_uuid_ret *ret)
4934 4935 4936
{
    virSecretPtr secret;

4937
    secret = virSecretLookupByUUID (conn, (unsigned char *)args->uuid);
4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950
    if (secret == NULL) {
        remoteDispatchConnError (err, conn);
        return -1;
    }

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

static int
remoteDispatchSecretSetValue (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
4951 4952 4953
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977
                              remote_secret_set_value_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virSecretPtr secret;

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

    virSecretFree(secret);
    return 0;
}

static int
remoteDispatchSecretUndefine (struct qemud_server *server ATTRIBUTE_UNUSED,
                              struct qemud_client *client ATTRIBUTE_UNUSED,
4978 4979 4980
                              virConnectPtr conn,
                              remote_message_header *hdr ATTRIBUTE_UNUSED,
                              remote_error *err,
4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000
                              remote_secret_undefine_args *args,
                              void *ret ATTRIBUTE_UNUSED)
{
    virSecretPtr secret;

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

    virSecretFree(secret);
    return 0;
}

5001 5002 5003
static int
remoteDispatchSecretLookupByUsage (struct qemud_server *server ATTRIBUTE_UNUSED,
                                   struct qemud_client *client ATTRIBUTE_UNUSED,
5004 5005 5006
                                   virConnectPtr conn,
                                   remote_message_header *hdr ATTRIBUTE_UNUSED,
                                   remote_error *err,
5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022
                                   remote_secret_lookup_by_usage_args *args,
                                   remote_secret_lookup_by_usage_ret *ret)
{
    virSecretPtr secret;

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

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

5023

5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225
static int remoteDispatchDomainIsActive(struct qemud_server *server ATTRIBUTE_UNUSED,
                                        struct qemud_client *client ATTRIBUTE_UNUSED,
                                        virConnectPtr conn,
                                        remote_message_header *hdr ATTRIBUTE_UNUSED,
                                        remote_error *err,
                                        remote_domain_is_active_args *args,
                                        remote_domain_is_active_ret *ret)
{
    virDomainPtr domain;

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

    ret->active = virDomainIsActive(domain);

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

    return 0;
}

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

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

    ret->persistent = virDomainIsPersistent(domain);

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

    return 0;
}

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

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

    ret->active = virInterfaceIsActive(iface);

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

    return 0;
}

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

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

    ret->active = virNetworkIsActive(network);

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

    return 0;
}

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

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

    ret->persistent = virNetworkIsPersistent(network);

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

    return 0;
}

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

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

    ret->active = virStoragePoolIsActive(pool);

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

    return 0;
}

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

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

    ret->persistent = virStoragePoolIsPersistent(pool);

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

    return 0;
}


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

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

    return 0;
}


5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251
/*----- Helpers. -----*/

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

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

D
Daniel Veillard 已提交
5252
static virInterfacePtr
5253
get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface)
D
Daniel Veillard 已提交
5254
{
5255
    return virGetInterface (conn, iface.name, iface.mac);
D
Daniel Veillard 已提交
5256 5257
}

5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271
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;
}

5272 5273 5274
static virSecretPtr
get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret)
{
5275
    return virGetSecret (conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
5276 5277
}

5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293
/* Make remote_nonnull_domain and remote_nonnull_network. */
static void
make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
{
    dom_dst->id = dom_src->id;
    dom_dst->name = strdup (dom_src->name);
    memcpy (dom_dst->uuid, dom_src->uuid, VIR_UUID_BUFLEN);
}

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

D
Daniel Veillard 已提交
5294 5295 5296 5297 5298 5299 5300 5301
static void
make_nonnull_interface (remote_nonnull_interface *interface_dst,
                        virInterfacePtr interface_src)
{
    interface_dst->name = strdup (interface_src->name);
    interface_dst->mac = strdup (interface_src->mac);
}

5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315
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);
}
5316 5317 5318 5319 5320 5321

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

static void
make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
{
5326
    memcpy (secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
5327 5328
    secret_dst->usageType = secret_src->usageType;
    secret_dst->usageID = strdup (secret_src->usageID);
5329
}