remote_driver.c 318.8 KB
Newer Older
1 2 3 4
/*
 * remote_internal.c: driver to provide access to libvirtd running
 *   on a remote machine
 *
5
 * Copyright (C) 2007-2010 Red Hat, Inc.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * 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 Jones <rjones@redhat.com>
 */

24
#include <config.h>
25

26 27 28
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
29
#include <string.h>
30 31 32
#include <assert.h>
#include <signal.h>
#include <sys/types.h>
33 34
#include <sys/stat.h>
#include <fcntl.h>
35
#include <arpa/inet.h>
E
Eric Blake 已提交
36
#include <sys/wait.h>
37

38 39 40 41 42
/* Windows socket compatibility functions. */
#include <errno.h>
#include <sys/socket.h>

#ifndef HAVE_WINSOCK2_H /* Unix & Cygwin. */
43 44 45 46 47 48
# include <sys/un.h>
# include <net/if.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
#endif

49
#ifdef HAVE_PWD_H
50
# include <pwd.h>
51 52 53
#endif

#ifdef HAVE_PATHS_H
54
# include <paths.h>
55 56
#endif

57
#include <rpc/types.h>
58 59 60
#include <rpc/xdr.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
61
#include "gnutls_1_0_compat.h"
62
#if HAVE_SASL
63
# include <sasl/sasl.h>
64
#endif
65 66
#include <libxml/uri.h>

J
Jim Meyering 已提交
67
#include <netdb.h>
68

69 70
#include <poll.h>

71
#include "virterror_internal.h"
72
#include "logging.h"
73
#include "datatypes.h"
74
#include "domain_event.h"
75
#include "driver.h"
76 77
#include "buf.h"
#include "qparams.h"
78
#include "remote_driver.h"
79
#include "remote_protocol.h"
C
Chris Lalancette 已提交
80
#include "qemu_protocol.h"
81
#include "memory.h"
82
#include "util.h"
83
#include "event.h"
84
#include "ignore-value.h"
85
#include "files.h"
86

87 88
#define VIR_FROM_THIS VIR_FROM_REMOTE

89
#ifdef WIN32
90
# define pipe(fds) _pipe(fds,4096, _O_BINARY)
91 92 93
#endif


94 95
static int inside_daemon = 0;

96 97 98 99 100 101 102 103 104 105 106 107 108
struct remote_thread_call;


enum {
    REMOTE_MODE_WAIT_TX,
    REMOTE_MODE_WAIT_RX,
    REMOTE_MODE_COMPLETE,
    REMOTE_MODE_ERROR,
};

struct remote_thread_call {
    int mode;

109 110
    /* Buffer for outgoing data packet
     * 4 byte length, followed by RPC message header+body */
111 112 113 114 115 116 117 118 119
    char buffer[4 + REMOTE_MESSAGE_MAX];
    unsigned int bufferLength;
    unsigned int bufferOffset;

    unsigned int serial;
    unsigned int proc_nr;

    virCond cond;

120
    int want_reply;
121 122 123 124 125 126 127 128
    xdrproc_t ret_filter;
    char *ret;

    remote_error err;

    struct remote_thread_call *next;
};

129 130 131 132 133 134 135
struct private_stream_data {
    unsigned int has_error : 1;
    remote_error err;

    unsigned int serial;
    unsigned int proc_nr;

136 137 138 139 140 141 142
    virStreamEventCallback cb;
    void *cbOpaque;
    virFreeCallback cbFree;
    int cbEvents;
    int cbTimer;
    int cbDispatch;

143 144 145 146 147 148 149 150 151 152 153 154 155
    /* XXX this is potentially unbounded if the client
     * app has domain events registered, since packets
     * may be read off wire, while app isn't ready to
     * recv them. Figure out how to address this some
     * time....
     */
    char *incoming;
    unsigned int incomingOffset;
    unsigned int incomingLength;

    struct private_stream_data *next;
};

156
struct private_data {
157 158
    virMutex lock;

159
    int sock;                   /* Socket. */
160
    int errfd;                /* File handle connected to remote stderr */
161
    int watch;                  /* File handle watch */
162
    pid_t pid;                  /* PID of tunnel process */
163
    int uses_tls;               /* TLS enabled on socket? */
164
    int is_secure;              /* Secure if TLS or SASL or UNIX sockets */
165 166 167
    gnutls_session_t session;   /* GnuTLS session (if uses_tls != 0). */
    char *type;                 /* Cached return from remoteType. */
    int counter;                /* Generates serial numbers for RPC. */
168
    int localUses;              /* Ref count for private data */
169 170
    char *hostname;             /* Original hostname */
    FILE *debugLog;             /* Debug remote protocol */
171

172 173
#if HAVE_SASL
    sasl_conn_t *saslconn;      /* SASL context */
174

175 176 177
    const char *saslDecoded;
    unsigned int saslDecodedLength;
    unsigned int saslDecodedOffset;
178 179 180 181

    const char *saslEncoded;
    unsigned int saslEncodedLength;
    unsigned int saslEncodedOffset;
182
#endif
183

184 185
    /* Buffer for incoming data packets
     * 4 byte length, followed by RPC message header+body */
186 187 188 189
    char buffer[4 + REMOTE_MESSAGE_MAX];
    unsigned int bufferLength;
    unsigned int bufferOffset;

190 191 192 193 194 195 196
    /* The list of domain event callbacks */
    virDomainEventCallbackListPtr callbackList;
    /* The queue of domain events generated
       during a call / response rpc          */
    virDomainEventQueuePtr domainEvents;
    /* Timer for flushing domainEvents queue */
    int eventFlushTimer;
197 198
    /* Flag if we're in process of dispatching */
    int domainEventDispatching;
199 200 201 202 203 204 205

    /* Self-pipe to wakeup threads waiting in poll() */
    int wakeupSendFD;
    int wakeupReadFD;

    /* List of threads currently waiting for dispatch */
    struct remote_thread_call *waitDispatch;
206 207

    struct private_stream_data *streams;
208 209
};

210
enum {
211
    REMOTE_CALL_IN_OPEN           = (1 << 0),
C
Chris Lalancette 已提交
212
    REMOTE_CALL_QUIET_MISSING_RPC = (1 << 1),
213 214
    REMOTE_CALL_QEMU              = (1 << 2),
    REMOTE_CALL_NONBLOCK          = (1 << 3),
215 216 217
};


218 219 220 221 222 223 224 225 226 227
static void remoteDriverLock(struct private_data *driver)
{
    virMutexLock(&driver->lock);
}

static void remoteDriverUnlock(struct private_data *driver)
{
    virMutexUnlock(&driver->lock);
}

228 229 230 231
static int remoteIO(virConnectPtr conn,
                    struct private_data *priv,
                    int flags,
                    struct remote_thread_call *thiscall);
232 233 234 235
static int call (virConnectPtr conn, struct private_data *priv,
                 int flags, int proc_nr,
                 xdrproc_t args_filter, char *args,
                 xdrproc_t ret_filter, char *ret);
236 237
static int remoteAuthenticate (virConnectPtr conn, struct private_data *priv, int in_open,
                               virConnectAuthPtr auth, const char *authtype);
238
#if HAVE_SASL
239 240
static int remoteAuthSASL (virConnectPtr conn, struct private_data *priv, int in_open,
                           virConnectAuthPtr auth, const char *mech);
241
#endif
242
#if HAVE_POLKIT
243 244
static int remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
                             virConnectAuthPtr auth);
245
#endif /* HAVE_POLKIT */
246 247 248

#define remoteError(code, ...)                                    \
    virReportErrorHelper(NULL, VIR_FROM_REMOTE, code, __FILE__,   \
249
                         __FUNCTION__, __LINE__, __VA_ARGS__)
250

251 252
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
253
static virNWFilterPtr get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter);
254
static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface);
255 256
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);
257
static virNodeDevicePtr get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev);
258
static virSecretPtr get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret);
C
Chris Lalancette 已提交
259
static virDomainSnapshotPtr get_nonnull_domain_snapshot (virDomainPtr domain, remote_nonnull_domain_snapshot snapshot);
260 261
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 已提交
262
static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
263 264
static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src);
static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
265
static void make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
266
static void make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src);
C
Chris Lalancette 已提交
267
static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
268
void remoteDomainEventFired(int watch, int fd, int event, void *data);
269
void remoteDomainEventQueueFlush(int timer, void *opaque);
270 271 272 273 274 275
/*----------------------------------------------------------------------*/

/* Helper functions for remoteOpen. */
static char *get_transport_from_scheme (char *scheme);

/* GnuTLS functions used by remoteOpen. */
276
static int initialize_gnutls(void);
277
static gnutls_session_t negotiate_gnutls_on_connection (virConnectPtr conn, struct private_data *priv, int no_verify);
278

A
Atsushi SAKAI 已提交
279
#ifdef WITH_LIBVIRTD
280
static int
281
remoteStartup(int privileged ATTRIBUTE_UNUSED)
282 283 284 285 286 287 288
{
    /* Mark that we're inside the daemon so we can avoid
     * re-entering ourselves
     */
    inside_daemon = 1;
    return 0;
}
A
Atsushi SAKAI 已提交
289
#endif
290

291
#ifndef WIN32
292 293 294 295
/**
 * remoteFindServerPath:
 *
 * Tries to find the path to the libvirtd binary.
296
 *
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
 * Returns path on success or NULL in case of error.
 */
static const char *
remoteFindDaemonPath(void)
{
    static const char *serverPaths[] = {
        SBINDIR "/libvirtd",
        SBINDIR "/libvirtd_dbg",
        NULL
    };
    int i;
    const char *customDaemon = getenv("LIBVIRTD_PATH");

    if (customDaemon)
        return(customDaemon);

    for (i = 0; serverPaths[i]; i++) {
        if (access(serverPaths[i], X_OK | R_OK) == 0) {
            return serverPaths[i];
        }
    }
    return NULL;
}

/**
 * qemuForkDaemon:
 *
 * Forks and try to launch the libvirtd daemon
 *
 * Returns 0 in case of success or -1 in case of detected error.
 */
328
static int
329
remoteForkDaemon(void)
330 331
{
    const char *daemonPath = remoteFindDaemonPath();
332
    const char *const daemonargs[] = { daemonPath, "--timeout=30", NULL };
333
    pid_t pid;
334 335

    if (!daemonPath) {
336 337
        remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("failed to find libvirtd binary"));
338
        return -1;
339 340
    }

341
    if (virExecDaemonize(daemonargs, NULL, NULL,
342 343
                         &pid, -1, NULL, NULL,
                         VIR_EXEC_CLEAR_CAPS,
344
                         NULL, NULL, NULL) < 0)
345
        return -1;
346

347
    return 0;
348
}
349
#endif
350

351
enum virDrvOpenRemoteFlags {
352
    VIR_DRV_OPEN_REMOTE_RO = (1 << 0),
353 354
    VIR_DRV_OPEN_REMOTE_USER      = (1 << 1), /* Use the per-user socket path */
    VIR_DRV_OPEN_REMOTE_AUTOSTART = (1 << 2), /* Autostart a per-user daemon */
355
};
356

357

358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
/*
 * URIs that this driver needs to handle:
 *
 * The easy answer:
 *   - Everything that no one else has yet claimed, but nothing if
 *     we're inside the libvirtd daemon
 *
 * The hard answer:
 *   - Plain paths (///var/lib/xen/xend-socket)  -> UNIX domain socket
 *   - xxx://servername/      -> TLS connection
 *   - xxx+tls://servername/  -> TLS connection
 *   - xxx+tls:///            -> TLS connection to localhost
 *   - xxx+tcp://servername/  -> TCP connection
 *   - xxx+tcp:///            -> TCP connection to localhost
 *   - xxx+unix:///           -> UNIX domain socket
 *   - xxx:///                -> UNIX domain socket
 */
375
static int
376 377 378 379
doRemoteOpen (virConnectPtr conn,
              struct private_data *priv,
              virConnectAuthPtr auth ATTRIBUTE_UNUSED,
              int flags)
380
{
381
    struct qparam_set *vars = NULL;
382
    int wakeupFD[2] = { -1, -1 };
383
    char *transport_str = NULL;
384 385 386 387 388 389 390
    enum {
        trans_tls,
        trans_unix,
        trans_ssh,
        trans_ext,
        trans_tcp,
    } transport;
391

392 393
    /* We handle *ALL*  URIs here. The caller has rejected any
     * URIs we don't care about */
394

395 396 397
    if (conn->uri) {
        if (!conn->uri->scheme) {
            /* This is the ///var/lib/xen/xend-socket local path style */
398
            transport = trans_unix;
399 400
        } else {
            transport_str = get_transport_from_scheme (conn->uri->scheme);
401

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
            if (!transport_str) {
                if (conn->uri->server)
                    transport = trans_tls;
                else
                    transport = trans_unix;
            } else {
                if (STRCASEEQ (transport_str, "tls"))
                    transport = trans_tls;
                else if (STRCASEEQ (transport_str, "unix"))
                    transport = trans_unix;
                else if (STRCASEEQ (transport_str, "ssh"))
                    transport = trans_ssh;
                else if (STRCASEEQ (transport_str, "ext"))
                    transport = trans_ext;
                else if (STRCASEEQ (transport_str, "tcp"))
                    transport = trans_tcp;
                else {
419 420 421
                    remoteError(VIR_ERR_INVALID_ARG, "%s",
                                _("remote_open: transport in URL not recognised "
                                  "(should be tls|unix|ssh|ext|tcp)"));
422 423 424 425 426 427 428
                    return VIR_DRV_OPEN_ERROR;
                }
            }
        }
    } else {
        /* No URI, then must be probing so use UNIX socket */
        transport = trans_unix;
429
    }
430

E
Eric Blake 已提交
431
    /* Local variables which we will initialize. These can
432 433
     * get freed in the failed: path.
     */
434 435
    char *name = NULL, *command = NULL, *sockname = NULL, *netcat = NULL;
    char *port = NULL, *authtype = NULL, *username = NULL;
436
    int no_verify = 0, no_tty = 0;
437
    char **cmd_argv = NULL;
438

439 440 441
    /* Return code from this function, and the private data. */
    int retcode = VIR_DRV_OPEN_ERROR;

442
    /* Remote server defaults to "localhost" if not specified. */
443
    if (conn->uri && conn->uri->port != 0) {
444
        if (virAsprintf(&port, "%d", conn->uri->port) == -1) goto out_of_memory;
445 446 447 448 449 450 451
    } else if (transport == trans_tls) {
        port = strdup (LIBVIRTD_TLS_PORT);
        if (!port) goto out_of_memory;
    } else if (transport == trans_tcp) {
        port = strdup (LIBVIRTD_TCP_PORT);
        if (!port) goto out_of_memory;
    } else
452
        port = NULL; /* Port not used for unix, ext., default for ssh */
453

454

455 456
    priv->hostname = strdup (conn->uri && conn->uri->server ?
                             conn->uri->server : "localhost");
457 458
    if (!priv->hostname)
        goto out_of_memory;
459 460
    if (conn->uri && conn->uri->user) {
        username = strdup (conn->uri->user);
461 462
        if (!username)
            goto out_of_memory;
463 464
    }

465 466 467 468 469
    /* Get the variables from the query string.
     * Then we need to reconstruct the query string (because
     * feasibly it might contain variables needed by the real driver,
     * although that won't be the case for now).
     */
470 471
    struct qparam *var;
    int i;
472 473
    char *query;

474
    if (conn->uri) {
475
#ifdef HAVE_XMLURI_QUERY_RAW
476
        query = conn->uri->query_raw;
477
#else
478
        query = conn->uri->query;
479
#endif
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
        vars = qparam_query_parse (query);
        if (vars == NULL) goto failed;

        for (i = 0; i < vars->n; i++) {
            var = &vars->p[i];
            if (STRCASEEQ (var->name, "name")) {
                name = strdup (var->value);
                if (!name) goto out_of_memory;
                var->ignore = 1;
            } else if (STRCASEEQ (var->name, "command")) {
                command = strdup (var->value);
                if (!command) goto out_of_memory;
                var->ignore = 1;
            } else if (STRCASEEQ (var->name, "socket")) {
                sockname = strdup (var->value);
                if (!sockname) goto out_of_memory;
                var->ignore = 1;
            } else if (STRCASEEQ (var->name, "auth")) {
                authtype = strdup (var->value);
                if (!authtype) goto out_of_memory;
                var->ignore = 1;
            } else if (STRCASEEQ (var->name, "netcat")) {
                netcat = strdup (var->value);
                if (!netcat) goto out_of_memory;
                var->ignore = 1;
            } else if (STRCASEEQ (var->name, "no_verify")) {
                no_verify = atoi (var->value);
                var->ignore = 1;
            } else if (STRCASEEQ (var->name, "no_tty")) {
                no_tty = atoi (var->value);
                var->ignore = 1;
            } else if (STRCASEEQ (var->name, "debug")) {
                if (var->value &&
                    STRCASEEQ (var->value, "stdout"))
                    priv->debugLog = stdout;
                else
                    priv->debugLog = stderr;
            } else
                DEBUG("passing through variable '%s' ('%s') to remote end",
                      var->name, var->value);
        }
521

522 523
        /* Construct the original name. */
        if (!name) {
524 525 526
            if (conn->uri->scheme &&
                (STREQ(conn->uri->scheme, "remote") ||
                 STRPREFIX(conn->uri->scheme, "remote+"))) {
527 528 529 530 531
                /* Allow remote serve to probe */
                name = strdup("");
            } else {
                xmlURI tmpuri = {
                    .scheme = conn->uri->scheme,
532
#ifdef HAVE_XMLURI_QUERY_RAW
533
                    .query_raw = qparam_get_query (vars),
534
#else
535
                    .query = qparam_get_query (vars),
536
#endif
537 538 539 540 541 542 543 544 545
                    .path = conn->uri->path,
                    .fragment = conn->uri->fragment,
                };

                /* Evil, blank out transport scheme temporarily */
                if (transport_str) {
                    assert (transport_str[-1] == '+');
                    transport_str[-1] = '\0';
                }
546

547
                name = (char *) xmlSaveUri (&tmpuri);
548

549 550 551 552 553 554 555 556 557 558
#ifdef HAVE_XMLURI_QUERY_RAW
                VIR_FREE(tmpuri.query_raw);
#else
                VIR_FREE(tmpuri.query);
#endif

                /* Restore transport scheme */
                if (transport_str)
                    transport_str[-1] = '+';
            }
559 560
        }

561
        free_qparam_set (vars);
562
        vars = NULL;
563 564 565 566
    } else {
        /* Probe URI server side */
        name = strdup("");
    }
567

568
    if (!name) {
569
        virReportOOMError();
570
        goto failed;
571 572
    }

573
    DEBUG("proceeding with name = %s", name);
574

575 576
    /* For ext transport, command is required. */
    if (transport == trans_ext && !command) {
577 578
        remoteError(VIR_ERR_INVALID_ARG, "%s",
                    _("remote_open: for 'ext' transport, command is required"));
579 580 581
        goto failed;
    }

582 583 584
    /* Connect to the remote service. */
    switch (transport) {
    case trans_tls:
585
        if (initialize_gnutls() == -1) goto failed;
586
        priv->uses_tls = 1;
587
        priv->is_secure = 1;
588 589 590 591 592 593

        /*FALLTHROUGH*/
    case trans_tcp: {
        // http://people.redhat.com/drepper/userapi-ipv6.html
        struct addrinfo *res, *r;
        struct addrinfo hints;
594
        int saved_errno = EINVAL;
595 596 597
        memset (&hints, 0, sizeof hints);
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_ADDRCONFIG;
598
        int e = getaddrinfo (priv->hostname, port, &hints, &res);
599
        if (e != 0) {
600 601 602
            remoteError(VIR_ERR_SYSTEM_ERROR,
                        _("unable to resolve hostname '%s': %s"),
                        priv->hostname, gai_strerror (e));
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
            goto failed;
        }

        /* Try to connect to each returned address in turn. */
        /* XXX This loop contains a subtle problem.  In the case
         * where a host is accessible over IPv4 and IPv6, it will
         * try the IPv4 and IPv6 addresses in turn.  However it
         * should be able to present different client certificates
         * (because the commonName field in a client cert contains
         * the client IP address, which is different for IPv4 and
         * IPv6).  At the moment we only have a single client
         * certificate, and no way to specify what address family
         * that certificate belongs to.
         */
        for (r = res; r; r = r->ai_next) {
            int no_slow_start = 1;

620 621
            priv->sock = socket (r->ai_family, SOCK_STREAM, 0);
            if (priv->sock == -1) {
J
Jim Meyering 已提交
622
                saved_errno = errno;
623 624 625 626
                continue;
            }

            /* Disable Nagle - Dan Berrange. */
627
            setsockopt (priv->sock,
628 629 630
                        IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
                        sizeof no_slow_start);

631
            if (connect (priv->sock, r->ai_addr, r->ai_addrlen) == -1) {
J
Jim Meyering 已提交
632
                saved_errno = errno;
633
                VIR_FORCE_CLOSE(priv->sock);
634 635 636
                continue;
            }

637 638
            if (priv->uses_tls) {
                priv->session =
639
                    negotiate_gnutls_on_connection
640
                      (conn, priv, no_verify);
641
                if (!priv->session) {
642
                    VIR_FORCE_CLOSE(priv->sock);
643
                    goto failed;
644 645 646 647 648 649
                }
            }
            goto tcp_connected;
        }

        freeaddrinfo (res);
650
        virReportSystemError(saved_errno,
651
                             _("unable to connect to libvirtd at '%s'"),
652
                             priv->hostname);
653 654 655 656 657 658 659 660 661 662
        goto failed;

       tcp_connected:
        freeaddrinfo (res);

        // NB. All versioning is done by the RPC headers, so we don't
        // need to worry (at this point anyway) about versioning.
        break;
    }

663
#ifndef WIN32
664 665
    case trans_unix: {
        if (!sockname) {
666
            if (flags & VIR_DRV_OPEN_REMOTE_USER) {
667
                char *userdir = virGetUserDirectory(getuid());
668

669
                if (!userdir)
670
                    goto failed;
671

672 673
                if (virAsprintf(&sockname, "@%s" LIBVIRTD_USER_UNIX_SOCKET, userdir) < 0) {
                    VIR_FREE(userdir);
674
                    goto out_of_memory;
675 676
                }
                VIR_FREE(userdir);
677
            } else {
678
                if (flags & VIR_DRV_OPEN_REMOTE_RO)
679 680 681
                    sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET_RO);
                else
                    sockname = strdup (LIBVIRTD_PRIV_UNIX_SOCKET);
682 683
                if (sockname == NULL)
                    goto out_of_memory;
684
            }
685 686
        }

687 688 689
# ifndef UNIX_PATH_MAX
#  define UNIX_PATH_MAX(addr) (sizeof (addr).sun_path)
# endif
690
        struct sockaddr_un addr;
691 692
        int trials = 0;

693 694
        memset (&addr, 0, sizeof addr);
        addr.sun_family = AF_UNIX;
C
Chris Lalancette 已提交
695
        if (virStrcpyStatic(addr.sun_path, sockname) == NULL) {
696 697
            remoteError(VIR_ERR_INTERNAL_ERROR,
                        _("Socket %s too big for destination"), sockname);
C
Chris Lalancette 已提交
698 699
            goto failed;
        }
700 701
        if (addr.sun_path[0] == '@')
            addr.sun_path[0] = '\0';
702

703
      autostart_retry:
704
        priv->is_secure = 1;
705 706
        priv->sock = socket (AF_UNIX, SOCK_STREAM, 0);
        if (priv->sock == -1) {
707
            virReportSystemError(errno, "%s",
708
                                 _("unable to create socket"));
709 710
            goto failed;
        }
711 712 713 714 715 716 717 718 719 720
        if (connect (priv->sock, (struct sockaddr *) &addr, sizeof addr) == -1) {
            /* We might have to autostart the daemon in some cases....
             * It takes a short while for the daemon to startup, hence we
             * have a number of retries, with a small sleep. This will
             * sometimes cause multiple daemons to be started - this is
             * ok because the duplicates will fail to bind to the socket
             * and immediately exit, leaving just one daemon.
             */
            if (errno == ECONNREFUSED &&
                flags & VIR_DRV_OPEN_REMOTE_AUTOSTART &&
721
                trials < 20) {
722
                VIR_FORCE_CLOSE(priv->sock);
723
                if (trials > 0 ||
724
                    remoteForkDaemon() == 0) {
725
                    trials++;
726
                    usleep(1000 * 100 * trials);
727 728 729
                    goto autostart_retry;
                }
            }
730
            virReportSystemError(errno,
731 732
              _("unable to connect to '%s', libvirtd may need to be started"),
              sockname);
733 734 735 736 737 738 739
            goto failed;
        }

        break;
    }

    case trans_ssh: {
740
        int j, nr_args = 6;
741 742 743

        if (username) nr_args += 2; /* For -l username */
        if (no_tty) nr_args += 5;   /* For -T -o BatchMode=yes -e none */
744
        if (port) nr_args += 2;     /* For -p port */
745

746
        command = command ? command : strdup ("ssh");
747 748
        if (command == NULL)
            goto out_of_memory;
749 750

        // Generate the final command argv[] array.
751
        //   ssh [-p $port] [-l $username] $hostname $netcat -U $sockname [NULL]
752 753
        if (VIR_ALLOC_N(cmd_argv, nr_args) < 0)
            goto out_of_memory;
J
Jim Meyering 已提交
754

755 756
        j = 0;
        cmd_argv[j++] = strdup (command);
757 758 759 760
        if (port) {
            cmd_argv[j++] = strdup ("-p");
            cmd_argv[j++] = strdup (port);
        }
761 762 763 764
        if (username) {
            cmd_argv[j++] = strdup ("-l");
            cmd_argv[j++] = strdup (username);
        }
765 766 767 768 769 770 771
        if (no_tty) {
            cmd_argv[j++] = strdup ("-T");
            cmd_argv[j++] = strdup ("-o");
            cmd_argv[j++] = strdup ("BatchMode=yes");
            cmd_argv[j++] = strdup ("-e");
            cmd_argv[j++] = strdup ("none");
        }
772
        cmd_argv[j++] = strdup (priv->hostname);
773 774
        cmd_argv[j++] = strdup (netcat ? netcat : "nc");
        cmd_argv[j++] = strdup ("-U");
775 776 777 778
        cmd_argv[j++] = strdup (sockname ? sockname :
                                (flags & VIR_CONNECT_RO
                                 ? LIBVIRTD_PRIV_UNIX_SOCKET_RO
                                 : LIBVIRTD_PRIV_UNIX_SOCKET));
779 780
        cmd_argv[j++] = 0;
        assert (j == nr_args);
781 782 783
        for (j = 0; j < (nr_args-1); j++)
            if (cmd_argv[j] == NULL)
                goto out_of_memory;
784 785

        priv->is_secure = 1;
786 787 788 789
    }

        /*FALLTHROUGH*/
    case trans_ext: {
790
        pid_t pid;
791
        int sv[2];
792
        int errfd[2];
793 794 795 796 797 798

        /* Fork off the external process.  Use socketpair to create a private
         * (unnamed) Unix domain socket to the child process so we don't have
         * to faff around with two file descriptors (a la 'pipe(2)').
         */
        if (socketpair (PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
799
            virReportSystemError(errno, "%s",
800
                                 _("unable to create socket pair"));
801 802 803
            goto failed;
        }

804 805 806 807 808 809
        if (pipe(errfd) == -1) {
            virReportSystemError(errno, "%s",
                                 _("unable to create socket pair"));
            goto failed;
        }

810
        if (virExec((const char**)cmd_argv, NULL, NULL,
811
                    &pid, sv[1], &(sv[1]), &(errfd[1]),
812
                    VIR_EXEC_CLEAR_CAPS) < 0)
813 814 815
            goto failed;

        /* Parent continues here. */
816 817
        VIR_FORCE_CLOSE(sv[1]);
        VIR_FORCE_CLOSE(errfd[1]);
818
        priv->sock = sv[0];
819
        priv->errfd = errfd[0];
820
        priv->pid = pid;
821 822 823 824

        /* Do not set 'is_secure' flag since we can't guarentee
         * an external program is secure, and this flag must be
         * pessimistic */
825
    }
826 827 828 829 830
#else /* WIN32 */

    case trans_unix:
    case trans_ssh:
    case trans_ext:
831 832 833
        remoteError(VIR_ERR_INVALID_ARG, "%s",
                    _("transport methods unix, ssh and ext are not supported "
                      "under Windows"));
834
        goto failed;
835 836 837

#endif /* WIN32 */

838 839
    } /* switch (transport) */

840
    if (virSetNonBlock(priv->sock) < 0) {
841
        virReportSystemError(errno, "%s",
842
                             _("unable to make socket non-blocking"));
843 844 845
        goto failed;
    }

846 847 848 849 850 851
    if ((priv->errfd != -1) && virSetNonBlock(priv->errfd) < 0) {
        virReportSystemError(errno, "%s",
                             _("unable to make socket non-blocking"));
        goto failed;
    }

852
    if (pipe(wakeupFD) < 0) {
853
        virReportSystemError(errno, "%s",
854
                             _("unable to make pipe"));
855 856 857 858
        goto failed;
    }
    priv->wakeupReadFD = wakeupFD[0];
    priv->wakeupSendFD = wakeupFD[1];
859 860

    /* Try and authenticate with server */
861
    if (remoteAuthenticate(conn, priv, 1, auth, authtype) == -1)
862 863
        goto failed;

864 865 866
    /* Finally we can call the remote side's open function. */
    remote_open_args args = { &name, flags };

867
    if (call (conn, priv, REMOTE_CALL_IN_OPEN, REMOTE_PROC_OPEN,
868 869 870 871
              (xdrproc_t) xdr_remote_open_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto failed;

872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
    /* Now try and find out what URI the daemon used */
    if (conn->uri == NULL) {
        remote_get_uri_ret uriret;
        int urierr;

        memset (&uriret, 0, sizeof uriret);
        urierr = call (conn, priv,
                       REMOTE_CALL_IN_OPEN | REMOTE_CALL_QUIET_MISSING_RPC,
                       REMOTE_PROC_GET_URI,
                       (xdrproc_t) xdr_void, (char *) NULL,
                       (xdrproc_t) xdr_remote_get_uri_ret, (char *) &uriret);
        if (urierr == -2) {
            /* Should not really happen, since we only probe local libvirtd's,
               & the library should always match the daemon. Only case is post
               RPM upgrade where an old daemon instance is still running with
               new client. Too bad. It is not worth the hassle to fix this */
888 889
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("unable to auto-detect URI"));
890 891 892 893 894 895 896 897 898 899
            goto failed;
        }
        if (urierr == -1) {
            goto failed;
        }

        DEBUG("Auto-probed URI is %s", uriret.uri);
        conn->uri = xmlParseURI(uriret.uri);
        VIR_FREE(uriret.uri);
        if (!conn->uri) {
900
            virReportOOMError();
901 902 903 904
            goto failed;
        }
    }

905
    if(VIR_ALLOC(priv->callbackList)<0) {
906
        virReportOOMError();
907 908 909 910
        goto failed;
    }

    if(VIR_ALLOC(priv->domainEvents)<0) {
911
        virReportOOMError();
912 913 914 915 916
        goto failed;
    }

    DEBUG0("Adding Handler for remote events");
    /* Set up a callback to listen on the socket data */
917
    if ((priv->watch = virEventAddHandle(priv->sock,
918
                                         VIR_EVENT_HANDLE_READABLE,
919
                                         remoteDomainEventFired,
920
                                         conn, NULL)) < 0) {
921 922 923 924 925 926
        DEBUG0("virEventAddHandle failed: No addHandleImpl defined."
               " continuing without events.");
    } else {

        DEBUG0("Adding Timeout for remote event queue flushing");
        if ( (priv->eventFlushTimer = virEventAddTimeout(-1,
927 928
                                                         remoteDomainEventQueueFlush,
                                                         conn, NULL)) < 0) {
929 930
            DEBUG0("virEventAddTimeout failed: No addTimeoutImpl defined. "
                    "continuing without events.");
931
            virEventRemoveHandle(priv->watch);
932
            priv->watch = -1;
933 934
        }
    }
935 936 937
    /* Successful. */
    retcode = VIR_DRV_OPEN_SUCCESS;

938
 cleanup:
939
    /* Free up the URL and strings. */
940 941 942 943 944 945 946
    VIR_FREE(name);
    VIR_FREE(command);
    VIR_FREE(sockname);
    VIR_FREE(authtype);
    VIR_FREE(netcat);
    VIR_FREE(username);
    VIR_FREE(port);
947 948 949
    if (cmd_argv) {
        char **cmd_argv_ptr = cmd_argv;
        while (*cmd_argv_ptr) {
950
            VIR_FREE(*cmd_argv_ptr);
951 952
            cmd_argv_ptr++;
        }
953
        VIR_FREE(cmd_argv);
954 955 956
    }

    return retcode;
957 958

 out_of_memory:
959
    virReportOOMError();
960 961
    if (vars)
        free_qparam_set (vars);
962 963 964

 failed:
    /* Close the socket if we failed. */
965
    VIR_FORCE_CLOSE(priv->errfd);
966

967 968 969 970 971
    if (priv->sock >= 0) {
        if (priv->uses_tls && priv->session) {
            gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
            gnutls_deinit (priv->session);
        }
972
        VIR_FORCE_CLOSE(priv->sock);
973
#ifndef WIN32
974 975 976
        if (priv->pid > 0) {
            pid_t reap;
            do {
977
retry:
978 979
                reap = waitpid(priv->pid, NULL, 0);
                if (reap == -1 && errno == EINTR)
980
                    goto retry;
981 982
            } while (reap != -1 && reap != priv->pid);
        }
983
#endif
984 985
    }

986 987
    VIR_FORCE_CLOSE(wakeupFD[0]);
    VIR_FORCE_CLOSE(wakeupFD[1]);
988

989
    VIR_FREE(priv->hostname);
990
    goto cleanup;
991 992
}

993
static struct private_data *
994
remoteAllocPrivateData(void)
995
{
996
    struct private_data *priv;
997
    if (VIR_ALLOC(priv) < 0) {
998
        virReportOOMError();
999
        return NULL;
1000 1001
    }

1002
    if (virMutexInit(&priv->lock) < 0) {
1003 1004
        remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("cannot initialize mutex"));
1005
        VIR_FREE(priv);
1006
        return NULL;
1007 1008 1009
    }
    remoteDriverLock(priv);
    priv->localUses = 1;
1010
    priv->watch = -1;
1011
    priv->sock = -1;
1012
    priv->errfd = -1;
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025

    return priv;
}

static int
remoteOpenSecondaryDriver(virConnectPtr conn,
                          virConnectAuthPtr auth,
                          int flags,
                          struct private_data **priv)
{
    int ret;
    int rflags = 0;

1026
    if (!((*priv) = remoteAllocPrivateData()))
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
        return VIR_DRV_OPEN_ERROR;

    if (flags & VIR_CONNECT_RO)
        rflags |= VIR_DRV_OPEN_REMOTE_RO;

    ret = doRemoteOpen(conn, *priv, auth, rflags);
    if (ret != VIR_DRV_OPEN_SUCCESS) {
        remoteDriverUnlock(*priv);
        VIR_FREE(*priv);
    } else {
        (*priv)->localUses = 1;
        remoteDriverUnlock(*priv);
    }

    return ret;
}

static virDrvOpenStatus
remoteOpen (virConnectPtr conn,
            virConnectAuthPtr auth,
            int flags)
{
    struct private_data *priv;
    int ret, rflags = 0;
1051
    const char *autostart = getenv("LIBVIRT_AUTOSTART");
1052

1053
    if (inside_daemon && (!conn->uri || (conn->uri && !conn->uri->server)))
1054 1055
        return VIR_DRV_OPEN_DECLINED;

1056
    if (!(priv = remoteAllocPrivateData()))
1057
        return VIR_DRV_OPEN_ERROR;
1058

1059
    if (flags & VIR_CONNECT_RO)
1060 1061
        rflags |= VIR_DRV_OPEN_REMOTE_RO;

1062 1063 1064 1065 1066 1067 1068 1069 1070
    /*
     * If no servername is given, and no +XXX
     * transport is listed, or transport is unix,
     * and path is /session, and uid is unprivileged
     * then auto-spawn a daemon.
     */
    if (conn->uri &&
        !conn->uri->server &&
        conn->uri->path &&
D
Daniel P. Berrange 已提交
1071
        conn->uri->scheme &&
1072 1073
        ((strchr(conn->uri->scheme, '+') == 0)||
         (strstr(conn->uri->scheme, "+unix") != NULL)) &&
1074 1075
        (STREQ(conn->uri->path, "/session") ||
         STRPREFIX(conn->uri->scheme, "test+")) &&
1076 1077 1078
        getuid() > 0) {
        DEBUG0("Auto-spawn user daemon instance");
        rflags |= VIR_DRV_OPEN_REMOTE_USER;
1079 1080 1081
        if (!autostart ||
            STRNEQ(autostart, "0"))
            rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
1082 1083 1084
    }

    /*
J
John Levon 已提交
1085 1086 1087 1088
     * If URI is NULL, then do a UNIX connection possibly auto-spawning
     * unprivileged server and probe remote server for URI. On Solaris,
     * this isn't supported, but we may be privileged enough to connect
     * to the UNIX socket anyway.
1089 1090 1091
     */
    if (!conn->uri) {
        DEBUG0("Auto-probe remote URI");
J
John Levon 已提交
1092
#ifndef __sun
1093 1094 1095
        if (getuid() > 0) {
            DEBUG0("Auto-spawn user daemon instance");
            rflags |= VIR_DRV_OPEN_REMOTE_USER;
1096 1097 1098
            if (!autostart ||
                STRNEQ(autostart, "0"))
                rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
1099
        }
J
John Levon 已提交
1100
#endif
1101
    }
1102

1103
    ret = doRemoteOpen(conn, priv, auth, rflags);
1104 1105
    if (ret != VIR_DRV_OPEN_SUCCESS) {
        conn->privateData = NULL;
1106
        remoteDriverUnlock(priv);
1107
        VIR_FREE(priv);
1108 1109
    } else {
        conn->privateData = priv;
1110
        remoteDriverUnlock(priv);
1111 1112 1113 1114 1115
    }
    return ret;
}


1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
/* In a string "driver+transport" return a pointer to "transport". */
static char *
get_transport_from_scheme (char *scheme)
{
    char *p = strchr (scheme, '+');
    return p ? p+1 : 0;
}

/* GnuTLS functions used by remoteOpen. */
static gnutls_certificate_credentials_t x509_cred;

1127 1128

static int
1129
check_cert_file(const char *type, const char *file)
1130 1131 1132
{
    struct stat sb;
    if (stat(file, &sb) < 0) {
1133
        virReportSystemError(errno,
1134 1135
                             _("Cannot access %s '%s'"),
                             type, file);
1136 1137 1138 1139 1140 1141
        return -1;
    }
    return 0;
}


1142 1143 1144 1145
static void remote_debug_gnutls_log(int level, const char* str) {
    DEBUG("%d %s", level, str);
}

1146
static int
1147
initialize_gnutls(void)
1148
{
E
Eric Blake 已提交
1149
    static int initialized = 0;
1150
    int err;
1151
    char *gnutlsdebug;
1152

E
Eric Blake 已提交
1153
    if (initialized) return 0;
1154 1155 1156

    gnutls_global_init ();

1157 1158 1159 1160 1161 1162 1163 1164
    if ((gnutlsdebug = getenv("LIBVIRT_GNUTLS_DEBUG")) != NULL) {
        int val;
        if (virStrToLong_i(gnutlsdebug, NULL, 10, &val) < 0)
            val = 10;
        gnutls_global_set_log_level(val);
        gnutls_global_set_log_function(remote_debug_gnutls_log);
    }

1165 1166 1167
    /* X509 stuff */
    err = gnutls_certificate_allocate_credentials (&x509_cred);
    if (err) {
1168 1169 1170
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to allocate TLS credentials: %s"),
                    gnutls_strerror (err));
1171 1172 1173
        return -1;
    }

1174

1175
    if (check_cert_file("CA certificate", LIBVIRT_CACERT) < 0)
1176
        return -1;
1177
    if (check_cert_file("client key", LIBVIRT_CLIENTKEY) < 0)
1178
        return -1;
1179
    if (check_cert_file("client certificate", LIBVIRT_CLIENTCERT) < 0)
1180 1181
        return -1;

1182
    /* Set the trusted CA cert. */
1183
    DEBUG("loading CA file %s", LIBVIRT_CACERT);
1184 1185 1186 1187
    err =
        gnutls_certificate_set_x509_trust_file (x509_cred, LIBVIRT_CACERT,
                                                GNUTLS_X509_FMT_PEM);
    if (err < 0) {
1188 1189 1190
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to load CA certificate: %s"),
                    gnutls_strerror (err));
1191 1192 1193 1194
        return -1;
    }

    /* Set the client certificate and private key. */
1195 1196
    DEBUG("loading client cert and key from files %s and %s",
          LIBVIRT_CLIENTCERT, LIBVIRT_CLIENTKEY);
1197 1198 1199 1200 1201 1202
    err =
        gnutls_certificate_set_x509_key_file (x509_cred,
                                              LIBVIRT_CLIENTCERT,
                                              LIBVIRT_CLIENTKEY,
                                              GNUTLS_X509_FMT_PEM);
    if (err < 0) {
1203 1204 1205
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to load private key/certificate: %s"),
                    gnutls_strerror (err));
1206 1207 1208
        return -1;
    }

E
Eric Blake 已提交
1209
    initialized = 1;
1210 1211 1212
    return 0;
}

1213
static int verify_certificate (virConnectPtr conn, struct private_data *priv, gnutls_session_t session);
1214

1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228
#if HAVE_WINSOCK2_H
static ssize_t
custom_gnutls_push(void *s, const void *buf, size_t len)
{
    return send((size_t)s, buf, len, 0);
}

static ssize_t
custom_gnutls_pull(void *s, void *buf, size_t len)
{
    return recv((size_t)s, buf, len, 0);
}
#endif

1229 1230
static gnutls_session_t
negotiate_gnutls_on_connection (virConnectPtr conn,
1231 1232
                                struct private_data *priv,
                                int no_verify)
1233 1234 1235 1236 1237 1238 1239 1240 1241
{
    const int cert_type_priority[3] = {
        GNUTLS_CRT_X509,
        GNUTLS_CRT_OPENPGP,
        0
    };
    int err;
    gnutls_session_t session;

1242
    /* Initialize TLS session
1243 1244 1245
     */
    err = gnutls_init (&session, GNUTLS_CLIENT);
    if (err) {
1246 1247 1248
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to initialize TLS client: %s"),
                    gnutls_strerror (err));
1249 1250 1251 1252 1253 1254
        return NULL;
    }

    /* Use default priorities */
    err = gnutls_set_default_priority (session);
    if (err) {
1255 1256 1257
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to set TLS algorithm priority: %s"),
                    gnutls_strerror (err));
1258 1259 1260 1261 1262 1263
        return NULL;
    }
    err =
        gnutls_certificate_type_set_priority (session,
                                              cert_type_priority);
    if (err) {
1264 1265 1266
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to set certificate priority: %s"),
                    gnutls_strerror (err));
1267 1268 1269 1270 1271 1272 1273
        return NULL;
    }

    /* put the x509 credentials to the current session
     */
    err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
    if (err) {
1274 1275 1276
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to set session credentials: %s"),
                    gnutls_strerror (err));
1277 1278 1279 1280
        return NULL;
    }

    gnutls_transport_set_ptr (session,
1281
                              (gnutls_transport_ptr_t) (long) priv->sock);
1282

1283 1284 1285 1286 1287 1288 1289
#if HAVE_WINSOCK2_H
    /* Make sure GnuTLS uses gnulib's replacment functions for send() and
     * recv() on Windows */
    gnutls_transport_set_push_function(session, custom_gnutls_push);
    gnutls_transport_set_pull_function(session, custom_gnutls_pull);
#endif

1290 1291 1292 1293 1294 1295
    /* Perform the TLS handshake. */
 again:
    err = gnutls_handshake (session);
    if (err < 0) {
        if (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED)
            goto again;
1296 1297 1298
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to complete TLS handshake: %s"),
                    gnutls_strerror (err));
1299 1300 1301 1302
        return NULL;
    }

    /* Verify certificate. */
1303
    if (verify_certificate (conn, priv, session) == -1) {
1304 1305 1306
        DEBUG0("failed to verify peer's certificate");
        if (!no_verify) return NULL;
    }
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317

    /* At this point, the server is verifying _our_ certificate, IP address,
     * etc.  If we make the grade, it will send us a '\1' byte.
     */
    char buf[1];
    int len;
 again_2:
    len = gnutls_record_recv (session, buf, 1);
    if (len < 0 && len != GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
        if (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED)
            goto again_2;
1318 1319 1320
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to complete TLS initialization: %s"),
                    gnutls_strerror (len));
1321 1322 1323
        return NULL;
    }
    if (len != 1 || buf[0] != '\1') {
1324 1325 1326
        remoteError(VIR_ERR_RPC, "%s",
                    _("server verification (of our certificate or IP "
                      "address) failed"));
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
        return NULL;
    }

#if 0
    /* Print session info. */
    print_info (session);
#endif

    return session;
}

static int
verify_certificate (virConnectPtr conn ATTRIBUTE_UNUSED,
1340 1341
                    struct private_data *priv,
                    gnutls_session_t session)
1342 1343 1344 1345 1346 1347 1348 1349
{
    int ret;
    unsigned int status;
    const gnutls_datum_t *certs;
    unsigned int nCerts, i;
    time_t now;

    if ((ret = gnutls_certificate_verify_peers2 (session, &status)) < 0) {
1350 1351 1352
        remoteError(VIR_ERR_GNUTLS_ERROR,
                    _("unable to verify server certificate: %s"),
                    gnutls_strerror (ret));
1353 1354
        return -1;
    }
1355

1356
    if ((now = time(NULL)) == ((time_t)-1)) {
1357
        virReportSystemError(errno, "%s",
1358
                             _("cannot get current time"));
1359 1360 1361 1362
        return -1;
    }

    if (status != 0) {
1363
        const char *reason = _("Invalid certificate");
1364 1365

        if (status & GNUTLS_CERT_INVALID)
1366
            reason = _("The certificate is not trusted.");
1367

1368
        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1369
            reason = _("The certificate hasn't got a known issuer.");
1370

1371
        if (status & GNUTLS_CERT_REVOKED)
1372
            reason = _("The certificate has been revoked.");
1373 1374

#ifndef GNUTLS_1_0_COMPAT
1375
        if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1376
            reason = _("The certificate uses an insecure algorithm");
1377
#endif
1378

1379 1380 1381
        remoteError(VIR_ERR_RPC,
                    _("server certificate failed validation: %s"),
                    reason);
1382 1383 1384 1385
        return -1;
    }

    if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
1386
        remoteError(VIR_ERR_RPC,  "%s",_("Certificate type is not X.509"));
1387 1388
        return -1;
    }
1389

1390
    if (!(certs = gnutls_certificate_get_peers(session, &nCerts))) {
1391
        remoteError(VIR_ERR_RPC,  "%s",_("gnutls_certificate_get_peers failed"));
1392 1393
        return -1;
    }
1394

1395 1396 1397 1398 1399
    for (i = 0 ; i < nCerts ; i++) {
        gnutls_x509_crt_t cert;

        ret = gnutls_x509_crt_init (&cert);
        if (ret < 0) {
1400 1401 1402
            remoteError(VIR_ERR_GNUTLS_ERROR,
                        _("unable to initialize certificate: %s"),
                        gnutls_strerror (ret));
1403 1404
            return -1;
        }
1405

1406 1407
        ret = gnutls_x509_crt_import (cert, &certs[i], GNUTLS_X509_FMT_DER);
        if (ret < 0) {
1408 1409 1410
            remoteError(VIR_ERR_GNUTLS_ERROR,
                        _("unable to import certificate: %s"),
                        gnutls_strerror (ret));
1411 1412 1413
            gnutls_x509_crt_deinit (cert);
            return -1;
        }
1414

1415
        if (gnutls_x509_crt_get_expiration_time (cert) < now) {
1416
            remoteError(VIR_ERR_RPC, "%s", _("The certificate has expired"));
1417 1418 1419
            gnutls_x509_crt_deinit (cert);
            return -1;
        }
1420

1421
        if (gnutls_x509_crt_get_activation_time (cert) > now) {
1422 1423
            remoteError(VIR_ERR_RPC, "%s",
                        _("The certificate is not yet activated"));
1424 1425 1426
            gnutls_x509_crt_deinit (cert);
            return -1;
        }
1427

1428
        if (i == 0) {
1429
            if (!gnutls_x509_crt_check_hostname (cert, priv->hostname)) {
1430 1431 1432
                remoteError(VIR_ERR_RPC,
                            _("Certificate's owner does not match the hostname (%s)"),
                            priv->hostname);
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
                gnutls_x509_crt_deinit (cert);
                return -1;
            }
        }
    }

    return 0;
}

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

1444

1445
static int
1446
doRemoteClose (virConnectPtr conn, struct private_data *priv)
1447
{
1448 1449 1450 1451 1452
    if (priv->eventFlushTimer >= 0) {
        /* Remove timeout */
        virEventRemoveTimeout(priv->eventFlushTimer);
        /* Remove handle for remote events */
        virEventRemoveHandle(priv->watch);
1453
        priv->watch = -1;
1454
    }
1455

1456 1457 1458 1459 1460
    if (call (conn, priv, 0, REMOTE_PROC_CLOSE,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        return -1;

1461
    /* Close socket. */
1462
    if (priv->uses_tls && priv->session) {
1463
        gnutls_bye (priv->session, GNUTLS_SHUT_RDWR);
1464 1465 1466 1467 1468 1469
        gnutls_deinit (priv->session);
    }
#if HAVE_SASL
    if (priv->saslconn)
        sasl_dispose (&priv->saslconn);
#endif
1470 1471
    VIR_FORCE_CLOSE(priv->sock);
    VIR_FORCE_CLOSE(priv->errfd);
1472

1473
#ifndef WIN32
1474 1475 1476
    if (priv->pid > 0) {
        pid_t reap;
        do {
1477
retry:
1478 1479
            reap = waitpid(priv->pid, NULL, 0);
            if (reap == -1 && errno == EINTR)
1480
                goto retry;
1481 1482
        } while (reap != -1 && reap != priv->pid);
    }
1483
#endif
1484 1485
    VIR_FORCE_CLOSE(priv->wakeupReadFD);
    VIR_FORCE_CLOSE(priv->wakeupSendFD);
1486

1487

1488
    /* Free hostname copy */
1489
    VIR_FREE(priv->hostname);
1490

1491
    /* See comment for remoteType. */
1492
    VIR_FREE(priv->type);
1493

1494 1495 1496 1497 1498 1499
    /* Free callback list */
    virDomainEventCallbackListFree(priv->callbackList);

    /* Free queued events */
    virDomainEventQueueFree(priv->domainEvents);

1500 1501 1502
    return 0;
}

1503 1504 1505
static int
remoteClose (virConnectPtr conn)
{
1506
    int ret = 0;
1507
    struct private_data *priv = conn->privateData;
1508

1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
    remoteDriverLock(priv);
    priv->localUses--;
    if (!priv->localUses) {
        ret = doRemoteClose(conn, priv);
        conn->privateData = NULL;
        remoteDriverUnlock(priv);
        virMutexDestroy(&priv->lock);
        VIR_FREE (priv);
    }
    if (priv)
        remoteDriverUnlock(priv);
1520 1521 1522 1523

    return ret;
}

1524 1525 1526
static int
remoteSupportsFeature (virConnectPtr conn, int feature)
{
1527
    int rv = -1;
1528 1529
    remote_supports_feature_args args;
    remote_supports_feature_ret ret;
1530
    struct private_data *priv = conn->privateData;
1531

1532 1533
    remoteDriverLock(priv);

1534
    /* VIR_DRV_FEATURE_REMOTE* features are handled directly. */
1535 1536 1537 1538
    if (feature == VIR_DRV_FEATURE_REMOTE) {
        rv = 1;
        goto done;
    }
1539 1540 1541 1542 1543 1544 1545

    args.feature = feature;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_SUPPORTS_FEATURE,
              (xdrproc_t) xdr_remote_supports_feature_args, (char *) &args,
              (xdrproc_t) xdr_remote_supports_feature_ret, (char *) &ret) == -1)
1546 1547 1548
        goto done;

    rv = ret.supported;
1549

1550
done:
1551
    remoteDriverUnlock(priv);
1552
    return rv;
1553 1554
}

1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565
/* Unfortunately this function is defined to return a static string.
 * Since the remote end always answers with the same type (for a
 * single connection anyway) we cache the type in the connection's
 * private data, and free it when we close the connection.
 *
 * See also:
 * http://www.redhat.com/archives/libvir-list/2007-February/msg00096.html
 */
static const char *
remoteType (virConnectPtr conn)
{
1566
    char *rv = NULL;
1567
    remote_get_type_ret ret;
1568
    struct private_data *priv = conn->privateData;
1569

1570 1571
    remoteDriverLock(priv);

1572
    /* Cached? */
1573 1574 1575 1576
    if (priv->type) {
        rv = priv->type;
        goto done;
    }
1577 1578 1579 1580 1581

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_GET_TYPE,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_get_type_ret, (char *) &ret) == -1)
1582
        goto done;
1583 1584

    /* Stash. */
1585 1586 1587
    rv = priv->type = ret.type;

done:
1588
    remoteDriverUnlock(priv);
1589
    return rv;
1590 1591 1592
}

static int
1593
remoteGetVersion (virConnectPtr conn, unsigned long *hvVer)
1594
{
1595
    int rv = -1;
1596
    remote_get_version_ret ret;
1597
    struct private_data *priv = conn->privateData;
1598

1599 1600
    remoteDriverLock(priv);

1601 1602 1603 1604
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_GET_VERSION,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_get_version_ret, (char *) &ret) == -1)
1605
        goto done;
1606 1607

    if (hvVer) *hvVer = ret.hv_ver;
1608 1609 1610
    rv = 0;

done:
1611
    remoteDriverUnlock(priv);
1612
    return rv;
1613 1614
}

1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638
static int
remoteGetLibVersion (virConnectPtr conn, unsigned long *libVer)
{
    int rv = -1;
    remote_get_lib_version_ret ret;
    struct private_data *priv = conn->privateData;

    remoteDriverLock(priv);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_GET_LIB_VERSION,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_get_lib_version_ret,
              (char *) &ret) == -1)
        goto done;

    if (libVer) *libVer = ret.lib_ver;
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

1639 1640 1641
static char *
remoteGetHostname (virConnectPtr conn)
{
1642
    char *rv = NULL;
1643
    remote_get_hostname_ret ret;
1644
    struct private_data *priv = conn->privateData;
1645

1646 1647
    remoteDriverLock(priv);

1648 1649 1650 1651
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_GET_HOSTNAME,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_get_hostname_ret, (char *) &ret) == -1)
1652
        goto done;
1653 1654

    /* Caller frees this. */
1655 1656 1657
    rv = ret.hostname;

done:
1658
    remoteDriverUnlock(priv);
1659
    return rv;
1660 1661
}

1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727
static int remoteIsSecure(virConnectPtr conn)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_is_secure_ret ret;
    remoteDriverLock(priv);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_IS_SECURE,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_is_secure_ret, (char *) &ret) == -1)
        goto done;

    /* We claim to be secure, if the remote driver
     * transport itself is secure, and the remote
     * HV connection is secure
     *
     * ie, we don't want to claim to be secure if the
     * remote driver is used to connect to a XenD
     * driver using unencrypted HTTP:/// access
     */
    rv = priv->is_secure && ret.secure ? 1 : 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int remoteIsEncrypted(virConnectPtr conn)
{
    int rv = -1;
    int encrypted = 0;
    struct private_data *priv = conn->privateData;
    remote_is_secure_ret ret;
    remoteDriverLock(priv);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_IS_SECURE,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_is_secure_ret, (char *) &ret) == -1)
        goto done;

    if (priv->uses_tls)
        encrypted = 1;
#if HAVE_SASL
    else if (priv->saslconn)
        encrypted = 1;
#endif


    /* We claim to be encrypted, if the remote driver
     * transport itself is encrypted, and the remote
     * HV connection is secure.
     *
     * Yes, we really don't check the remote 'encrypted'
     * option, since it will almost always be false,
     * even if secure (eg UNIX sockets).
     */
    rv = encrypted && ret.secure ? 1 : 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}


1728 1729 1730
static int
remoteGetMaxVcpus (virConnectPtr conn, const char *type)
{
1731
    int rv = -1;
1732 1733
    remote_get_max_vcpus_args args;
    remote_get_max_vcpus_ret ret;
1734
    struct private_data *priv = conn->privateData;
1735

1736 1737
    remoteDriverLock(priv);

1738
    memset (&ret, 0, sizeof ret);
1739
    args.type = type == NULL ? NULL : (char **) &type;
1740 1741 1742
    if (call (conn, priv, 0, REMOTE_PROC_GET_MAX_VCPUS,
              (xdrproc_t) xdr_remote_get_max_vcpus_args, (char *) &args,
              (xdrproc_t) xdr_remote_get_max_vcpus_ret, (char *) &ret) == -1)
1743 1744 1745
        goto done;

    rv = ret.max_vcpus;
1746

1747
done:
1748
    remoteDriverUnlock(priv);
1749
    return rv;
1750 1751 1752 1753 1754
}

static int
remoteNodeGetInfo (virConnectPtr conn, virNodeInfoPtr info)
{
1755
    int rv = -1;
1756
    remote_node_get_info_ret ret;
1757
    struct private_data *priv = conn->privateData;
1758

1759 1760
    remoteDriverLock(priv);

1761 1762 1763 1764
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_INFO,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_node_get_info_ret, (char *) &ret) == -1)
1765
        goto done;
1766

C
Chris Lalancette 已提交
1767 1768
    if (virStrcpyStatic(info->model, ret.model) == NULL)
        goto done;
1769 1770 1771 1772 1773 1774 1775
    info->memory = ret.memory;
    info->cpus = ret.cpus;
    info->mhz = ret.mhz;
    info->nodes = ret.nodes;
    info->sockets = ret.sockets;
    info->cores = ret.cores;
    info->threads = ret.threads;
1776 1777 1778
    rv = 0;

done:
1779
    remoteDriverUnlock(priv);
1780
    return rv;
1781 1782 1783 1784 1785
}

static char *
remoteGetCapabilities (virConnectPtr conn)
{
1786
    char *rv = NULL;
1787
    remote_get_capabilities_ret ret;
1788
    struct private_data *priv = conn->privateData;
1789

1790 1791
    remoteDriverLock(priv);

1792 1793 1794 1795
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_GET_CAPABILITIES,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_get_capabilities_ret, (char *)&ret) == -1)
1796
        goto done;
1797 1798

    /* Caller frees this. */
1799 1800 1801
    rv = ret.capabilities;

done:
1802
    remoteDriverUnlock(priv);
1803
    return rv;
1804 1805
}

1806 1807 1808 1809 1810 1811
static int
remoteNodeGetCellsFreeMemory(virConnectPtr conn,
                            unsigned long long *freeMems,
                            int startCell,
                            int maxCells)
{
1812
    int rv = -1;
1813 1814 1815
    remote_node_get_cells_free_memory_args args;
    remote_node_get_cells_free_memory_ret ret;
    int i;
1816
    struct private_data *priv = conn->privateData;
1817

1818 1819
    remoteDriverLock(priv);

1820
    if (maxCells > REMOTE_NODE_MAX_CELLS) {
1821 1822 1823
        remoteError(VIR_ERR_RPC,
                    _("too many NUMA cells: %d > %d"),
                    maxCells, REMOTE_NODE_MAX_CELLS);
1824
        goto done;
1825 1826 1827 1828 1829 1830 1831 1832 1833
    }

    args.startCell = startCell;
    args.maxCells = maxCells;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY,
              (xdrproc_t) xdr_remote_node_get_cells_free_memory_args, (char *)&args,
              (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *)&ret) == -1)
1834
        goto done;
1835 1836 1837 1838 1839 1840

    for (i = 0 ; i < ret.freeMems.freeMems_len ; i++)
        freeMems[i] = ret.freeMems.freeMems_val[i];

    xdr_free((xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *) &ret);

1841 1842 1843
    rv = ret.freeMems.freeMems_len;

done:
1844
    remoteDriverUnlock(priv);
1845
    return rv;
1846 1847 1848 1849 1850
}

static unsigned long long
remoteNodeGetFreeMemory (virConnectPtr conn)
{
1851
    unsigned long long rv = 0; /* 0 is error value this special function*/
1852
    remote_node_get_free_memory_ret ret;
1853
    struct private_data *priv = conn->privateData;
1854

1855 1856
    remoteDriverLock(priv);

1857 1858 1859 1860
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_MEMORY,
              (xdrproc_t) xdr_void, NULL,
              (xdrproc_t) xdr_remote_node_get_free_memory_ret, (char *)&ret) == -1)
1861 1862 1863
        goto done;

    rv = ret.freeMem;
1864

1865
done:
1866
    remoteDriverUnlock(priv);
1867
    return rv;
1868 1869 1870
}


1871 1872 1873
static int
remoteListDomains (virConnectPtr conn, int *ids, int maxids)
{
1874
    int rv = -1;
1875 1876 1877
    int i;
    remote_list_domains_args args;
    remote_list_domains_ret ret;
1878
    struct private_data *priv = conn->privateData;
1879

1880 1881
    remoteDriverLock(priv);

1882
    if (maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
1883 1884 1885
        remoteError(VIR_ERR_RPC,
                    _("too many remote domain IDs: %d > %d"),
                    maxids, REMOTE_DOMAIN_ID_LIST_MAX);
1886
        goto done;
1887 1888 1889 1890 1891 1892 1893
    }
    args.maxids = maxids;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_DOMAINS,
              (xdrproc_t) xdr_remote_list_domains_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret) == -1)
1894
        goto done;
1895 1896

    if (ret.ids.ids_len > maxids) {
1897 1898 1899
        remoteError(VIR_ERR_RPC,
                    _("too many remote domain IDs: %d > %d"),
                    ret.ids.ids_len, maxids);
1900
        goto cleanup;
1901 1902 1903 1904 1905
    }

    for (i = 0; i < ret.ids.ids_len; ++i)
        ids[i] = ret.ids.ids_val[i];

1906 1907 1908
    rv = ret.ids.ids_len;

cleanup:
1909 1910
    xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);

1911
done:
1912
    remoteDriverUnlock(priv);
1913
    return rv;
1914 1915 1916 1917 1918
}

static int
remoteNumOfDomains (virConnectPtr conn)
{
1919
    int rv = -1;
1920
    remote_num_of_domains_ret ret;
1921
    struct private_data *priv = conn->privateData;
1922

1923 1924
    remoteDriverLock(priv);

1925 1926 1927 1928
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DOMAINS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_domains_ret, (char *) &ret) == -1)
1929 1930 1931
        goto done;

    rv = ret.num;
1932

1933
done:
1934
    remoteDriverUnlock(priv);
1935
    return rv;
1936 1937
}

1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985
static int
remoteDomainIsActive(virDomainPtr domain)
{
    int rv = -1;
    remote_domain_is_active_args args;
    remote_domain_is_active_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_ACTIVE,
              (xdrproc_t) xdr_remote_domain_is_active_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_is_active_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainIsPersistent(virDomainPtr domain)
{
    int rv = -1;
    remote_domain_is_persistent_args args;
    remote_domain_is_persistent_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_IS_PERSISTENT,
              (xdrproc_t) xdr_remote_domain_is_persistent_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_is_persistent_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.persistent;

done:
    remoteDriverUnlock(priv);
    return rv;
}

1986
static virDomainPtr
1987
remoteDomainCreateXML (virConnectPtr conn,
1988 1989 1990
                         const char *xmlDesc,
                         unsigned int flags)
{
1991
    virDomainPtr dom = NULL;
1992 1993
    remote_domain_create_xml_args args;
    remote_domain_create_xml_ret ret;
1994
    struct private_data *priv = conn->privateData;
1995

1996 1997
    remoteDriverLock(priv);

1998 1999 2000 2001
    args.xml_desc = (char *) xmlDesc;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
2002 2003 2004
    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_XML,
              (xdrproc_t) xdr_remote_domain_create_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_create_xml_ret, (char *) &ret) == -1)
2005
        goto done;
2006 2007

    dom = get_nonnull_domain (conn, ret.dom);
2008
    xdr_free ((xdrproc_t) &xdr_remote_domain_create_xml_ret, (char *) &ret);
2009

2010
done:
2011
    remoteDriverUnlock(priv);
2012 2013 2014 2015 2016 2017
    return dom;
}

static virDomainPtr
remoteDomainLookupByID (virConnectPtr conn, int id)
{
2018
    virDomainPtr dom = NULL;
2019 2020
    remote_domain_lookup_by_id_args args;
    remote_domain_lookup_by_id_ret ret;
2021
    struct private_data *priv = conn->privateData;
2022

2023 2024
    remoteDriverLock(priv);

2025 2026 2027 2028 2029 2030
    args.id = id;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_ID,
              (xdrproc_t) xdr_remote_domain_lookup_by_id_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_lookup_by_id_ret, (char *) &ret) == -1)
2031
        goto done;
2032 2033 2034 2035

    dom = get_nonnull_domain (conn, ret.dom);
    xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_id_ret, (char *) &ret);

2036
done:
2037
    remoteDriverUnlock(priv);
2038 2039 2040 2041 2042 2043
    return dom;
}

static virDomainPtr
remoteDomainLookupByUUID (virConnectPtr conn, const unsigned char *uuid)
{
2044
    virDomainPtr dom = NULL;
2045 2046
    remote_domain_lookup_by_uuid_args args;
    remote_domain_lookup_by_uuid_ret ret;
2047
    struct private_data *priv = conn->privateData;
2048

2049 2050
    remoteDriverLock(priv);

2051 2052 2053 2054 2055 2056
    memcpy (args.uuid, uuid, VIR_UUID_BUFLEN);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID,
              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret) == -1)
2057
        goto done;
2058 2059 2060

    dom = get_nonnull_domain (conn, ret.dom);
    xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret);
2061 2062

done:
2063
    remoteDriverUnlock(priv);
2064 2065 2066 2067 2068 2069
    return dom;
}

static virDomainPtr
remoteDomainLookupByName (virConnectPtr conn, const char *name)
{
2070
    virDomainPtr dom = NULL;
2071 2072
    remote_domain_lookup_by_name_args args;
    remote_domain_lookup_by_name_ret ret;
2073
    struct private_data *priv = conn->privateData;
2074

2075 2076
    remoteDriverLock(priv);

2077 2078 2079 2080 2081 2082
    args.name = (char *) name;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_domain_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_lookup_by_name_ret, (char *) &ret) == -1)
2083
        goto done;
2084 2085 2086 2087

    dom = get_nonnull_domain (conn, ret.dom);
    xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_name_ret, (char *) &ret);

2088
done:
2089
    remoteDriverUnlock(priv);
2090 2091 2092 2093 2094 2095
    return dom;
}

static int
remoteDomainSuspend (virDomainPtr domain)
{
2096
    int rv = -1;
2097
    remote_domain_suspend_args args;
2098
    struct private_data *priv = domain->conn->privateData;
2099

2100 2101
    remoteDriverLock(priv);

2102 2103 2104 2105 2106
    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SUSPEND,
              (xdrproc_t) xdr_remote_domain_suspend_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2107
        goto done;
2108

2109 2110 2111
    rv = 0;

done:
2112
    remoteDriverUnlock(priv);
2113
    return rv;
2114 2115 2116 2117 2118
}

static int
remoteDomainResume (virDomainPtr domain)
{
2119
    int rv = -1;
2120
    remote_domain_resume_args args;
2121
    struct private_data *priv = domain->conn->privateData;
2122

2123 2124
    remoteDriverLock(priv);

2125 2126 2127 2128 2129
    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_RESUME,
              (xdrproc_t) xdr_remote_domain_resume_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2130
        goto done;
2131

2132 2133 2134
    rv = 0;

done:
2135
    remoteDriverUnlock(priv);
2136
    return rv;
2137 2138 2139 2140 2141
}

static int
remoteDomainShutdown (virDomainPtr domain)
{
2142
    int rv = -1;
2143
    remote_domain_shutdown_args args;
2144
    struct private_data *priv = domain->conn->privateData;
2145

2146 2147
    remoteDriverLock(priv);

2148 2149 2150 2151 2152
    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SHUTDOWN,
              (xdrproc_t) xdr_remote_domain_shutdown_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2153
        goto done;
2154

2155 2156 2157
    rv = 0;

done:
2158
    remoteDriverUnlock(priv);
2159
    return rv;
2160 2161 2162 2163 2164
}

static int
remoteDomainReboot (virDomainPtr domain, unsigned int flags)
{
2165
    int rv = -1;
2166
    remote_domain_reboot_args args;
2167
    struct private_data *priv = domain->conn->privateData;
2168

2169 2170
    remoteDriverLock(priv);

2171 2172 2173 2174 2175 2176
    make_nonnull_domain (&args.dom, domain);
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_REBOOT,
              (xdrproc_t) xdr_remote_domain_reboot_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2177
        goto done;
2178

2179 2180 2181
    rv = 0;

done:
2182
    remoteDriverUnlock(priv);
2183
    return rv;
2184 2185 2186 2187 2188
}

static int
remoteDomainDestroy (virDomainPtr domain)
{
2189
    int rv = -1;
2190
    remote_domain_destroy_args args;
2191
    struct private_data *priv = domain->conn->privateData;
2192

2193 2194
    remoteDriverLock(priv);

2195 2196 2197 2198 2199
    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DESTROY,
              (xdrproc_t) xdr_remote_domain_destroy_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2200
        goto done;
2201

2202
    rv = 0;
2203
    domain->id = -1;
2204 2205

done:
2206
    remoteDriverUnlock(priv);
2207
    return rv;
2208 2209 2210 2211 2212
}

static char *
remoteDomainGetOSType (virDomainPtr domain)
{
2213
    char *rv = NULL;
2214 2215
    remote_domain_get_os_type_args args;
    remote_domain_get_os_type_ret ret;
2216
    struct private_data *priv = domain->conn->privateData;
2217

2218 2219
    remoteDriverLock(priv);

2220 2221 2222 2223 2224 2225
    make_nonnull_domain (&args.dom, domain);

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_OS_TYPE,
              (xdrproc_t) xdr_remote_domain_get_os_type_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_os_type_ret, (char *) &ret) == -1)
2226
        goto done;
2227 2228

    /* Caller frees. */
2229 2230 2231
    rv = ret.type;

done:
2232
    remoteDriverUnlock(priv);
2233
    return rv;
2234 2235 2236 2237 2238
}

static unsigned long
remoteDomainGetMaxMemory (virDomainPtr domain)
{
2239
    unsigned long rv = 0;
2240 2241
    remote_domain_get_max_memory_args args;
    remote_domain_get_max_memory_ret ret;
2242
    struct private_data *priv = domain->conn->privateData;
2243

2244 2245
    remoteDriverLock(priv);

2246 2247 2248 2249 2250 2251
    make_nonnull_domain (&args.dom, domain);

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_MEMORY,
              (xdrproc_t) xdr_remote_domain_get_max_memory_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_max_memory_ret, (char *) &ret) == -1)
2252 2253 2254
        goto done;

    rv = ret.memory;
2255

2256
done:
2257
    remoteDriverUnlock(priv);
2258
    return rv;
2259 2260 2261 2262 2263
}

static int
remoteDomainSetMaxMemory (virDomainPtr domain, unsigned long memory)
{
2264
    int rv = -1;
2265
    remote_domain_set_max_memory_args args;
2266
    struct private_data *priv = domain->conn->privateData;
2267

2268 2269
    remoteDriverLock(priv);

2270 2271 2272 2273 2274 2275
    make_nonnull_domain (&args.dom, domain);
    args.memory = memory;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MAX_MEMORY,
              (xdrproc_t) xdr_remote_domain_set_max_memory_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2276
        goto done;
2277

2278 2279 2280
    rv = 0;

done:
2281
    remoteDriverUnlock(priv);
2282
    return rv;
2283 2284 2285 2286 2287
}

static int
remoteDomainSetMemory (virDomainPtr domain, unsigned long memory)
{
2288
    int rv = -1;
2289
    remote_domain_set_memory_args args;
2290
    struct private_data *priv = domain->conn->privateData;
2291

2292 2293
    remoteDriverLock(priv);

2294 2295 2296 2297 2298 2299
    make_nonnull_domain (&args.dom, domain);
    args.memory = memory;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY,
              (xdrproc_t) xdr_remote_domain_set_memory_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2300
        goto done;
2301

2302 2303 2304
    rv = 0;

done:
2305
    remoteDriverUnlock(priv);
2306
    return rv;
2307 2308
}

2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477
static int
remoteDomainSetMemoryParameters (virDomainPtr domain,
                                 virMemoryParameterPtr params,
                                 int nparams,
                                 unsigned int flags)
{
    int rv = -1;
    remote_domain_set_memory_parameters_args args;
    int i, do_error;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);

    /* Serialise the memory parameters. */
    args.params.params_len = nparams;
    args.flags = flags;
    if (VIR_ALLOC_N(args.params.params_val, nparams) < 0) {
        virReportOOMError();
        goto done;
    }

    do_error = 0;
    for (i = 0; i < nparams; ++i) {
        // call() will free this:
        args.params.params_val[i].field = strdup (params[i].field);
        if (args.params.params_val[i].field == NULL) {
            virReportOOMError();
            do_error = 1;
        }
        args.params.params_val[i].value.type = params[i].type;
        switch (params[i].type) {
        case VIR_DOMAIN_MEMORY_PARAM_INT:
            args.params.params_val[i].value.remote_memory_param_value_u.i =
                params[i].value.i; break;
        case VIR_DOMAIN_MEMORY_PARAM_UINT:
            args.params.params_val[i].value.remote_memory_param_value_u.ui =
                params[i].value.ui; break;
        case VIR_DOMAIN_MEMORY_PARAM_LLONG:
            args.params.params_val[i].value.remote_memory_param_value_u.l =
                params[i].value.l; break;
        case VIR_DOMAIN_MEMORY_PARAM_ULLONG:
            args.params.params_val[i].value.remote_memory_param_value_u.ul =
                params[i].value.ul; break;
        case VIR_DOMAIN_MEMORY_PARAM_DOUBLE:
            args.params.params_val[i].value.remote_memory_param_value_u.d =
                params[i].value.d; break;
        case VIR_DOMAIN_MEMORY_PARAM_BOOLEAN:
            args.params.params_val[i].value.remote_memory_param_value_u.b =
                params[i].value.b; break;
        default:
            remoteError(VIR_ERR_RPC, "%s", _("unknown parameter type"));
            do_error = 1;
        }
    }

    if (do_error) {
        xdr_free ((xdrproc_t) xdr_remote_domain_set_memory_parameters_args,
                  (char *) &args);
        goto done;
    }

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS,
              (xdrproc_t) xdr_remote_domain_set_memory_parameters_args,
              (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetMemoryParameters (virDomainPtr domain,
                                 virMemoryParameterPtr params, int *nparams,
                                 unsigned int flags)
{
    int rv = -1;
    remote_domain_get_memory_parameters_args args;
    remote_domain_get_memory_parameters_ret ret;
    int i = -1;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.nparams = *nparams;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS,
              (xdrproc_t) xdr_remote_domain_get_memory_parameters_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_memory_parameters_ret, (char *) &ret) == -1)
        goto done;

    /* Check the length of the returned list carefully. */
    if (ret.params.params_len > REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX ||
        ret.params.params_len > *nparams) {
        remoteError(VIR_ERR_RPC, "%s",
                    _("remoteDomainGetMemoryParameters: "
                      "returned number of parameters exceeds limit"));
        goto cleanup;
    }
    /* Handle the case when the caller does not know the number of parameters
     * and is asking for the number of parameters supported
     */
    if (*nparams == 0) {
        *nparams = ret.nparams;
        rv = 0;
        goto cleanup;
    }

    *nparams = ret.params.params_len;

    /* Deserialise the result. */
    for (i = 0; i < *nparams; ++i) {
        if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) {
            remoteError(VIR_ERR_INTERNAL_ERROR,
                        _("Parameter %s too big for destination"),
                        ret.params.params_val[i].field);
            goto cleanup;
        }
        params[i].type = ret.params.params_val[i].value.type;
        switch (params[i].type) {
        case VIR_DOMAIN_MEMORY_PARAM_INT:
            params[i].value.i =
                ret.params.params_val[i].value.remote_memory_param_value_u.i;
            break;
        case VIR_DOMAIN_MEMORY_PARAM_UINT:
            params[i].value.ui =
                ret.params.params_val[i].value.remote_memory_param_value_u.ui;
            break;
        case VIR_DOMAIN_MEMORY_PARAM_LLONG:
            params[i].value.l =
                ret.params.params_val[i].value.remote_memory_param_value_u.l;
            break;
        case VIR_DOMAIN_MEMORY_PARAM_ULLONG:
            params[i].value.ul =
                ret.params.params_val[i].value.remote_memory_param_value_u.ul;
            break;
        case VIR_DOMAIN_MEMORY_PARAM_DOUBLE:
            params[i].value.d =
                ret.params.params_val[i].value.remote_memory_param_value_u.d;
            break;
        case VIR_DOMAIN_MEMORY_PARAM_BOOLEAN:
            params[i].value.b =
                ret.params.params_val[i].value.remote_memory_param_value_u.b;
            break;
        default:
            remoteError(VIR_ERR_RPC, "%s",
                        _("remoteDomainGetMemoryParameters: "
                          "unknown parameter type"));
            goto cleanup;
        }
    }

    rv = 0;

cleanup:
    xdr_free ((xdrproc_t) xdr_remote_domain_get_memory_parameters_ret,
              (char *) &ret);
done:
    remoteDriverUnlock(priv);
    return rv;
}

2478 2479 2480
static int
remoteDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info)
{
2481
    int rv = -1;
2482 2483
    remote_domain_get_info_args args;
    remote_domain_get_info_ret ret;
2484
    struct private_data *priv = domain->conn->privateData;
2485

2486 2487
    remoteDriverLock(priv);

2488 2489 2490 2491 2492 2493
    make_nonnull_domain (&args.dom, domain);

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_INFO,
              (xdrproc_t) xdr_remote_domain_get_info_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_info_ret, (char *) &ret) == -1)
2494
        goto done;
2495 2496 2497 2498 2499 2500

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

2502 2503 2504
    rv = 0;

done:
2505
    remoteDriverUnlock(priv);
2506
    return rv;
2507 2508 2509 2510 2511
}

static int
remoteDomainSave (virDomainPtr domain, const char *to)
{
2512
    int rv = -1;
2513
    remote_domain_save_args args;
2514
    struct private_data *priv = domain->conn->privateData;
2515

2516 2517
    remoteDriverLock(priv);

2518 2519 2520 2521 2522 2523
    make_nonnull_domain (&args.dom, domain);
    args.to = (char *) to;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SAVE,
              (xdrproc_t) xdr_remote_domain_save_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2524
        goto done;
2525

2526 2527 2528
    rv = 0;

done:
2529
    remoteDriverUnlock(priv);
2530
    return rv;
2531 2532 2533 2534 2535
}

static int
remoteDomainRestore (virConnectPtr conn, const char *from)
{
2536
    int rv = -1;
2537
    remote_domain_restore_args args;
2538
    struct private_data *priv = conn->privateData;
2539

2540 2541
    remoteDriverLock(priv);

2542 2543 2544 2545 2546
    args.from = (char *) from;

    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_RESTORE,
              (xdrproc_t) xdr_remote_domain_restore_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2547
        goto done;
2548

2549 2550 2551
    rv = 0;

done:
2552
    remoteDriverUnlock(priv);
2553
    return rv;
2554 2555 2556 2557 2558
}

static int
remoteDomainCoreDump (virDomainPtr domain, const char *to, int flags)
{
2559
    int rv = -1;
2560
    remote_domain_core_dump_args args;
2561
    struct private_data *priv = domain->conn->privateData;
2562

2563 2564
    remoteDriverLock(priv);

2565 2566 2567 2568 2569 2570 2571
    make_nonnull_domain (&args.dom, domain);
    args.to = (char *) to;
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CORE_DUMP,
              (xdrproc_t) xdr_remote_domain_core_dump_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2572
        goto done;
2573

2574 2575 2576
    rv = 0;

done:
2577
    remoteDriverUnlock(priv);
2578
    return rv;
2579 2580 2581 2582 2583
}

static int
remoteDomainSetVcpus (virDomainPtr domain, unsigned int nvcpus)
{
2584
    int rv = -1;
2585
    remote_domain_set_vcpus_args args;
2586
    struct private_data *priv = domain->conn->privateData;
2587

2588 2589
    remoteDriverLock(priv);

2590 2591 2592 2593 2594 2595
    make_nonnull_domain (&args.dom, domain);
    args.nvcpus = nvcpus;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS,
              (xdrproc_t) xdr_remote_domain_set_vcpus_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2596
        goto done;
2597

2598 2599 2600
    rv = 0;

done:
2601
    remoteDriverUnlock(priv);
2602
    return rv;
2603 2604
}

E
Eric Blake 已提交
2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657
static int
remoteDomainSetVcpusFlags (virDomainPtr domain, unsigned int nvcpus,
                           unsigned int flags)
{
    int rv = -1;
    remote_domain_set_vcpus_flags_args args;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.nvcpus = nvcpus;
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS,
              (xdrproc_t) xdr_remote_domain_set_vcpus_flags_args,
              (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainGetVcpusFlags (virDomainPtr domain, unsigned int flags)
{
    int rv = -1;
    remote_domain_get_vcpus_flags_args args;
    remote_domain_get_vcpus_flags_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS,
              (xdrproc_t) xdr_remote_domain_get_vcpus_flags_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_vcpus_flags_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

2658 2659 2660 2661 2662 2663
static int
remoteDomainPinVcpu (virDomainPtr domain,
                     unsigned int vcpu,
                     unsigned char *cpumap,
                     int maplen)
{
2664
    int rv = -1;
2665
    remote_domain_pin_vcpu_args args;
2666
    struct private_data *priv = domain->conn->privateData;
2667

2668 2669
    remoteDriverLock(priv);

2670
    if (maplen > REMOTE_CPUMAP_MAX) {
2671 2672 2673
        remoteError(VIR_ERR_RPC,
                    _("map length greater than maximum: %d > %d"),
                    maplen, REMOTE_CPUMAP_MAX);
2674
        goto done;
2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
    }

    make_nonnull_domain (&args.dom, domain);
    args.vcpu = vcpu;
    args.cpumap.cpumap_len = maplen;
    args.cpumap.cpumap_val = (char *) cpumap;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_VCPU,
              (xdrproc_t) xdr_remote_domain_pin_vcpu_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2685
        goto done;
2686

2687 2688 2689
    rv = 0;

done:
2690
    remoteDriverUnlock(priv);
2691
    return rv;
2692 2693 2694 2695 2696 2697 2698 2699 2700
}

static int
remoteDomainGetVcpus (virDomainPtr domain,
                      virVcpuInfoPtr info,
                      int maxinfo,
                      unsigned char *cpumaps,
                      int maplen)
{
2701
    int rv = -1;
2702 2703 2704
    int i;
    remote_domain_get_vcpus_args args;
    remote_domain_get_vcpus_ret ret;
2705
    struct private_data *priv = domain->conn->privateData;
2706

2707 2708
    remoteDriverLock(priv);

2709
    if (maxinfo > REMOTE_VCPUINFO_MAX) {
2710 2711 2712
        remoteError(VIR_ERR_RPC,
                    _("vCPU count exceeds maximum: %d > %d"),
                    maxinfo, REMOTE_VCPUINFO_MAX);
2713
        goto done;
2714
    }
2715
    if (maxinfo * maplen > REMOTE_CPUMAPS_MAX) {
2716 2717 2718
        remoteError(VIR_ERR_RPC,
                    _("vCPU map buffer length exceeds maximum: %d > %d"),
                    maxinfo * maplen, REMOTE_CPUMAPS_MAX);
2719
        goto done;
2720 2721 2722 2723 2724 2725 2726 2727 2728 2729
    }

    make_nonnull_domain (&args.dom, domain);
    args.maxinfo = maxinfo;
    args.maplen = maplen;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS,
              (xdrproc_t) xdr_remote_domain_get_vcpus_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret) == -1)
2730
        goto done;
2731 2732

    if (ret.info.info_len > maxinfo) {
2733 2734 2735
        remoteError(VIR_ERR_RPC,
                    _("host reports too many vCPUs: %d > %d"),
                    ret.info.info_len, maxinfo);
2736
        goto cleanup;
2737
    }
2738
    if (ret.cpumaps.cpumaps_len > maxinfo * maplen) {
2739 2740 2741
        remoteError(VIR_ERR_RPC,
                    _("host reports map buffer length exceeds maximum: %d > %d"),
                    ret.cpumaps.cpumaps_len, maxinfo * maplen);
2742
        goto cleanup;
2743 2744
    }

2745 2746 2747
    memset (info, 0, sizeof (virVcpuInfo) * maxinfo);
    memset (cpumaps, 0, maxinfo * maplen);

2748 2749 2750 2751 2752 2753 2754 2755 2756 2757
    for (i = 0; i < ret.info.info_len; ++i) {
        info[i].number = ret.info.info_val[i].number;
        info[i].state = ret.info.info_val[i].state;
        info[i].cpuTime = ret.info.info_val[i].cpu_time;
        info[i].cpu = ret.info.info_val[i].cpu;
    }

    for (i = 0; i < ret.cpumaps.cpumaps_len; ++i)
        cpumaps[i] = ret.cpumaps.cpumaps_val[i];

2758 2759 2760
    rv = ret.info.info_len;

cleanup:
2761
    xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret);
2762 2763

done:
2764
    remoteDriverUnlock(priv);
2765
    return rv;
2766 2767 2768 2769 2770
}

static int
remoteDomainGetMaxVcpus (virDomainPtr domain)
{
2771
    int rv = -1;
2772 2773
    remote_domain_get_max_vcpus_args args;
    remote_domain_get_max_vcpus_ret ret;
2774
    struct private_data *priv = domain->conn->privateData;
2775

2776 2777
    remoteDriverLock(priv);

2778 2779 2780
    make_nonnull_domain (&args.dom, domain);

    memset (&ret, 0, sizeof ret);
2781
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MAX_VCPUS,
2782 2783
              (xdrproc_t) xdr_remote_domain_get_max_vcpus_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_max_vcpus_ret, (char *) &ret) == -1)
2784
        goto done;
2785

2786 2787 2788
    rv = ret.num;

done:
2789
    remoteDriverUnlock(priv);
2790
    return rv;
2791 2792
}

2793 2794 2795 2796 2797 2798
static int
remoteDomainGetSecurityLabel (virDomainPtr domain, virSecurityLabelPtr seclabel)
{
    remote_domain_get_security_label_args args;
    remote_domain_get_security_label_ret ret;
    struct private_data *priv = domain->conn->privateData;
2799 2800 2801
    int rv = -1;

    remoteDriverLock(priv);
2802 2803 2804

    make_nonnull_domain (&args.dom, domain);
    memset (&ret, 0, sizeof ret);
2805 2806
    memset (seclabel, 0, sizeof (*seclabel));

2807 2808 2809
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL,
              (xdrproc_t) xdr_remote_domain_get_security_label_args, (char *)&args,
              (xdrproc_t) xdr_remote_domain_get_security_label_ret, (char *)&ret) == -1) {
2810
        goto done;
2811 2812 2813 2814
    }

    if (ret.label.label_val != NULL) {
        if (strlen (ret.label.label_val) >= sizeof seclabel->label) {
2815 2816
            remoteError(VIR_ERR_RPC, _("security label exceeds maximum: %zd"),
                        sizeof seclabel->label - 1);
2817
            goto done;
2818 2819 2820 2821 2822
        }
        strcpy (seclabel->label, ret.label.label_val);
        seclabel->enforcing = ret.enforcing;
    }

2823 2824 2825 2826 2827
    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
2828 2829 2830 2831 2832 2833 2834
}

static int
remoteNodeGetSecurityModel (virConnectPtr conn, virSecurityModelPtr secmodel)
{
    remote_node_get_security_model_ret ret;
    struct private_data *priv = conn->privateData;
2835 2836 2837
    int rv = -1;

    remoteDriverLock(priv);
2838 2839

    memset (&ret, 0, sizeof ret);
2840 2841
    memset (secmodel, 0, sizeof (*secmodel));

2842 2843 2844
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_SECURITY_MODEL,
              (xdrproc_t) xdr_void, NULL,
              (xdrproc_t) xdr_remote_node_get_security_model_ret, (char *)&ret) == -1) {
2845
        goto done;
2846 2847 2848 2849
    }

    if (ret.model.model_val != NULL) {
        if (strlen (ret.model.model_val) >= sizeof secmodel->model) {
2850 2851
            remoteError(VIR_ERR_RPC, _("security model exceeds maximum: %zd"),
                        sizeof secmodel->model - 1);
2852
            goto done;
2853 2854 2855 2856 2857 2858
        }
        strcpy (secmodel->model, ret.model.model_val);
    }

    if (ret.doi.doi_val != NULL) {
        if (strlen (ret.doi.doi_val) >= sizeof secmodel->doi) {
2859 2860
            remoteError(VIR_ERR_RPC, _("security doi exceeds maximum: %zd"),
                        sizeof secmodel->doi - 1);
2861
            goto done;
2862 2863 2864
        }
        strcpy (secmodel->doi, ret.doi.doi_val);
    }
2865 2866 2867 2868 2869 2870

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
2871 2872
}

2873 2874 2875
static char *
remoteDomainDumpXML (virDomainPtr domain, int flags)
{
2876
    char *rv = NULL;
2877 2878
    remote_domain_dump_xml_args args;
    remote_domain_dump_xml_ret ret;
2879
    struct private_data *priv = domain->conn->privateData;
2880

2881 2882
    remoteDriverLock(priv);

2883 2884 2885 2886 2887 2888 2889
    make_nonnull_domain (&args.dom, domain);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DUMP_XML,
              (xdrproc_t) xdr_remote_domain_dump_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_dump_xml_ret, (char *) &ret) == -1)
2890
        goto done;
2891 2892

    /* Caller frees. */
2893 2894 2895
    rv = ret.xml;

done:
2896
    remoteDriverUnlock(priv);
2897
    return rv;
2898 2899
}

2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961
static char *
remoteDomainXMLFromNative (virConnectPtr conn,
                           const char *format,
                           const char *config,
                           unsigned int flags)
{
    char *rv = NULL;
    remote_domain_xml_from_native_args args;
    remote_domain_xml_from_native_ret ret;
    struct private_data *priv = conn->privateData;

    remoteDriverLock(priv);

    args.nativeFormat = (char *)format;
    args.nativeConfig = (char *)config;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_XML_FROM_NATIVE,
              (xdrproc_t) xdr_remote_domain_xml_from_native_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_xml_from_native_ret, (char *) &ret) == -1)
        goto done;

    /* Caller frees. */
    rv = ret.domainXml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static char *
remoteDomainXMLToNative (virConnectPtr conn,
                         const char *format,
                         const char *xml,
                         unsigned int flags)
{
    char *rv = NULL;
    remote_domain_xml_to_native_args args;
    remote_domain_xml_to_native_ret ret;
    struct private_data *priv = conn->privateData;

    remoteDriverLock(priv);

    args.nativeFormat = (char *)format;
    args.domainXml = (char *)xml;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_XML_TO_NATIVE,
              (xdrproc_t) xdr_remote_domain_xml_to_native_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_xml_to_native_ret, (char *) &ret) == -1)
        goto done;

    /* Caller frees. */
    rv = ret.nativeConfig;

done:
    remoteDriverUnlock(priv);
    return rv;
}

2962 2963 2964 2965 2966 2967 2968
static int
remoteDomainMigratePrepare (virConnectPtr dconn,
                            char **cookie, int *cookielen,
                            const char *uri_in, char **uri_out,
                            unsigned long flags, const char *dname,
                            unsigned long resource)
{
2969
    int rv = -1;
2970 2971
    remote_domain_migrate_prepare_args args;
    remote_domain_migrate_prepare_ret ret;
2972
    struct private_data *priv = dconn->privateData;
2973

2974 2975
    remoteDriverLock(priv);

2976 2977 2978 2979 2980 2981 2982 2983 2984
    args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
    args.flags = flags;
    args.dname = dname == NULL ? NULL : (char **) &dname;
    args.resource = resource;

    memset (&ret, 0, sizeof ret);
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE,
              (xdrproc_t) xdr_remote_domain_migrate_prepare_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_migrate_prepare_ret, (char *) &ret) == -1)
2985
        goto done;
2986 2987 2988 2989 2990 2991 2992 2993

    if (ret.cookie.cookie_len > 0) {
        *cookie = ret.cookie.cookie_val; /* Caller frees. */
        *cookielen = ret.cookie.cookie_len;
    }
    if (ret.uri_out)
        *uri_out = *ret.uri_out; /* Caller frees. */

2994 2995 2996
    rv = 0;

done:
2997
    remoteDriverUnlock(priv);
2998
    return rv;
2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009
}

static int
remoteDomainMigratePerform (virDomainPtr domain,
                            const char *cookie,
                            int cookielen,
                            const char *uri,
                            unsigned long flags,
                            const char *dname,
                            unsigned long resource)
{
3010
    int rv = -1;
3011
    remote_domain_migrate_perform_args args;
3012
    struct private_data *priv = domain->conn->privateData;
3013

3014 3015
    remoteDriverLock(priv);

3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
    make_nonnull_domain (&args.dom, domain);
    args.cookie.cookie_len = cookielen;
    args.cookie.cookie_val = (char *) cookie;
    args.uri = (char *) uri;
    args.flags = flags;
    args.dname = dname == NULL ? NULL : (char **) &dname;
    args.resource = resource;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM,
              (xdrproc_t) xdr_remote_domain_migrate_perform_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3027
        goto done;
3028

3029 3030 3031
    rv = 0;

done:
3032
    remoteDriverUnlock(priv);
3033
    return rv;
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043
}

static virDomainPtr
remoteDomainMigrateFinish (virConnectPtr dconn,
                           const char *dname,
                           const char *cookie,
                           int cookielen,
                           const char *uri,
                           unsigned long flags)
{
3044
    virDomainPtr ddom = NULL;
3045 3046
    remote_domain_migrate_finish_args args;
    remote_domain_migrate_finish_ret ret;
3047
    struct private_data *priv = dconn->privateData;
3048

3049 3050
    remoteDriverLock(priv);

3051 3052 3053 3054 3055 3056 3057 3058 3059 3060
    args.dname = (char *) dname;
    args.cookie.cookie_len = cookielen;
    args.cookie.cookie_val = (char *) cookie;
    args.uri = (char *) uri;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH,
              (xdrproc_t) xdr_remote_domain_migrate_finish_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_migrate_finish_ret, (char *) &ret) == -1)
3061
        goto done;
3062 3063 3064 3065

    ddom = get_nonnull_domain (dconn, ret.ddom);
    xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish_ret, (char *) &ret);

3066
done:
3067
    remoteDriverUnlock(priv);
3068 3069 3070
    return ddom;
}

D
Daniel Veillard 已提交
3071 3072 3073 3074 3075 3076 3077 3078
static int
remoteDomainMigratePrepare2 (virConnectPtr dconn,
                             char **cookie, int *cookielen,
                             const char *uri_in, char **uri_out,
                             unsigned long flags, const char *dname,
                             unsigned long resource,
                             const char *dom_xml)
{
3079
    int rv = -1;
D
Daniel Veillard 已提交
3080 3081
    remote_domain_migrate_prepare2_args args;
    remote_domain_migrate_prepare2_ret ret;
3082
    struct private_data *priv = dconn->privateData;
D
Daniel Veillard 已提交
3083

3084 3085
    remoteDriverLock(priv);

D
Daniel Veillard 已提交
3086 3087 3088 3089 3090 3091 3092 3093 3094 3095
    args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
    args.flags = flags;
    args.dname = dname == NULL ? NULL : (char **) &dname;
    args.resource = resource;
    args.dom_xml = (char *) dom_xml;

    memset (&ret, 0, sizeof ret);
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2,
              (xdrproc_t) xdr_remote_domain_migrate_prepare2_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_migrate_prepare2_ret, (char *) &ret) == -1)
3096
        goto done;
D
Daniel Veillard 已提交
3097 3098

    if (ret.cookie.cookie_len > 0) {
3099 3100 3101 3102 3103
        if (!cookie || !cookielen) {
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("caller ignores cookie or cookielen"));
            goto error;
        }
D
Daniel Veillard 已提交
3104 3105 3106
        *cookie = ret.cookie.cookie_val; /* Caller frees. */
        *cookielen = ret.cookie.cookie_len;
    }
3107 3108 3109 3110 3111 3112
    if (ret.uri_out) {
        if (!uri_out) {
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("caller ignores uri_out"));
            goto error;
        }
D
Daniel Veillard 已提交
3113
        *uri_out = *ret.uri_out; /* Caller frees. */
3114
    }
D
Daniel Veillard 已提交
3115

3116 3117 3118
    rv = 0;

done:
3119
    remoteDriverUnlock(priv);
3120
    return rv;
3121 3122 3123 3124 3125 3126
error:
    if (ret.cookie.cookie_len)
        VIR_FREE(ret.cookie.cookie_val);
    if (ret.uri_out)
        VIR_FREE(*ret.uri_out);
    goto done;
D
Daniel Veillard 已提交
3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137
}

static virDomainPtr
remoteDomainMigrateFinish2 (virConnectPtr dconn,
                            const char *dname,
                            const char *cookie,
                            int cookielen,
                            const char *uri,
                            unsigned long flags,
                            int retcode)
{
3138
    virDomainPtr ddom = NULL;
D
Daniel Veillard 已提交
3139 3140
    remote_domain_migrate_finish2_args args;
    remote_domain_migrate_finish2_ret ret;
3141
    struct private_data *priv = dconn->privateData;
D
Daniel Veillard 已提交
3142

3143 3144
    remoteDriverLock(priv);

D
Daniel Veillard 已提交
3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155
    args.dname = (char *) dname;
    args.cookie.cookie_len = cookielen;
    args.cookie.cookie_val = (char *) cookie;
    args.uri = (char *) uri;
    args.flags = flags;
    args.retcode = retcode;

    memset (&ret, 0, sizeof ret);
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH2,
              (xdrproc_t) xdr_remote_domain_migrate_finish2_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_migrate_finish2_ret, (char *) &ret) == -1)
3156
        goto done;
D
Daniel Veillard 已提交
3157 3158 3159 3160

    ddom = get_nonnull_domain (dconn, ret.ddom);
    xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish2_ret, (char *) &ret);

3161
done:
3162
    remoteDriverUnlock(priv);
D
Daniel Veillard 已提交
3163 3164 3165
    return ddom;
}

3166 3167 3168
static int
remoteListDefinedDomains (virConnectPtr conn, char **const names, int maxnames)
{
3169
    int rv = -1;
3170 3171 3172
    int i;
    remote_list_defined_domains_args args;
    remote_list_defined_domains_ret ret;
3173
    struct private_data *priv = conn->privateData;
3174

3175 3176
    remoteDriverLock(priv);

3177
    if (maxnames > REMOTE_DOMAIN_NAME_LIST_MAX) {
3178 3179 3180
        remoteError(VIR_ERR_RPC,
                    _("too many remote domain names: %d > %d"),
                    maxnames, REMOTE_DOMAIN_NAME_LIST_MAX);
3181
        goto done;
3182 3183 3184 3185 3186 3187 3188
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_DOMAINS,
              (xdrproc_t) xdr_remote_list_defined_domains_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret) == -1)
3189
        goto done;
3190 3191

    if (ret.names.names_len > maxnames) {
3192 3193 3194
        remoteError(VIR_ERR_RPC,
                    _("too many remote domain names: %d > %d"),
                    ret.names.names_len, maxnames);
3195
        goto cleanup;
3196 3197 3198 3199 3200 3201 3202
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
3203
    for (i = 0; i < ret.names.names_len; ++i) {
3204 3205
        names[i] = strdup (ret.names.names_val[i]);

3206 3207 3208 3209
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

3210
            virReportOOMError();
3211 3212 3213 3214
            goto cleanup;
        }
    }

3215 3216 3217
    rv = ret.names.names_len;

cleanup:
3218 3219
    xdr_free ((xdrproc_t) xdr_remote_list_defined_domains_ret, (char *) &ret);

3220
done:
3221
    remoteDriverUnlock(priv);
3222
    return rv;
3223 3224 3225 3226 3227
}

static int
remoteNumOfDefinedDomains (virConnectPtr conn)
{
3228
    int rv = -1;
3229
    remote_num_of_defined_domains_ret ret;
3230
    struct private_data *priv = conn->privateData;
3231

3232 3233
    remoteDriverLock(priv);

3234 3235 3236 3237
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_DOMAINS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_defined_domains_ret, (char *) &ret) == -1)
3238
        goto done;
3239

3240 3241 3242
    rv = ret.num;

done:
3243
    remoteDriverUnlock(priv);
3244
    return rv;
3245 3246 3247 3248 3249
}

static int
remoteDomainCreate (virDomainPtr domain)
{
3250
    int rv = -1;
3251
    remote_domain_create_args args;
3252 3253
    remote_domain_lookup_by_uuid_args args2;
    remote_domain_lookup_by_uuid_ret ret2;
3254
    struct private_data *priv = domain->conn->privateData;
3255

3256 3257
    remoteDriverLock(priv);

3258 3259 3260 3261 3262
    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE,
              (xdrproc_t) xdr_remote_domain_create_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3263
        goto done;
3264

3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278
    /* Need to do a lookup figure out ID of newly started guest, because
     * bug in design of REMOTE_PROC_DOMAIN_CREATE means we aren't getting
     * it returned.
     */
    memcpy (args2.uuid, domain->uuid, VIR_UUID_BUFLEN);
    memset (&ret2, 0, sizeof ret2);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID,
              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, (char *) &args2,
              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2) == -1)
        goto done;

    domain->id = ret2.dom.id;
    xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2);

3279 3280 3281
    rv = 0;

done:
3282
    remoteDriverUnlock(priv);
3283
    return rv;
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 3314 3315 3316 3317
static int
remoteDomainCreateWithFlags (virDomainPtr domain, unsigned int flags)
{
    int rv = -1;
    remote_domain_create_with_flags_args args;
    remote_domain_create_with_flags_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS,
              (xdrproc_t) xdr_remote_domain_create_with_flags_args,
              (char *) &args,
              (xdrproc_t) xdr_remote_domain_create_with_flags_ret,
              (char *) &ret) == -1)
        goto done;

    domain->id = ret.dom.id;
    xdr_free ((xdrproc_t) &xdr_remote_domain_create_with_flags_ret,
              (char *) &ret);

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

3318 3319 3320
static virDomainPtr
remoteDomainDefineXML (virConnectPtr conn, const char *xml)
{
3321
    virDomainPtr dom = NULL;
3322 3323
    remote_domain_define_xml_args args;
    remote_domain_define_xml_ret ret;
3324
    struct private_data *priv = conn->privateData;
3325

3326 3327
    remoteDriverLock(priv);

3328 3329 3330 3331 3332 3333
    args.xml = (char *) xml;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_DEFINE_XML,
              (xdrproc_t) xdr_remote_domain_define_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_define_xml_ret, (char *) &ret) == -1)
3334
        goto done;
3335 3336 3337 3338

    dom = get_nonnull_domain (conn, ret.dom);
    xdr_free ((xdrproc_t) xdr_remote_domain_define_xml_ret, (char *) &ret);

3339
done:
3340
    remoteDriverUnlock(priv);
3341 3342 3343 3344 3345 3346
    return dom;
}

static int
remoteDomainUndefine (virDomainPtr domain)
{
3347
    int rv = -1;
3348
    remote_domain_undefine_args args;
3349
    struct private_data *priv = domain->conn->privateData;
3350

3351 3352
    remoteDriverLock(priv);

3353 3354 3355 3356 3357
    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_UNDEFINE,
              (xdrproc_t) xdr_remote_domain_undefine_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3358
        goto done;
3359

3360 3361 3362
    rv = 0;

done:
3363
    remoteDriverUnlock(priv);
3364
    return rv;
3365 3366 3367
}

static int
3368
remoteDomainAttachDevice (virDomainPtr domain, const char *xml)
3369
{
3370
    int rv = -1;
3371
    remote_domain_attach_device_args args;
3372
    struct private_data *priv = domain->conn->privateData;
3373

3374 3375
    remoteDriverLock(priv);

3376
    make_nonnull_domain (&args.dom, domain);
3377
    args.xml = (char *) xml;
3378 3379 3380 3381

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE,
              (xdrproc_t) xdr_remote_domain_attach_device_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3382
        goto done;
3383

3384 3385 3386
    rv = 0;

done:
3387
    remoteDriverUnlock(priv);
3388
    return rv;
3389 3390
}

J
Jim Fehlig 已提交
3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416
static int
remoteDomainAttachDeviceFlags (virDomainPtr domain, const char *xml,
                               unsigned int flags)
{
    int rv = -1;
    remote_domain_attach_device_flags_args args;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.xml = (char *) xml;
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_ATTACH_DEVICE_FLAGS,
              (xdrproc_t) xdr_remote_domain_attach_device_flags_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

3417
static int
3418
remoteDomainDetachDevice (virDomainPtr domain, const char *xml)
3419
{
3420
    int rv = -1;
3421
    remote_domain_detach_device_args args;
3422
    struct private_data *priv = domain->conn->privateData;
3423

3424 3425
    remoteDriverLock(priv);

3426
    make_nonnull_domain (&args.dom, domain);
3427
    args.xml = (char *) xml;
3428 3429 3430 3431

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE,
              (xdrproc_t) xdr_remote_domain_detach_device_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3432
        goto done;
3433

3434 3435 3436
    rv = 0;

done:
3437
    remoteDriverUnlock(priv);
3438
    return rv;
3439 3440
}

J
Jim Fehlig 已提交
3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466
static int
remoteDomainDetachDeviceFlags (virDomainPtr domain, const char *xml,
                               unsigned int flags)
{
    int rv = -1;
    remote_domain_detach_device_flags_args args;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.xml = (char *) xml;
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_DETACH_DEVICE_FLAGS,
              (xdrproc_t) xdr_remote_domain_detach_device_flags_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492
static int
remoteDomainUpdateDeviceFlags (virDomainPtr domain, const char *xml,
                               unsigned int flags)
{
    int rv = -1;
    remote_domain_update_device_flags_args args;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.xml = (char *) xml;
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_UPDATE_DEVICE_FLAGS,
              (xdrproc_t) xdr_remote_domain_update_device_flags_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

3493 3494 3495
static int
remoteDomainGetAutostart (virDomainPtr domain, int *autostart)
{
3496
    int rv = -1;
3497 3498
    remote_domain_get_autostart_args args;
    remote_domain_get_autostart_ret ret;
3499
    struct private_data *priv = domain->conn->privateData;
3500

3501 3502
    remoteDriverLock(priv);

3503 3504 3505 3506 3507 3508
    make_nonnull_domain (&args.dom, domain);

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_AUTOSTART,
              (xdrproc_t) xdr_remote_domain_get_autostart_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_autostart_ret, (char *) &ret) == -1)
3509
        goto done;
3510 3511

    if (autostart) *autostart = ret.autostart;
3512 3513 3514
    rv = 0;

done:
3515
    remoteDriverUnlock(priv);
3516
    return rv;
3517 3518 3519 3520 3521
}

static int
remoteDomainSetAutostart (virDomainPtr domain, int autostart)
{
3522
    int rv = -1;
3523
    remote_domain_set_autostart_args args;
3524
    struct private_data *priv = domain->conn->privateData;
3525

3526 3527
    remoteDriverLock(priv);

3528 3529 3530 3531 3532 3533
    make_nonnull_domain (&args.dom, domain);
    args.autostart = autostart;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_AUTOSTART,
              (xdrproc_t) xdr_remote_domain_set_autostart_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3534
        goto done;
3535

3536 3537 3538
    rv = 0;

done:
3539
    remoteDriverUnlock(priv);
3540
    return rv;
3541 3542
}

3543 3544 3545
static char *
remoteDomainGetSchedulerType (virDomainPtr domain, int *nparams)
{
3546
    char *rv = NULL;
3547 3548
    remote_domain_get_scheduler_type_args args;
    remote_domain_get_scheduler_type_ret ret;
3549
    struct private_data *priv = domain->conn->privateData;
3550

3551 3552
    remoteDriverLock(priv);

3553 3554 3555 3556 3557 3558
    make_nonnull_domain (&args.dom, domain);

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE,
              (xdrproc_t) xdr_remote_domain_get_scheduler_type_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_scheduler_type_ret, (char *) &ret) == -1)
3559
        goto done;
3560 3561 3562 3563

    if (nparams) *nparams = ret.nparams;

    /* Caller frees this. */
3564 3565 3566
    rv = ret.type;

done:
3567
    remoteDriverUnlock(priv);
3568
    return rv;
3569 3570 3571 3572 3573 3574
}

static int
remoteDomainGetSchedulerParameters (virDomainPtr domain,
                                    virSchedParameterPtr params, int *nparams)
{
3575
    int rv = -1;
3576 3577
    remote_domain_get_scheduler_parameters_args args;
    remote_domain_get_scheduler_parameters_ret ret;
3578
    int i = -1;
3579
    struct private_data *priv = domain->conn->privateData;
3580

3581 3582
    remoteDriverLock(priv);

3583 3584 3585 3586 3587 3588 3589
    make_nonnull_domain (&args.dom, domain);
    args.nparams = *nparams;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS,
              (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret, (char *) &ret) == -1)
3590
        goto done;
3591 3592 3593 3594

    /* Check the length of the returned list carefully. */
    if (ret.params.params_len > REMOTE_DOMAIN_SCHEDULER_PARAMETERS_MAX ||
        ret.params.params_len > *nparams) {
3595 3596 3597
        remoteError(VIR_ERR_RPC, "%s",
                    _("remoteDomainGetSchedulerParameters: "
                      "returned number of parameters exceeds limit"));
3598
        goto cleanup;
3599 3600 3601 3602 3603
    }
    *nparams = ret.params.params_len;

    /* Deserialise the result. */
    for (i = 0; i < *nparams; ++i) {
C
Chris Lalancette 已提交
3604
        if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) {
3605 3606 3607
            remoteError(VIR_ERR_INTERNAL_ERROR,
                        _("Parameter %s too big for destination"),
                        ret.params.params_val[i].field);
C
Chris Lalancette 已提交
3608 3609
            goto cleanup;
        }
3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624
        params[i].type = ret.params.params_val[i].value.type;
        switch (params[i].type) {
        case VIR_DOMAIN_SCHED_FIELD_INT:
            params[i].value.i = ret.params.params_val[i].value.remote_sched_param_value_u.i; break;
        case VIR_DOMAIN_SCHED_FIELD_UINT:
            params[i].value.ui = ret.params.params_val[i].value.remote_sched_param_value_u.ui; break;
        case VIR_DOMAIN_SCHED_FIELD_LLONG:
            params[i].value.l = ret.params.params_val[i].value.remote_sched_param_value_u.l; break;
        case VIR_DOMAIN_SCHED_FIELD_ULLONG:
            params[i].value.ul = ret.params.params_val[i].value.remote_sched_param_value_u.ul; break;
        case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
            params[i].value.d = ret.params.params_val[i].value.remote_sched_param_value_u.d; break;
        case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
            params[i].value.b = ret.params.params_val[i].value.remote_sched_param_value_u.b; break;
        default:
3625 3626 3627
            remoteError(VIR_ERR_RPC, "%s",
                        _("remoteDomainGetSchedulerParameters: "
                          "unknown parameter type"));
3628
            goto cleanup;
3629 3630 3631
        }
    }

3632 3633 3634
    rv = 0;

cleanup:
3635
    xdr_free ((xdrproc_t) xdr_remote_domain_get_scheduler_parameters_ret, (char *) &ret);
3636
done:
3637
    remoteDriverUnlock(priv);
3638
    return rv;
3639 3640 3641 3642 3643 3644
}

static int
remoteDomainSetSchedulerParameters (virDomainPtr domain,
                                    virSchedParameterPtr params, int nparams)
{
3645
    int rv = -1;
3646 3647
    remote_domain_set_scheduler_parameters_args args;
    int i, do_error;
3648
    struct private_data *priv = domain->conn->privateData;
3649

3650 3651
    remoteDriverLock(priv);

3652 3653 3654 3655
    make_nonnull_domain (&args.dom, domain);

    /* Serialise the scheduler parameters. */
    args.params.params_len = nparams;
3656
    if (VIR_ALLOC_N(args.params.params_val, nparams) < 0) {
3657
        virReportOOMError();
3658
        goto done;
3659 3660 3661 3662 3663 3664 3665
    }

    do_error = 0;
    for (i = 0; i < nparams; ++i) {
        // call() will free this:
        args.params.params_val[i].field = strdup (params[i].field);
        if (args.params.params_val[i].field == NULL) {
3666
            virReportOOMError();
3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683
            do_error = 1;
        }
        args.params.params_val[i].value.type = params[i].type;
        switch (params[i].type) {
        case VIR_DOMAIN_SCHED_FIELD_INT:
            args.params.params_val[i].value.remote_sched_param_value_u.i = params[i].value.i; break;
        case VIR_DOMAIN_SCHED_FIELD_UINT:
            args.params.params_val[i].value.remote_sched_param_value_u.ui = params[i].value.ui; break;
        case VIR_DOMAIN_SCHED_FIELD_LLONG:
            args.params.params_val[i].value.remote_sched_param_value_u.l = params[i].value.l; break;
        case VIR_DOMAIN_SCHED_FIELD_ULLONG:
            args.params.params_val[i].value.remote_sched_param_value_u.ul = params[i].value.ul; break;
        case VIR_DOMAIN_SCHED_FIELD_DOUBLE:
            args.params.params_val[i].value.remote_sched_param_value_u.d = params[i].value.d; break;
        case VIR_DOMAIN_SCHED_FIELD_BOOLEAN:
            args.params.params_val[i].value.remote_sched_param_value_u.b = params[i].value.b; break;
        default:
3684
            remoteError(VIR_ERR_RPC, "%s", _("unknown parameter type"));
3685 3686 3687 3688 3689 3690
            do_error = 1;
        }
    }

    if (do_error) {
        xdr_free ((xdrproc_t) xdr_remote_domain_set_scheduler_parameters_args, (char *) &args);
3691
        goto done;
3692 3693 3694 3695 3696
    }

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS,
              (xdrproc_t) xdr_remote_domain_set_scheduler_parameters_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3697
        goto done;
3698

3699 3700 3701
    rv = 0;

done:
3702
    remoteDriverUnlock(priv);
3703
    return rv;
3704 3705
}

3706 3707 3708 3709
static int
remoteDomainBlockStats (virDomainPtr domain, const char *path,
                        struct _virDomainBlockStats *stats)
{
3710
    int rv = -1;
3711 3712
    remote_domain_block_stats_args args;
    remote_domain_block_stats_ret ret;
3713
    struct private_data *priv = domain->conn->privateData;
3714

3715 3716
    remoteDriverLock(priv);

3717 3718 3719 3720 3721 3722 3723 3724
    make_nonnull_domain (&args.dom, domain);
    args.path = (char *) path;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS,
              (xdrproc_t) xdr_remote_domain_block_stats_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_block_stats_ret, (char *) &ret)
        == -1)
3725
        goto done;
3726 3727 3728 3729 3730 3731 3732

    stats->rd_req = ret.rd_req;
    stats->rd_bytes = ret.rd_bytes;
    stats->wr_req = ret.wr_req;
    stats->wr_bytes = ret.wr_bytes;
    stats->errs = ret.errs;

3733 3734 3735
    rv = 0;

done:
3736
    remoteDriverUnlock(priv);
3737
    return rv;
3738 3739 3740 3741 3742 3743
}

static int
remoteDomainInterfaceStats (virDomainPtr domain, const char *path,
                            struct _virDomainInterfaceStats *stats)
{
3744
    int rv = -1;
3745 3746
    remote_domain_interface_stats_args args;
    remote_domain_interface_stats_ret ret;
3747
    struct private_data *priv = domain->conn->privateData;
3748

3749 3750
    remoteDriverLock(priv);

3751 3752 3753 3754 3755 3756 3757 3758 3759
    make_nonnull_domain (&args.dom, domain);
    args.path = (char *) path;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACE_STATS,
              (xdrproc_t) xdr_remote_domain_interface_stats_args,
                (char *) &args,
              (xdrproc_t) xdr_remote_domain_interface_stats_ret,
                (char *) &ret) == -1)
3760
        goto done;
3761 3762 3763 3764 3765 3766 3767 3768 3769 3770

    stats->rx_bytes = ret.rx_bytes;
    stats->rx_packets = ret.rx_packets;
    stats->rx_errs = ret.rx_errs;
    stats->rx_drop = ret.rx_drop;
    stats->tx_bytes = ret.tx_bytes;
    stats->tx_packets = ret.tx_packets;
    stats->tx_errs = ret.tx_errs;
    stats->tx_drop = ret.tx_drop;

3771 3772 3773
    rv = 0;

done:
3774
    remoteDriverUnlock(priv);
3775
    return rv;
3776 3777
}

3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792
static int
remoteDomainMemoryStats (virDomainPtr domain,
                         struct _virDomainMemoryStat *stats,
                         unsigned int nr_stats)
{
    int rv = -1;
    remote_domain_memory_stats_args args;
    remote_domain_memory_stats_ret ret;
    struct private_data *priv = domain->conn->privateData;
    unsigned int i;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    if (nr_stats > REMOTE_DOMAIN_MEMORY_STATS_MAX) {
3793 3794 3795
        remoteError(VIR_ERR_RPC,
                    _("too many memory stats requested: %d > %d"), nr_stats,
                    REMOTE_DOMAIN_MEMORY_STATS_MAX);
3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820
        goto done;
    }
    args.maxStats = nr_stats;
    args.flags = 0;
    memset (&ret, 0, sizeof ret);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MEMORY_STATS,
              (xdrproc_t) xdr_remote_domain_memory_stats_args,
                (char *) &args,
              (xdrproc_t) xdr_remote_domain_memory_stats_ret,
                (char *) &ret) == -1)
        goto done;

    for (i = 0; i < ret.stats.stats_len; i++) {
        stats[i].tag = ret.stats.stats_val[i].tag;
        stats[i].val = ret.stats.stats_val[i].val;
    }
    rv = ret.stats.stats_len;
    xdr_free((xdrproc_t) xdr_remote_domain_memory_stats_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

3821 3822 3823 3824 3825 3826 3827 3828
static int
remoteDomainBlockPeek (virDomainPtr domain,
                       const char *path,
                       unsigned long long offset,
                       size_t size,
                       void *buffer,
                       unsigned int flags)
{
3829
    int rv = -1;
3830 3831
    remote_domain_block_peek_args args;
    remote_domain_block_peek_ret ret;
3832
    struct private_data *priv = domain->conn->privateData;
3833

3834 3835
    remoteDriverLock(priv);

3836
    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
3837 3838 3839
        remoteError(VIR_ERR_RPC,
                    _("block peek request too large for remote protocol, %zi > %d"),
                    size, REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX);
3840
        goto done;
3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854
    }

    make_nonnull_domain (&args.dom, domain);
    args.path = (char *) path;
    args.offset = offset;
    args.size = size;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_PEEK,
              (xdrproc_t) xdr_remote_domain_block_peek_args,
                (char *) &args,
              (xdrproc_t) xdr_remote_domain_block_peek_ret,
                (char *) &ret) == -1)
3855
        goto done;
3856 3857

    if (ret.buffer.buffer_len != size) {
3858 3859
        remoteError(VIR_ERR_RPC, "%s",
                    _("returned buffer is not same size as requested"));
3860
        goto cleanup;
3861 3862 3863
    }

    memcpy (buffer, ret.buffer.buffer_val, size);
3864 3865 3866
    rv = 0;

cleanup:
3867
    VIR_FREE(ret.buffer.buffer_val);
3868

3869
done:
3870
    remoteDriverUnlock(priv);
3871
    return rv;
3872 3873
}

R
Richard W.M. Jones 已提交
3874 3875 3876 3877 3878 3879 3880
static int
remoteDomainMemoryPeek (virDomainPtr domain,
                        unsigned long long offset,
                        size_t size,
                        void *buffer,
                        unsigned int flags)
{
3881
    int rv = -1;
R
Richard W.M. Jones 已提交
3882 3883
    remote_domain_memory_peek_args args;
    remote_domain_memory_peek_ret ret;
3884
    struct private_data *priv = domain->conn->privateData;
R
Richard W.M. Jones 已提交
3885

3886 3887
    remoteDriverLock(priv);

R
Richard W.M. Jones 已提交
3888
    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
3889 3890 3891
        remoteError(VIR_ERR_RPC,
                    _("memory peek request too large for remote protocol, %zi > %d"),
                    size, REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX);
3892
        goto done;
R
Richard W.M. Jones 已提交
3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905
    }

    make_nonnull_domain (&args.dom, domain);
    args.offset = offset;
    args.size = size;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MEMORY_PEEK,
              (xdrproc_t) xdr_remote_domain_memory_peek_args,
                (char *) &args,
              (xdrproc_t) xdr_remote_domain_memory_peek_ret,
                (char *) &ret) == -1)
3906
        goto done;
R
Richard W.M. Jones 已提交
3907 3908

    if (ret.buffer.buffer_len != size) {
3909 3910
        remoteError(VIR_ERR_RPC, "%s",
                    _("returned buffer is not same size as requested"));
3911
        goto cleanup;
R
Richard W.M. Jones 已提交
3912 3913 3914
    }

    memcpy (buffer, ret.buffer.buffer_val, size);
3915 3916 3917
    rv = 0;

cleanup:
3918
    VIR_FREE(ret.buffer.buffer_val);
R
Richard W.M. Jones 已提交
3919

3920
done:
3921
    remoteDriverUnlock(priv);
3922
    return rv;
R
Richard W.M. Jones 已提交
3923 3924
}

3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958
static int
remoteDomainGetBlockInfo (virDomainPtr domain,
                          const char *path,
                          virDomainBlockInfoPtr info,
                          unsigned int flags)
{
    int rv = -1;
    remote_domain_get_block_info_args args;
    remote_domain_get_block_info_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.path = (char*)path;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_INFO,
              (xdrproc_t) xdr_remote_domain_get_block_info_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_block_info_ret, (char *) &ret) == -1)
        goto done;

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

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031
static int
remoteDomainManagedSave (virDomainPtr domain, unsigned int flags)
{
    int rv = -1;
    remote_domain_managed_save_args args;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE,
              (xdrproc_t) xdr_remote_domain_managed_save_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainHasManagedSaveImage (virDomainPtr domain, unsigned int flags)
{
    int rv = -1;
    remote_domain_has_managed_save_image_args args;
    remote_domain_has_managed_save_image_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_MANAGED_SAVE_IMAGE,
              (xdrproc_t) xdr_remote_domain_has_managed_save_image_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_has_managed_save_image_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.ret;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteDomainManagedSaveRemove (virDomainPtr domain, unsigned int flags)
{
    int rv = -1;
    remote_domain_managed_save_remove_args args;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);
    args.flags = flags;

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MANAGED_SAVE_REMOVE,
              (xdrproc_t) xdr_remote_domain_managed_save_remove_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

4032 4033
/*----------------------------------------------------------------------*/

J
Jim Meyering 已提交
4034
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
4035
remoteNetworkOpen (virConnectPtr conn,
4036
                   virConnectAuthPtr auth,
4037
                   int flags)
4038
{
4039 4040 4041
    if (inside_daemon)
        return VIR_DRV_OPEN_DECLINED;

J
Jim Meyering 已提交
4042
    if (conn->driver &&
4043
        STREQ (conn->driver->name, "remote")) {
4044 4045 4046
        struct private_data *priv;

       /* If we're here, the remote driver is already
4047 4048 4049
         * in use due to a) a QEMU uri, or b) a remote
         * URI. So we can re-use existing connection
         */
4050 4051 4052 4053 4054
        priv = conn->privateData;
        remoteDriverLock(priv);
        priv->localUses++;
        conn->networkPrivateData = priv;
        remoteDriverUnlock(priv);
4055
        return VIR_DRV_OPEN_SUCCESS;
4056 4057 4058
    } else {
        /* Using a non-remote driver, so we need to open a
         * new connection for network APIs, forcing it to
4059 4060
         * use the UNIX transport. This handles Xen driver
         * which doesn't have its own impl of the network APIs.
4061
         */
4062
        struct private_data *priv;
4063 4064 4065 4066 4067 4068
        int ret;
        ret = remoteOpenSecondaryDriver(conn,
                                        auth,
                                        flags,
                                        &priv);
        if (ret == VIR_DRV_OPEN_SUCCESS)
4069 4070 4071
            conn->networkPrivateData = priv;
        return ret;
    }
4072 4073 4074
}

static int
4075 4076
remoteNetworkClose (virConnectPtr conn)
{
4077
    int rv = 0;
4078 4079
    struct private_data *priv = conn->networkPrivateData;

4080 4081 4082 4083 4084 4085 4086 4087
    remoteDriverLock(priv);
    priv->localUses--;
    if (!priv->localUses) {
        rv = doRemoteClose(conn, priv);
        conn->networkPrivateData = NULL;
        remoteDriverUnlock(priv);
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
4088
    }
4089 4090
    if (priv)
        remoteDriverUnlock(priv);
4091
    return rv;
4092 4093 4094 4095 4096
}

static int
remoteNumOfNetworks (virConnectPtr conn)
{
4097
    int rv = -1;
4098
    remote_num_of_networks_ret ret;
4099
    struct private_data *priv = conn->networkPrivateData;
4100

4101 4102
    remoteDriverLock(priv);

4103 4104 4105 4106
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NETWORKS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_networks_ret, (char *) &ret) == -1)
4107 4108 4109
        goto done;

    rv = ret.num;
4110

4111
done:
4112
    remoteDriverUnlock(priv);
4113
    return rv;
4114 4115 4116 4117 4118
}

static int
remoteListNetworks (virConnectPtr conn, char **const names, int maxnames)
{
4119
    int rv = -1;
4120 4121 4122
    int i;
    remote_list_networks_args args;
    remote_list_networks_ret ret;
4123
    struct private_data *priv = conn->networkPrivateData;
4124

4125 4126
    remoteDriverLock(priv);

4127
    if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
4128 4129 4130
        remoteError(VIR_ERR_RPC,
                    _("too many remote networks: %d > %d"),
                    maxnames, REMOTE_NETWORK_NAME_LIST_MAX);
4131
        goto done;
4132 4133 4134 4135 4136 4137 4138
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_NETWORKS,
              (xdrproc_t) xdr_remote_list_networks_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret) == -1)
4139
        goto done;
4140 4141

    if (ret.names.names_len > maxnames) {
4142 4143 4144
        remoteError(VIR_ERR_RPC,
                    _("too many remote networks: %d > %d"),
                    ret.names.names_len, maxnames);
4145
        goto cleanup;
4146 4147 4148 4149 4150 4151 4152
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
4153
    for (i = 0; i < ret.names.names_len; ++i) {
4154 4155
        names[i] = strdup (ret.names.names_val[i]);

4156 4157 4158 4159
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

4160
            virReportOOMError();
4161 4162 4163 4164
            goto cleanup;
        }
    }

4165 4166 4167
    rv = ret.names.names_len;

cleanup:
4168 4169
    xdr_free ((xdrproc_t) xdr_remote_list_networks_ret, (char *) &ret);

4170
done:
4171
    remoteDriverUnlock(priv);
4172
    return rv;
4173 4174 4175 4176 4177
}

static int
remoteNumOfDefinedNetworks (virConnectPtr conn)
{
4178
    int rv = -1;
4179
    remote_num_of_defined_networks_ret ret;
4180
    struct private_data *priv = conn->networkPrivateData;
4181

4182 4183
    remoteDriverLock(priv);

4184 4185 4186 4187
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_NETWORKS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_defined_networks_ret, (char *) &ret) == -1)
4188 4189 4190
        goto done;

    rv = ret.num;
4191

4192
done:
4193
    remoteDriverUnlock(priv);
4194
    return rv;
4195 4196 4197 4198 4199 4200
}

static int
remoteListDefinedNetworks (virConnectPtr conn,
                           char **const names, int maxnames)
{
4201
    int rv = -1;
4202 4203 4204
    int i;
    remote_list_defined_networks_args args;
    remote_list_defined_networks_ret ret;
4205
    struct private_data *priv = conn->networkPrivateData;
4206

4207 4208
    remoteDriverLock(priv);

4209
    if (maxnames > REMOTE_NETWORK_NAME_LIST_MAX) {
4210 4211 4212
        remoteError(VIR_ERR_RPC,
                    _("too many remote networks: %d > %d"),
                    maxnames, REMOTE_NETWORK_NAME_LIST_MAX);
4213
        goto done;
4214 4215 4216 4217 4218 4219 4220
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_NETWORKS,
              (xdrproc_t) xdr_remote_list_defined_networks_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret) == -1)
4221
        goto done;
4222 4223

    if (ret.names.names_len > maxnames) {
4224 4225 4226
        remoteError(VIR_ERR_RPC,
                    _("too many remote networks: %d > %d"),
                    ret.names.names_len, maxnames);
4227
        goto cleanup;
4228 4229 4230 4231 4232 4233 4234
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
4235
    for (i = 0; i < ret.names.names_len; ++i) {
4236 4237
        names[i] = strdup (ret.names.names_val[i]);

4238 4239 4240 4241
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

4242
            virReportOOMError();
4243 4244 4245 4246
            goto cleanup;
        }
    }

4247 4248 4249
    rv = ret.names.names_len;

cleanup:
4250 4251
    xdr_free ((xdrproc_t) xdr_remote_list_defined_networks_ret, (char *) &ret);

4252
done:
4253
    remoteDriverUnlock(priv);
4254
    return rv;
4255 4256 4257 4258 4259 4260
}

static virNetworkPtr
remoteNetworkLookupByUUID (virConnectPtr conn,
                           const unsigned char *uuid)
{
4261
    virNetworkPtr net = NULL;
4262 4263
    remote_network_lookup_by_uuid_args args;
    remote_network_lookup_by_uuid_ret ret;
4264
    struct private_data *priv = conn->networkPrivateData;
4265

4266 4267
    remoteDriverLock(priv);

4268 4269 4270 4271 4272 4273
    memcpy (args.uuid, uuid, VIR_UUID_BUFLEN);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_UUID,
              (xdrproc_t) xdr_remote_network_lookup_by_uuid_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_lookup_by_uuid_ret, (char *) &ret) == -1)
4274
        goto done;
4275 4276 4277 4278

    net = get_nonnull_network (conn, ret.net);
    xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_uuid_ret, (char *) &ret);

4279
done:
4280
    remoteDriverUnlock(priv);
4281 4282 4283 4284 4285 4286 4287
    return net;
}

static virNetworkPtr
remoteNetworkLookupByName (virConnectPtr conn,
                           const char *name)
{
4288
    virNetworkPtr net = NULL;
4289 4290
    remote_network_lookup_by_name_args args;
    remote_network_lookup_by_name_ret ret;
4291
    struct private_data *priv = conn->networkPrivateData;
4292

4293 4294
    remoteDriverLock(priv);

4295 4296 4297 4298 4299 4300
    args.name = (char *) name;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NETWORK_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_network_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_lookup_by_name_ret, (char *) &ret) == -1)
4301
        goto done;
4302 4303 4304 4305

    net = get_nonnull_network (conn, ret.net);
    xdr_free ((xdrproc_t) &xdr_remote_network_lookup_by_name_ret, (char *) &ret);

4306
done:
4307
    remoteDriverUnlock(priv);
4308 4309 4310
    return net;
}

4311 4312 4313 4314 4315 4316
static int
remoteNetworkIsActive(virNetworkPtr network)
{
    int rv = -1;
    remote_network_is_active_args args;
    remote_network_is_active_ret ret;
4317
    struct private_data *priv = network->conn->networkPrivateData;
4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340

    remoteDriverLock(priv);

    make_nonnull_network (&args.net, network);

    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_IS_ACTIVE,
              (xdrproc_t) xdr_remote_network_is_active_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_is_active_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNetworkIsPersistent(virNetworkPtr network)
{
    int rv = -1;
    remote_network_is_persistent_args args;
    remote_network_is_persistent_ret ret;
4341
    struct private_data *priv = network->conn->networkPrivateData;
4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358

    remoteDriverLock(priv);

    make_nonnull_network (&args.net, network);

    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_IS_PERSISTENT,
              (xdrproc_t) xdr_remote_network_is_persistent_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_is_persistent_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.persistent;

done:
    remoteDriverUnlock(priv);
    return rv;
}

4359 4360 4361
static virNetworkPtr
remoteNetworkCreateXML (virConnectPtr conn, const char *xmlDesc)
{
4362
    virNetworkPtr net = NULL;
4363 4364
    remote_network_create_xml_args args;
    remote_network_create_xml_ret ret;
4365
    struct private_data *priv = conn->networkPrivateData;
4366

4367 4368
    remoteDriverLock(priv);

4369 4370 4371 4372 4373 4374
    args.xml = (char *) xmlDesc;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NETWORK_CREATE_XML,
              (xdrproc_t) xdr_remote_network_create_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_create_xml_ret, (char *) &ret) == -1)
4375
        goto done;
4376 4377 4378 4379

    net = get_nonnull_network (conn, ret.net);
    xdr_free ((xdrproc_t) &xdr_remote_network_create_xml_ret, (char *) &ret);

4380
done:
4381
    remoteDriverUnlock(priv);
4382 4383 4384 4385 4386 4387
    return net;
}

static virNetworkPtr
remoteNetworkDefineXML (virConnectPtr conn, const char *xml)
{
4388
    virNetworkPtr net = NULL;
4389 4390
    remote_network_define_xml_args args;
    remote_network_define_xml_ret ret;
4391
    struct private_data *priv = conn->networkPrivateData;
4392

4393 4394
    remoteDriverLock(priv);

4395 4396 4397 4398 4399 4400
    args.xml = (char *) xml;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NETWORK_DEFINE_XML,
              (xdrproc_t) xdr_remote_network_define_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_define_xml_ret, (char *) &ret) == -1)
4401
        goto done;
4402 4403 4404 4405

    net = get_nonnull_network (conn, ret.net);
    xdr_free ((xdrproc_t) &xdr_remote_network_define_xml_ret, (char *) &ret);

4406
done:
4407
    remoteDriverUnlock(priv);
4408 4409 4410 4411 4412 4413
    return net;
}

static int
remoteNetworkUndefine (virNetworkPtr network)
{
4414
    int rv = -1;
4415
    remote_network_undefine_args args;
4416
    struct private_data *priv = network->conn->networkPrivateData;
4417

4418 4419
    remoteDriverLock(priv);

4420 4421 4422 4423 4424
    make_nonnull_network (&args.net, network);

    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_UNDEFINE,
              (xdrproc_t) xdr_remote_network_undefine_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
4425
        goto done;
4426

4427 4428 4429
    rv = 0;

done:
4430
    remoteDriverUnlock(priv);
4431
    return rv;
4432 4433 4434 4435 4436
}

static int
remoteNetworkCreate (virNetworkPtr network)
{
4437
    int rv = -1;
4438
    remote_network_create_args args;
4439
    struct private_data *priv = network->conn->networkPrivateData;
4440

4441 4442
    remoteDriverLock(priv);

4443 4444 4445 4446 4447
    make_nonnull_network (&args.net, network);

    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_CREATE,
              (xdrproc_t) xdr_remote_network_create_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
4448
        goto done;
4449

4450 4451 4452
    rv = 0;

done:
4453
    remoteDriverUnlock(priv);
4454
    return rv;
4455 4456 4457 4458 4459
}

static int
remoteNetworkDestroy (virNetworkPtr network)
{
4460
    int rv = -1;
4461
    remote_network_destroy_args args;
4462
    struct private_data *priv = network->conn->networkPrivateData;
4463

4464 4465
    remoteDriverLock(priv);

4466 4467 4468 4469 4470
    make_nonnull_network (&args.net, network);

    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_DESTROY,
              (xdrproc_t) xdr_remote_network_destroy_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
4471
        goto done;
4472

4473 4474 4475
    rv = 0;

done:
4476
    remoteDriverUnlock(priv);
4477
    return rv;
4478 4479 4480 4481 4482
}

static char *
remoteNetworkDumpXML (virNetworkPtr network, int flags)
{
4483
    char *rv = NULL;
4484 4485
    remote_network_dump_xml_args args;
    remote_network_dump_xml_ret ret;
4486
    struct private_data *priv = network->conn->networkPrivateData;
4487

4488 4489
    remoteDriverLock(priv);

4490 4491 4492 4493 4494 4495 4496
    make_nonnull_network (&args.net, network);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_DUMP_XML,
              (xdrproc_t) xdr_remote_network_dump_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_dump_xml_ret, (char *) &ret) == -1)
4497
        goto done;
4498 4499

    /* Caller frees. */
4500 4501 4502
    rv = ret.xml;

done:
4503
    remoteDriverUnlock(priv);
4504
    return rv;
4505 4506 4507 4508 4509
}

static char *
remoteNetworkGetBridgeName (virNetworkPtr network)
{
4510
    char *rv = NULL;
4511 4512
    remote_network_get_bridge_name_args args;
    remote_network_get_bridge_name_ret ret;
4513
    struct private_data *priv = network->conn->networkPrivateData;
4514

4515 4516
    remoteDriverLock(priv);

4517 4518 4519 4520 4521 4522
    make_nonnull_network (&args.net, network);

    memset (&ret, 0, sizeof ret);
    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_GET_BRIDGE_NAME,
              (xdrproc_t) xdr_remote_network_get_bridge_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_get_bridge_name_ret, (char *) &ret) == -1)
4523
        goto done;
4524 4525

    /* Caller frees. */
4526 4527 4528
    rv = ret.name;

done:
4529
    remoteDriverUnlock(priv);
4530
    return rv;
4531 4532 4533 4534 4535
}

static int
remoteNetworkGetAutostart (virNetworkPtr network, int *autostart)
{
4536
    int rv = -1;
4537 4538
    remote_network_get_autostart_args args;
    remote_network_get_autostart_ret ret;
4539
    struct private_data *priv = network->conn->networkPrivateData;
4540

4541 4542
    remoteDriverLock(priv);

4543 4544 4545 4546 4547 4548
    make_nonnull_network (&args.net, network);

    memset (&ret, 0, sizeof ret);
    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_GET_AUTOSTART,
              (xdrproc_t) xdr_remote_network_get_autostart_args, (char *) &args,
              (xdrproc_t) xdr_remote_network_get_autostart_ret, (char *) &ret) == -1)
4549
        goto done;
4550 4551 4552

    if (autostart) *autostart = ret.autostart;

4553 4554 4555
    rv = 0;

done:
4556
    remoteDriverUnlock(priv);
4557
    return rv;
4558 4559 4560 4561 4562
}

static int
remoteNetworkSetAutostart (virNetworkPtr network, int autostart)
{
4563
    int rv = -1;
4564
    remote_network_set_autostart_args args;
4565
    struct private_data *priv = network->conn->networkPrivateData;
4566

4567 4568
    remoteDriverLock(priv);

4569 4570 4571 4572 4573 4574
    make_nonnull_network (&args.net, network);
    args.autostart = autostart;

    if (call (network->conn, priv, 0, REMOTE_PROC_NETWORK_SET_AUTOSTART,
              (xdrproc_t) xdr_remote_network_set_autostart_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
4575
        goto done;
4576

4577 4578 4579
    rv = 0;

done:
4580
    remoteDriverUnlock(priv);
4581
    return rv;
4582 4583
}

4584 4585 4586



D
Daniel Veillard 已提交
4587 4588
/*----------------------------------------------------------------------*/

J
Jim Meyering 已提交
4589
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
D
Daniel Veillard 已提交
4590
remoteInterfaceOpen (virConnectPtr conn,
J
Jim Meyering 已提交
4591 4592
                     virConnectAuthPtr auth,
                     int flags)
D
Daniel Veillard 已提交
4593 4594 4595 4596
{
    if (inside_daemon)
        return VIR_DRV_OPEN_DECLINED;

J
Jim Meyering 已提交
4597
    if (conn->driver &&
D
Daniel Veillard 已提交
4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682
        STREQ (conn->driver->name, "remote")) {
        struct private_data *priv;

       /* If we're here, the remote driver is already
         * in use due to a) a QEMU uri, or b) a remote
         * URI. So we can re-use existing connection
         */
        priv = conn->privateData;
        remoteDriverLock(priv);
        priv->localUses++;
        conn->interfacePrivateData = priv;
        remoteDriverUnlock(priv);
        return VIR_DRV_OPEN_SUCCESS;
    } else {
        /* Using a non-remote driver, so we need to open a
         * new connection for interface APIs, forcing it to
         * use the UNIX transport. This handles Xen driver
         * which doesn't have its own impl of the interface APIs.
         */
        struct private_data *priv;
        int ret;
        ret = remoteOpenSecondaryDriver(conn,
                                        auth,
                                        flags,
                                        &priv);
        if (ret == VIR_DRV_OPEN_SUCCESS)
            conn->interfacePrivateData = priv;
        return ret;
    }
}

static int
remoteInterfaceClose (virConnectPtr conn)
{
    int rv = 0;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);
    priv->localUses--;
    if (!priv->localUses) {
        rv = doRemoteClose(conn, priv);
        conn->interfacePrivateData = NULL;
        remoteDriverUnlock(priv);
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
    }
    if (priv)
        remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNumOfInterfaces (virConnectPtr conn)
{
    int rv = -1;
    remote_num_of_interfaces_ret ret;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_INTERFACES,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_interfaces_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteListInterfaces (virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    int i;
    remote_list_interfaces_args args;
    remote_list_interfaces_ret ret;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) {
4683 4684 4685
        remoteError(VIR_ERR_RPC,
                    _("too many remote interfaces: %d > %d"),
                    maxnames, REMOTE_INTERFACE_NAME_LIST_MAX);
D
Daniel Veillard 已提交
4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696
        goto done;
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_INTERFACES,
              (xdrproc_t) xdr_remote_list_interfaces_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret) == -1)
        goto done;

    if (ret.names.names_len > maxnames) {
4697 4698 4699
        remoteError(VIR_ERR_RPC,
                    _("too many remote interfaces: %d > %d"),
                    ret.names.names_len, maxnames);
D
Daniel Veillard 已提交
4700 4701 4702 4703 4704 4705 4706 4707
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
4708
    for (i = 0; i < ret.names.names_len; ++i) {
D
Daniel Veillard 已提交
4709 4710
        names[i] = strdup (ret.names.names_val[i]);

4711 4712 4713 4714
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

4715
            virReportOOMError();
4716 4717 4718 4719
            goto cleanup;
        }
    }

D
Daniel Veillard 已提交
4720 4721 4722 4723 4724 4725 4726 4727 4728 4729
    rv = ret.names.names_len;

cleanup:
    xdr_free ((xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763
static int
remoteNumOfDefinedInterfaces (virConnectPtr conn)
{
    int rv = -1;
    remote_num_of_defined_interfaces_ret ret;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_INTERFACES,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_defined_interfaces_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteListDefinedInterfaces (virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    int i;
    remote_list_defined_interfaces_args args;
    remote_list_defined_interfaces_ret ret;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX) {
4764 4765 4766
        remoteError(VIR_ERR_RPC,
                    _("too many remote interfaces: %d > %d"),
                    maxnames, REMOTE_DEFINED_INTERFACE_NAME_LIST_MAX);
4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777
        goto done;
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_INTERFACES,
              (xdrproc_t) xdr_remote_list_defined_interfaces_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_defined_interfaces_ret, (char *) &ret) == -1)
        goto done;

    if (ret.names.names_len > maxnames) {
4778 4779 4780
        remoteError(VIR_ERR_RPC,
                    _("too many remote interfaces: %d > %d"),
                    ret.names.names_len, maxnames);
4781 4782 4783 4784 4785 4786 4787 4788
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
4789
    for (i = 0; i < ret.names.names_len; ++i) {
4790 4791
        names[i] = strdup (ret.names.names_val[i]);

4792 4793 4794 4795
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

4796
            virReportOOMError();
4797 4798 4799 4800
            goto cleanup;
        }
    }

4801 4802 4803 4804 4805 4806 4807 4808 4809 4810
    rv = ret.names.names_len;

cleanup:
    xdr_free ((xdrproc_t) xdr_remote_list_defined_interfaces_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

D
Daniel Veillard 已提交
4811 4812 4813 4814
static virInterfacePtr
remoteInterfaceLookupByName (virConnectPtr conn,
                             const char *name)
{
4815
    virInterfacePtr iface = NULL;
D
Daniel Veillard 已提交
4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829
    remote_interface_lookup_by_name_args args;
    remote_interface_lookup_by_name_ret ret;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);

    args.name = (char *) name;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_interface_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_interface_lookup_by_name_ret, (char *) &ret) == -1)
        goto done;

4830
    iface = get_nonnull_interface (conn, ret.iface);
D
Daniel Veillard 已提交
4831 4832 4833 4834
    xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_name_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
4835
    return iface;
D
Daniel Veillard 已提交
4836 4837 4838 4839 4840 4841
}

static virInterfacePtr
remoteInterfaceLookupByMACString (virConnectPtr conn,
                                  const char *mac)
{
4842
    virInterfacePtr iface = NULL;
D
Daniel Veillard 已提交
4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856
    remote_interface_lookup_by_mac_string_args args;
    remote_interface_lookup_by_mac_string_ret ret;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);

    args.mac = (char *) mac;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING,
              (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args, (char *) &args,
              (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret) == -1)
        goto done;

4857
    iface = get_nonnull_interface (conn, ret.iface);
D
Daniel Veillard 已提交
4858 4859 4860 4861
    xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
4862
    return iface;
D
Daniel Veillard 已提交
4863 4864
}

4865 4866 4867 4868 4869 4870 4871

static int
remoteInterfaceIsActive(virInterfacePtr iface)
{
    int rv = -1;
    remote_interface_is_active_args args;
    remote_interface_is_active_ret ret;
4872
    struct private_data *priv = iface->conn->interfacePrivateData;
4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890

    remoteDriverLock(priv);

    make_nonnull_interface (&args.iface, iface);

    if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_IS_ACTIVE,
              (xdrproc_t) xdr_remote_interface_is_active_args, (char *) &args,
              (xdrproc_t) xdr_remote_interface_is_active_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}


D
Daniel Veillard 已提交
4891
static char *
4892
remoteInterfaceGetXMLDesc (virInterfacePtr iface,
D
Daniel Veillard 已提交
4893 4894 4895 4896 4897
                           unsigned int flags)
{
    char *rv = NULL;
    remote_interface_get_xml_desc_args args;
    remote_interface_get_xml_desc_ret ret;
4898
    struct private_data *priv = iface->conn->interfacePrivateData;
D
Daniel Veillard 已提交
4899 4900 4901

    remoteDriverLock(priv);

4902
    make_nonnull_interface (&args.iface, iface);
D
Daniel Veillard 已提交
4903 4904 4905
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
4906
    if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_GET_XML_DESC,
D
Daniel Veillard 已提交
4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923
              (xdrproc_t) xdr_remote_interface_get_xml_desc_args, (char *) &args,
              (xdrproc_t) xdr_remote_interface_get_xml_desc_ret, (char *) &ret) == -1)
        goto done;

    /* Caller frees. */
    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virInterfacePtr
remoteInterfaceDefineXML (virConnectPtr conn,
                          const char *xmlDesc,
                          unsigned int flags)
{
4924
    virInterfacePtr iface = NULL;
D
Daniel Veillard 已提交
4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939
    remote_interface_define_xml_args args;
    remote_interface_define_xml_ret ret;
    struct private_data *priv = conn->interfacePrivateData;

    remoteDriverLock(priv);

    args.xml = (char *) xmlDesc;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_DEFINE_XML,
              (xdrproc_t) xdr_remote_interface_define_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_interface_define_xml_ret, (char *) &ret) == -1)
        goto done;

4940
    iface = get_nonnull_interface (conn, ret.iface);
D
Daniel Veillard 已提交
4941 4942 4943 4944
    xdr_free ((xdrproc_t) &xdr_remote_interface_define_xml_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
4945
    return iface;
D
Daniel Veillard 已提交
4946 4947 4948
}

static int
4949
remoteInterfaceUndefine (virInterfacePtr iface)
D
Daniel Veillard 已提交
4950 4951 4952
{
    int rv = -1;
    remote_interface_undefine_args args;
4953
    struct private_data *priv = iface->conn->interfacePrivateData;
D
Daniel Veillard 已提交
4954 4955 4956

    remoteDriverLock(priv);

4957
    make_nonnull_interface (&args.iface, iface);
D
Daniel Veillard 已提交
4958

4959
    if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_UNDEFINE,
D
Daniel Veillard 已提交
4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971
              (xdrproc_t) xdr_remote_interface_undefine_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
4972
remoteInterfaceCreate (virInterfacePtr iface,
D
Daniel Veillard 已提交
4973 4974 4975 4976
                       unsigned int flags)
{
    int rv = -1;
    remote_interface_create_args args;
4977
    struct private_data *priv = iface->conn->interfacePrivateData;
D
Daniel Veillard 已提交
4978 4979 4980

    remoteDriverLock(priv);

4981
    make_nonnull_interface (&args.iface, iface);
D
Daniel Veillard 已提交
4982 4983
    args.flags = flags;

4984
    if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_CREATE,
D
Daniel Veillard 已提交
4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996
              (xdrproc_t) xdr_remote_interface_create_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
4997
remoteInterfaceDestroy (virInterfacePtr iface,
D
Daniel Veillard 已提交
4998 4999 5000 5001
                        unsigned int flags)
{
    int rv = -1;
    remote_interface_destroy_args args;
5002
    struct private_data *priv = iface->conn->interfacePrivateData;
D
Daniel Veillard 已提交
5003 5004 5005

    remoteDriverLock(priv);

5006
    make_nonnull_interface (&args.iface, iface);
D
Daniel Veillard 已提交
5007 5008
    args.flags = flags;

5009
    if (call (iface->conn, priv, 0, REMOTE_PROC_INTERFACE_DESTROY,
D
Daniel Veillard 已提交
5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020
              (xdrproc_t) xdr_remote_interface_destroy_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

5021 5022
/*----------------------------------------------------------------------*/

J
Jim Meyering 已提交
5023
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
5024 5025 5026 5027 5028 5029 5030
remoteStorageOpen (virConnectPtr conn,
                   virConnectAuthPtr auth,
                   int flags)
{
    if (inside_daemon)
        return VIR_DRV_OPEN_DECLINED;

J
Jim Meyering 已提交
5031
    if (conn->driver &&
5032
        STREQ (conn->driver->name, "remote")) {
5033
        struct private_data *priv = conn->privateData;
5034 5035 5036 5037
        /* If we're here, the remote driver is already
         * in use due to a) a QEMU uri, or b) a remote
         * URI. So we can re-use existing connection
         */
5038 5039 5040 5041
        remoteDriverLock(priv);
        priv->localUses++;
        conn->storagePrivateData = priv;
        remoteDriverUnlock(priv);
5042 5043 5044
        return VIR_DRV_OPEN_SUCCESS;
    } else if (conn->networkDriver &&
               STREQ (conn->networkDriver->name, "remote")) {
5045 5046 5047 5048 5049
        struct private_data *priv = conn->networkPrivateData;
        remoteDriverLock(priv);
        conn->storagePrivateData = priv;
        priv->localUses++;
        remoteDriverUnlock(priv);
5050 5051 5052 5053 5054 5055 5056
        return VIR_DRV_OPEN_SUCCESS;
    } else {
        /* Using a non-remote driver, so we need to open a
         * new connection for network APIs, forcing it to
         * use the UNIX transport. This handles Xen driver
         * which doesn't have its own impl of the network APIs.
         */
5057
        struct private_data *priv;
5058 5059 5060 5061 5062 5063
        int ret;
        ret = remoteOpenSecondaryDriver(conn,
                                        auth,
                                        flags,
                                        &priv);
        if (ret == VIR_DRV_OPEN_SUCCESS)
5064 5065 5066 5067 5068 5069 5070 5071 5072
            conn->storagePrivateData = priv;
        return ret;
    }
}

static int
remoteStorageClose (virConnectPtr conn)
{
    int ret = 0;
5073 5074
    struct private_data *priv = conn->storagePrivateData;

5075 5076 5077 5078 5079 5080 5081 5082
    remoteDriverLock(priv);
    priv->localUses--;
    if (!priv->localUses) {
        ret = doRemoteClose(conn, priv);
        conn->storagePrivateData = NULL;
        remoteDriverUnlock(priv);
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
5083
    }
5084 5085
    if (priv)
        remoteDriverUnlock(priv);
5086

5087 5088 5089 5090 5091 5092
    return ret;
}

static int
remoteNumOfStoragePools (virConnectPtr conn)
{
5093
    int rv = -1;
5094
    remote_num_of_storage_pools_ret ret;
5095
    struct private_data *priv = conn->storagePrivateData;
5096

5097 5098
    remoteDriverLock(priv);

5099 5100 5101 5102
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_STORAGE_POOLS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_storage_pools_ret, (char *) &ret) == -1)
5103 5104 5105
        goto done;

    rv = ret.num;
5106

5107
done:
5108
    remoteDriverUnlock(priv);
5109
    return rv;
5110 5111 5112 5113 5114
}

static int
remoteListStoragePools (virConnectPtr conn, char **const names, int maxnames)
{
5115
    int rv = -1;
5116 5117 5118
    int i;
    remote_list_storage_pools_args args;
    remote_list_storage_pools_ret ret;
5119
    struct private_data *priv = conn->storagePrivateData;
5120

5121 5122
    remoteDriverLock(priv);

5123
    if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
5124
        remoteError(VIR_ERR_RPC, "%s", _("too many storage pools requested"));
5125
        goto done;
5126 5127 5128 5129 5130 5131 5132
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_STORAGE_POOLS,
              (xdrproc_t) xdr_remote_list_storage_pools_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret) == -1)
5133
        goto done;
5134 5135

    if (ret.names.names_len > maxnames) {
5136
        remoteError(VIR_ERR_RPC, "%s", _("too many storage pools received"));
5137
        goto cleanup;
5138 5139 5140 5141 5142 5143 5144
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
5145
    for (i = 0; i < ret.names.names_len; ++i) {
5146 5147
        names[i] = strdup (ret.names.names_val[i]);

5148 5149 5150 5151
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

5152
            virReportOOMError();
5153 5154 5155 5156
            goto cleanup;
        }
    }

5157 5158 5159
    rv = ret.names.names_len;

cleanup:
5160 5161
    xdr_free ((xdrproc_t) xdr_remote_list_storage_pools_ret, (char *) &ret);

5162
done:
5163
    remoteDriverUnlock(priv);
5164
    return rv;
5165 5166 5167 5168 5169
}

static int
remoteNumOfDefinedStoragePools (virConnectPtr conn)
{
5170
    int rv = -1;
5171
    remote_num_of_defined_storage_pools_ret ret;
5172
    struct private_data *priv = conn->storagePrivateData;
5173

5174 5175
    remoteDriverLock(priv);

5176 5177 5178 5179
    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_DEFINED_STORAGE_POOLS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_defined_storage_pools_ret, (char *) &ret) == -1)
5180
        goto done;
5181

5182 5183 5184
    rv = ret.num;

done:
5185
    remoteDriverUnlock(priv);
5186
    return rv;
5187 5188 5189 5190 5191 5192
}

static int
remoteListDefinedStoragePools (virConnectPtr conn,
                               char **const names, int maxnames)
{
5193
    int rv = -1;
5194 5195 5196
    int i;
    remote_list_defined_storage_pools_args args;
    remote_list_defined_storage_pools_ret ret;
5197
    struct private_data *priv = conn->storagePrivateData;
5198

5199 5200
    remoteDriverLock(priv);

5201
    if (maxnames > REMOTE_STORAGE_POOL_NAME_LIST_MAX) {
5202
        remoteError(VIR_ERR_RPC, "%s", _("too many storage pools requested"));
5203
        goto done;
5204 5205 5206 5207 5208 5209 5210
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_DEFINED_STORAGE_POOLS,
              (xdrproc_t) xdr_remote_list_defined_storage_pools_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret) == -1)
5211
        goto done;
5212 5213

    if (ret.names.names_len > maxnames) {
5214
        remoteError(VIR_ERR_RPC, "%s", _("too many storage pools received"));
5215
        goto cleanup;
5216 5217 5218 5219 5220 5221 5222
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
5223
    for (i = 0; i < ret.names.names_len; ++i) {
5224 5225
        names[i] = strdup (ret.names.names_val[i]);

5226 5227 5228 5229
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

5230
            virReportOOMError();
5231 5232 5233 5234
            goto cleanup;
        }
    }

5235 5236 5237
    rv = ret.names.names_len;

cleanup:
5238 5239
    xdr_free ((xdrproc_t) xdr_remote_list_defined_storage_pools_ret, (char *) &ret);

5240
done:
5241
    remoteDriverUnlock(priv);
5242
    return rv;
5243 5244
}

5245 5246 5247 5248 5249 5250
static char *
remoteFindStoragePoolSources (virConnectPtr conn,
                              const char *type,
                              const char *srcSpec,
                              unsigned int flags)
{
5251
    char *rv = NULL;
5252 5253
    remote_find_storage_pool_sources_args args;
    remote_find_storage_pool_sources_ret ret;
5254
    struct private_data *priv = conn->storagePrivateData;
5255 5256
    const char *emptyString = "";

5257 5258
    remoteDriverLock(priv);

5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277
    args.type = (char*)type;
    /*
     * I'd think the following would work here:
     *    args.srcSpec = (char**)&srcSpec;
     * since srcSpec is a remote_string (not a remote_nonnull_string).
     *
     * But when srcSpec is NULL, this yields:
     *    libvir: Remote error : marshalling args
     *
     * So for now I'm working around this by turning NULL srcSpecs
     * into empty strings.
     */
    args.srcSpec = srcSpec ? (char **)&srcSpec : (char **)&emptyString;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_FIND_STORAGE_POOL_SOURCES,
              (xdrproc_t) xdr_remote_find_storage_pool_sources_args, (char *) &args,
              (xdrproc_t) xdr_remote_find_storage_pool_sources_ret, (char *) &ret) == -1)
5278
        goto done;
5279

5280
    rv = ret.xml;
5281 5282 5283 5284
    ret.xml = NULL; /* To stop xdr_free free'ing it */

    xdr_free ((xdrproc_t) xdr_remote_find_storage_pool_sources_ret, (char *) &ret);

5285
done:
5286
    remoteDriverUnlock(priv);
5287
    return rv;
5288 5289
}

5290 5291 5292 5293
static virStoragePoolPtr
remoteStoragePoolLookupByUUID (virConnectPtr conn,
                               const unsigned char *uuid)
{
5294
    virStoragePoolPtr pool = NULL;
5295 5296
    remote_storage_pool_lookup_by_uuid_args args;
    remote_storage_pool_lookup_by_uuid_ret ret;
5297
    struct private_data *priv = conn->storagePrivateData;
5298

5299 5300
    remoteDriverLock(priv);

5301 5302 5303 5304 5305 5306
    memcpy (args.uuid, uuid, VIR_UUID_BUFLEN);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID,
              (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_lookup_by_uuid_ret, (char *) &ret) == -1)
5307
        goto done;
5308 5309 5310 5311

    pool = get_nonnull_storage_pool (conn, ret.pool);
    xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_uuid_ret, (char *) &ret);

5312
done:
5313
    remoteDriverUnlock(priv);
5314 5315 5316 5317 5318 5319 5320
    return pool;
}

static virStoragePoolPtr
remoteStoragePoolLookupByName (virConnectPtr conn,
                               const char *name)
{
5321
    virStoragePoolPtr pool = NULL;
5322 5323
    remote_storage_pool_lookup_by_name_args args;
    remote_storage_pool_lookup_by_name_ret ret;
5324
    struct private_data *priv = conn->storagePrivateData;
5325

5326 5327
    remoteDriverLock(priv);

5328 5329 5330 5331 5332 5333
    args.name = (char *) name;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_lookup_by_name_ret, (char *) &ret) == -1)
5334
        goto done;
5335 5336 5337 5338

    pool = get_nonnull_storage_pool (conn, ret.pool);
    xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_name_ret, (char *) &ret);

5339
done:
5340
    remoteDriverUnlock(priv);
5341 5342 5343 5344 5345 5346
    return pool;
}

static virStoragePoolPtr
remoteStoragePoolLookupByVolume (virStorageVolPtr vol)
{
5347
    virStoragePoolPtr pool = NULL;
5348 5349
    remote_storage_pool_lookup_by_volume_args args;
    remote_storage_pool_lookup_by_volume_ret ret;
5350
    struct private_data *priv = vol->conn->storagePrivateData;
5351

5352 5353
    remoteDriverLock(priv);

5354 5355 5356 5357 5358 5359
    make_nonnull_storage_vol (&args.vol, vol);

    memset (&ret, 0, sizeof ret);
    if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME,
              (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_lookup_by_volume_ret, (char *) &ret) == -1)
5360
        goto done;
5361 5362 5363 5364

    pool = get_nonnull_storage_pool (vol->conn, ret.pool);
    xdr_free ((xdrproc_t) &xdr_remote_storage_pool_lookup_by_volume_ret, (char *) &ret);

5365
done:
5366
    remoteDriverUnlock(priv);
5367 5368 5369 5370
    return pool;
}


5371 5372 5373 5374 5375 5376
static int
remoteStoragePoolIsActive(virStoragePoolPtr pool)
{
    int rv = -1;
    remote_storage_pool_is_active_args args;
    remote_storage_pool_is_active_ret ret;
5377
    struct private_data *priv = pool->conn->storagePrivateData;
5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400

    remoteDriverLock(priv);

    make_nonnull_storage_pool (&args.pool, pool);

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_ACTIVE,
              (xdrproc_t) xdr_remote_storage_pool_is_active_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_is_active_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.active;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteStoragePoolIsPersistent(virStoragePoolPtr pool)
{
    int rv = -1;
    remote_storage_pool_is_persistent_args args;
    remote_storage_pool_is_persistent_ret ret;
5401
    struct private_data *priv = pool->conn->storagePrivateData;
5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419

    remoteDriverLock(priv);

    make_nonnull_storage_pool (&args.pool, pool);

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT,
              (xdrproc_t) xdr_remote_storage_pool_is_persistent_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_is_persistent_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.persistent;

done:
    remoteDriverUnlock(priv);
    return rv;
}


5420 5421 5422
static virStoragePoolPtr
remoteStoragePoolCreateXML (virConnectPtr conn, const char *xmlDesc, unsigned int flags)
{
5423
    virStoragePoolPtr pool = NULL;
5424 5425
    remote_storage_pool_create_xml_args args;
    remote_storage_pool_create_xml_ret ret;
5426
    struct private_data *priv = conn->storagePrivateData;
5427

5428 5429
    remoteDriverLock(priv);

5430 5431 5432 5433 5434 5435 5436
    args.xml = (char *) xmlDesc;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE_XML,
              (xdrproc_t) xdr_remote_storage_pool_create_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_create_xml_ret, (char *) &ret) == -1)
5437
        goto done;
5438 5439 5440 5441

    pool = get_nonnull_storage_pool (conn, ret.pool);
    xdr_free ((xdrproc_t) &xdr_remote_storage_pool_create_xml_ret, (char *) &ret);

5442
done:
5443
    remoteDriverUnlock(priv);
5444 5445 5446 5447 5448 5449
    return pool;
}

static virStoragePoolPtr
remoteStoragePoolDefineXML (virConnectPtr conn, const char *xml, unsigned int flags)
{
5450
    virStoragePoolPtr pool = NULL;
5451 5452
    remote_storage_pool_define_xml_args args;
    remote_storage_pool_define_xml_ret ret;
5453
    struct private_data *priv = conn->storagePrivateData;
5454

5455 5456
    remoteDriverLock(priv);

5457 5458 5459 5460 5461 5462 5463
    args.xml = (char *) xml;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DEFINE_XML,
              (xdrproc_t) xdr_remote_storage_pool_define_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_define_xml_ret, (char *) &ret) == -1)
5464
        goto done;
5465 5466 5467 5468

    pool = get_nonnull_storage_pool (conn, ret.pool);
    xdr_free ((xdrproc_t) &xdr_remote_storage_pool_define_xml_ret, (char *) &ret);

5469
done:
5470
    remoteDriverUnlock(priv);
5471 5472 5473 5474 5475 5476
    return pool;
}

static int
remoteStoragePoolUndefine (virStoragePoolPtr pool)
{
5477
    int rv = -1;
5478
    remote_storage_pool_undefine_args args;
5479
    struct private_data *priv = pool->conn->storagePrivateData;
5480

5481 5482
    remoteDriverLock(priv);

5483 5484 5485 5486 5487
    make_nonnull_storage_pool (&args.pool, pool);

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_UNDEFINE,
              (xdrproc_t) xdr_remote_storage_pool_undefine_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5488
        goto done;
5489

5490 5491 5492
    rv = 0;

done:
5493
    remoteDriverUnlock(priv);
5494
    return rv;
5495 5496 5497 5498 5499
}

static int
remoteStoragePoolCreate (virStoragePoolPtr pool, unsigned int flags)
{
5500
    int rv = -1;
5501
    remote_storage_pool_create_args args;
5502
    struct private_data *priv = pool->conn->storagePrivateData;
5503

5504 5505
    remoteDriverLock(priv);

5506 5507 5508 5509 5510 5511
    make_nonnull_storage_pool (&args.pool, pool);
    args.flags = flags;

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_CREATE,
              (xdrproc_t) xdr_remote_storage_pool_create_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5512
        goto done;
5513

5514 5515 5516
    rv = 0;

done:
5517
    remoteDriverUnlock(priv);
5518
    return rv;
5519 5520 5521 5522 5523 5524
}

static int
remoteStoragePoolBuild (virStoragePoolPtr pool,
                        unsigned int flags)
{
5525
    int rv = -1;
5526
    remote_storage_pool_build_args args;
5527
    struct private_data *priv = pool->conn->storagePrivateData;
5528

5529 5530
    remoteDriverLock(priv);

5531 5532 5533 5534 5535 5536
    make_nonnull_storage_pool (&args.pool, pool);
    args.flags = flags;

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_BUILD,
              (xdrproc_t) xdr_remote_storage_pool_build_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5537
        goto done;
5538

5539 5540 5541
    rv = 0;

done:
5542
    remoteDriverUnlock(priv);
5543
    return rv;
5544 5545 5546 5547 5548
}

static int
remoteStoragePoolDestroy (virStoragePoolPtr pool)
{
5549
    int rv = -1;
5550
    remote_storage_pool_destroy_args args;
5551
    struct private_data *priv = pool->conn->storagePrivateData;
5552

5553 5554
    remoteDriverLock(priv);

5555 5556 5557 5558 5559
    make_nonnull_storage_pool (&args.pool, pool);

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DESTROY,
              (xdrproc_t) xdr_remote_storage_pool_destroy_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5560
        goto done;
5561

5562 5563 5564
    rv = 0;

done:
5565
    remoteDriverUnlock(priv);
5566
    return rv;
5567 5568 5569 5570 5571 5572
}

static int
remoteStoragePoolDelete (virStoragePoolPtr pool,
                         unsigned int flags)
{
5573
    int rv = -1;
5574
    remote_storage_pool_delete_args args;
5575
    struct private_data *priv = pool->conn->storagePrivateData;
5576

5577 5578
    remoteDriverLock(priv);

5579 5580 5581 5582 5583 5584
    make_nonnull_storage_pool (&args.pool, pool);
    args.flags = flags;

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DELETE,
              (xdrproc_t) xdr_remote_storage_pool_delete_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5585
        goto done;
5586

5587 5588 5589
    rv = 0;

done:
5590
    remoteDriverUnlock(priv);
5591
    return rv;
5592 5593 5594 5595 5596 5597
}

static int
remoteStoragePoolRefresh (virStoragePoolPtr pool,
                          unsigned int flags)
{
5598
    int rv = -1;
5599
    remote_storage_pool_refresh_args args;
5600
    struct private_data *priv = pool->conn->storagePrivateData;
5601

5602 5603
    remoteDriverLock(priv);

5604 5605 5606 5607 5608 5609
    make_nonnull_storage_pool (&args.pool, pool);
    args.flags = flags;

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_REFRESH,
              (xdrproc_t) xdr_remote_storage_pool_refresh_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5610
        goto done;
5611

5612 5613 5614
    rv = 0;

done:
5615
    remoteDriverUnlock(priv);
5616
    return rv;
5617 5618 5619 5620 5621
}

static int
remoteStoragePoolGetInfo (virStoragePoolPtr pool, virStoragePoolInfoPtr info)
{
5622
    int rv = -1;
5623 5624
    remote_storage_pool_get_info_args args;
    remote_storage_pool_get_info_ret ret;
5625
    struct private_data *priv = pool->conn->storagePrivateData;
5626

5627 5628
    remoteDriverLock(priv);

5629 5630 5631 5632 5633 5634
    make_nonnull_storage_pool (&args.pool, pool);

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_INFO,
              (xdrproc_t) xdr_remote_storage_pool_get_info_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_get_info_ret, (char *) &ret) == -1)
5635
        goto done;
5636 5637 5638 5639 5640 5641

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

5642 5643 5644
    rv = 0;

done:
5645
    remoteDriverUnlock(priv);
5646
    return rv;
5647 5648 5649 5650 5651 5652
}

static char *
remoteStoragePoolDumpXML (virStoragePoolPtr pool,
                          unsigned int flags)
{
5653
    char *rv = NULL;
5654 5655
    remote_storage_pool_dump_xml_args args;
    remote_storage_pool_dump_xml_ret ret;
5656
    struct private_data *priv = pool->conn->storagePrivateData;
5657

5658 5659
    remoteDriverLock(priv);

5660 5661 5662 5663 5664 5665 5666
    make_nonnull_storage_pool (&args.pool, pool);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_DUMP_XML,
              (xdrproc_t) xdr_remote_storage_pool_dump_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_dump_xml_ret, (char *) &ret) == -1)
5667
        goto done;
5668 5669

    /* Caller frees. */
5670 5671 5672
    rv = ret.xml;

done:
5673
    remoteDriverUnlock(priv);
5674
    return rv;
5675 5676 5677 5678 5679
}

static int
remoteStoragePoolGetAutostart (virStoragePoolPtr pool, int *autostart)
{
5680
    int rv = -1;
5681 5682
    remote_storage_pool_get_autostart_args args;
    remote_storage_pool_get_autostart_ret ret;
5683
    struct private_data *priv = pool->conn->storagePrivateData;
5684

5685 5686
    remoteDriverLock(priv);

5687 5688 5689 5690 5691 5692
    make_nonnull_storage_pool (&args.pool, pool);

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART,
              (xdrproc_t) xdr_remote_storage_pool_get_autostart_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_get_autostart_ret, (char *) &ret) == -1)
5693
        goto done;
5694 5695 5696

    if (autostart) *autostart = ret.autostart;

5697 5698 5699
    rv = 0;

done:
5700
    remoteDriverUnlock(priv);
5701
    return rv;
5702 5703 5704 5705 5706
}

static int
remoteStoragePoolSetAutostart (virStoragePoolPtr pool, int autostart)
{
5707
    int rv = -1;
5708
    remote_storage_pool_set_autostart_args args;
5709
    struct private_data *priv = pool->conn->storagePrivateData;
5710

5711 5712
    remoteDriverLock(priv);

5713 5714 5715 5716 5717 5718
    make_nonnull_storage_pool (&args.pool, pool);
    args.autostart = autostart;

    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART,
              (xdrproc_t) xdr_remote_storage_pool_set_autostart_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5719
        goto done;
5720

5721 5722 5723
    rv = 0;

done:
5724
    remoteDriverUnlock(priv);
5725
    return rv;
5726 5727 5728 5729 5730 5731
}


static int
remoteStoragePoolNumOfVolumes (virStoragePoolPtr pool)
{
5732
    int rv = -1;
5733 5734
    remote_storage_pool_num_of_volumes_args args;
    remote_storage_pool_num_of_volumes_ret ret;
5735
    struct private_data *priv = pool->conn->storagePrivateData;
5736

5737 5738
    remoteDriverLock(priv);

5739 5740 5741 5742 5743 5744
    make_nonnull_storage_pool(&args.pool, pool);

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES,
              (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_num_of_volumes_ret, (char *) &ret) == -1)
5745 5746 5747
        goto done;

    rv = ret.num;
5748

5749
done:
5750
    remoteDriverUnlock(priv);
5751
    return rv;
5752 5753 5754 5755 5756
}

static int
remoteStoragePoolListVolumes (virStoragePoolPtr pool, char **const names, int maxnames)
{
5757
    int rv = -1;
5758 5759 5760
    int i;
    remote_storage_pool_list_volumes_args args;
    remote_storage_pool_list_volumes_ret ret;
5761
    struct private_data *priv = pool->conn->storagePrivateData;
5762

5763 5764
    remoteDriverLock(priv);

5765
    if (maxnames > REMOTE_STORAGE_VOL_NAME_LIST_MAX) {
5766
        remoteError(VIR_ERR_RPC, "%s", _("too many storage volumes requested"));
5767
        goto done;
5768 5769 5770 5771 5772 5773 5774 5775
    }
    args.maxnames = maxnames;
    make_nonnull_storage_pool(&args.pool, pool);

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES,
              (xdrproc_t) xdr_remote_storage_pool_list_volumes_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret) == -1)
5776
        goto done;
5777 5778

    if (ret.names.names_len > maxnames) {
5779
        remoteError(VIR_ERR_RPC, "%s", _("too many storage volumes received"));
5780
        goto cleanup;
5781 5782 5783 5784 5785 5786 5787
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
5788
    for (i = 0; i < ret.names.names_len; ++i) {
5789 5790
        names[i] = strdup (ret.names.names_val[i]);

5791 5792 5793 5794
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

5795
            virReportOOMError();
5796 5797 5798 5799
            goto cleanup;
        }
    }

5800 5801 5802
    rv = ret.names.names_len;

cleanup:
5803 5804
    xdr_free ((xdrproc_t) xdr_remote_storage_pool_list_volumes_ret, (char *) &ret);

5805
done:
5806
    remoteDriverUnlock(priv);
5807
    return rv;
5808 5809 5810 5811 5812 5813 5814 5815
}



static virStorageVolPtr
remoteStorageVolLookupByName (virStoragePoolPtr pool,
                              const char *name)
{
5816
    virStorageVolPtr vol = NULL;
5817 5818
    remote_storage_vol_lookup_by_name_args args;
    remote_storage_vol_lookup_by_name_ret ret;
5819
    struct private_data *priv = pool->conn->storagePrivateData;
5820

5821 5822
    remoteDriverLock(priv);

5823 5824 5825 5826 5827 5828 5829
    make_nonnull_storage_pool(&args.pool, pool);
    args.name = (char *) name;

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_lookup_by_name_ret, (char *) &ret) == -1)
5830
        goto done;
5831 5832 5833 5834

    vol = get_nonnull_storage_vol (pool->conn, ret.vol);
    xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_name_ret, (char *) &ret);

5835
done:
5836
    remoteDriverUnlock(priv);
5837 5838 5839 5840 5841 5842 5843
    return vol;
}

static virStorageVolPtr
remoteStorageVolLookupByKey (virConnectPtr conn,
                             const char *key)
{
5844
    virStorageVolPtr  vol = NULL;
5845 5846
    remote_storage_vol_lookup_by_key_args args;
    remote_storage_vol_lookup_by_key_ret ret;
5847
    struct private_data *priv = conn->storagePrivateData;
5848

5849 5850
    remoteDriverLock(priv);

5851 5852 5853 5854 5855 5856
    args.key = (char *) key;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY,
              (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_lookup_by_key_ret, (char *) &ret) == -1)
5857
        goto done;
5858 5859 5860 5861

    vol = get_nonnull_storage_vol (conn, ret.vol);
    xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_key_ret, (char *) &ret);

5862
done:
5863
    remoteDriverUnlock(priv);
5864 5865 5866 5867 5868 5869 5870
    return vol;
}

static virStorageVolPtr
remoteStorageVolLookupByPath (virConnectPtr conn,
                              const char *path)
{
5871
    virStorageVolPtr vol = NULL;
5872 5873
    remote_storage_vol_lookup_by_path_args args;
    remote_storage_vol_lookup_by_path_ret ret;
5874
    struct private_data *priv = conn->storagePrivateData;
5875

5876 5877
    remoteDriverLock(priv);

5878 5879 5880 5881 5882 5883
    args.path = (char *) path;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH,
              (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_lookup_by_path_ret, (char *) &ret) == -1)
5884
        goto done;
5885 5886 5887 5888

    vol = get_nonnull_storage_vol (conn, ret.vol);
    xdr_free ((xdrproc_t) &xdr_remote_storage_vol_lookup_by_path_ret, (char *) &ret);

5889
done:
5890
    remoteDriverUnlock(priv);
5891 5892 5893 5894 5895 5896 5897
    return vol;
}

static virStorageVolPtr
remoteStorageVolCreateXML (virStoragePoolPtr pool, const char *xmlDesc,
                           unsigned int flags)
{
5898
    virStorageVolPtr vol = NULL;
5899 5900
    remote_storage_vol_create_xml_args args;
    remote_storage_vol_create_xml_ret ret;
5901
    struct private_data *priv = pool->conn->storagePrivateData;
5902

5903 5904
    remoteDriverLock(priv);

5905 5906 5907 5908 5909 5910 5911 5912
    make_nonnull_storage_pool (&args.pool, pool);
    args.xml = (char *) xmlDesc;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML,
              (xdrproc_t) xdr_remote_storage_vol_create_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_create_xml_ret, (char *) &ret) == -1)
5913
        goto done;
5914 5915 5916 5917

    vol = get_nonnull_storage_vol (pool->conn, ret.vol);
    xdr_free ((xdrproc_t) &xdr_remote_storage_vol_create_xml_ret, (char *) &ret);

5918
done:
5919
    remoteDriverUnlock(priv);
5920 5921 5922
    return vol;
}

5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954
static virStorageVolPtr
remoteStorageVolCreateXMLFrom (virStoragePoolPtr pool,
                               const char *xmlDesc,
                               virStorageVolPtr clonevol,
                               unsigned int flags)
{
    virStorageVolPtr newvol = NULL;
    remote_storage_vol_create_xml_from_args args;
    remote_storage_vol_create_xml_from_ret ret;
    struct private_data *priv = pool->conn->storagePrivateData;

    remoteDriverLock(priv);

    make_nonnull_storage_pool (&args.pool, pool);
    make_nonnull_storage_vol (&args.clonevol, clonevol);
    args.xml = (char *) xmlDesc;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (pool->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM,
              (xdrproc_t) xdr_remote_storage_vol_create_xml_from_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_create_xml_from_ret, (char *) &ret) == -1)
        goto done;

    newvol = get_nonnull_storage_vol (pool->conn, ret.vol);
    xdr_free ((xdrproc_t) &xdr_remote_storage_vol_create_xml_from_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return newvol;
}

5955 5956 5957 5958
static int
remoteStorageVolDelete (virStorageVolPtr vol,
                        unsigned int flags)
{
5959
    int rv = -1;
5960
    remote_storage_vol_delete_args args;
5961
    struct private_data *priv = vol->conn->storagePrivateData;
5962

5963 5964
    remoteDriverLock(priv);

5965 5966 5967 5968 5969 5970
    make_nonnull_storage_vol (&args.vol, vol);
    args.flags = flags;

    if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DELETE,
              (xdrproc_t) xdr_remote_storage_vol_delete_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
5971
        goto done;
5972

5973 5974 5975
    rv = 0;

done:
5976
    remoteDriverUnlock(priv);
5977
    return rv;
5978 5979
}

5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005
static int
remoteStorageVolWipe(virStorageVolPtr vol,
                     unsigned int flags)
{
    int rv = -1;
    remote_storage_vol_wipe_args args;
    struct private_data *priv = vol->conn->storagePrivateData;

    remoteDriverLock(priv);

    make_nonnull_storage_vol(&args.vol, vol);
    args.flags = flags;

    if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_WIPE,
             (xdrproc_t) xdr_remote_storage_vol_wipe_args, (char *) &args,
             (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}


6006 6007 6008
static int
remoteStorageVolGetInfo (virStorageVolPtr vol, virStorageVolInfoPtr info)
{
6009
    int rv = -1;
6010 6011
    remote_storage_vol_get_info_args args;
    remote_storage_vol_get_info_ret ret;
6012
    struct private_data *priv = vol->conn->storagePrivateData;
6013

6014 6015
    remoteDriverLock(priv);

6016 6017 6018 6019 6020 6021
    make_nonnull_storage_vol (&args.vol, vol);

    memset (&ret, 0, sizeof ret);
    if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_INFO,
              (xdrproc_t) xdr_remote_storage_vol_get_info_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_get_info_ret, (char *) &ret) == -1)
6022
        goto done;
6023 6024 6025 6026 6027

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

6028 6029 6030
    rv = 0;

done:
6031
    remoteDriverUnlock(priv);
6032
    return rv;
6033 6034 6035 6036 6037 6038
}

static char *
remoteStorageVolDumpXML (virStorageVolPtr vol,
                         unsigned int flags)
{
6039
    char *rv = NULL;
6040 6041
    remote_storage_vol_dump_xml_args args;
    remote_storage_vol_dump_xml_ret ret;
6042
    struct private_data *priv = vol->conn->storagePrivateData;
6043

6044 6045
    remoteDriverLock(priv);

6046 6047 6048 6049 6050 6051 6052
    make_nonnull_storage_vol (&args.vol, vol);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_DUMP_XML,
              (xdrproc_t) xdr_remote_storage_vol_dump_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_dump_xml_ret, (char *) &ret) == -1)
6053
        goto done;
6054 6055

    /* Caller frees. */
6056 6057 6058
    rv = ret.xml;

done:
6059
    remoteDriverUnlock(priv);
6060
    return rv;
6061 6062 6063 6064 6065
}

static char *
remoteStorageVolGetPath (virStorageVolPtr vol)
{
6066
    char *rv = NULL;
6067 6068
    remote_storage_vol_get_path_args args;
    remote_storage_vol_get_path_ret ret;
6069
    struct private_data *priv = vol->conn->storagePrivateData;
6070

6071 6072
    remoteDriverLock(priv);

6073 6074 6075 6076 6077 6078
    make_nonnull_storage_vol (&args.vol, vol);

    memset (&ret, 0, sizeof ret);
    if (call (vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_PATH,
              (xdrproc_t) xdr_remote_storage_vol_get_path_args, (char *) &args,
              (xdrproc_t) xdr_remote_storage_vol_get_path_ret, (char *) &ret) == -1)
6079
        goto done;
6080 6081

    /* Caller frees. */
6082 6083 6084
    rv = ret.name;

done:
6085
    remoteDriverUnlock(priv);
6086
    return rv;
6087 6088 6089
}


6090 6091
/*----------------------------------------------------------------------*/

J
Jim Meyering 已提交
6092
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
6093 6094 6095 6096
remoteDevMonOpen(virConnectPtr conn,
                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                 int flags ATTRIBUTE_UNUSED)
{
6097 6098 6099
    if (inside_daemon)
        return VIR_DRV_OPEN_DECLINED;

J
Jim Meyering 已提交
6100
    if (conn->driver &&
6101
        STREQ (conn->driver->name, "remote")) {
6102
        struct private_data *priv = conn->privateData;
6103 6104 6105 6106
        /* If we're here, the remote driver is already
         * in use due to a) a QEMU uri, or b) a remote
         * URI. So we can re-use existing connection
         */
6107 6108 6109 6110
        remoteDriverLock(priv);
        priv->localUses++;
        conn->devMonPrivateData = priv;
        remoteDriverUnlock(priv);
6111
        return VIR_DRV_OPEN_SUCCESS;
6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126
    } else if (conn->networkDriver &&
               STREQ (conn->networkDriver->name, "remote")) {
        struct private_data *priv = conn->networkPrivateData;
        remoteDriverLock(priv);
        conn->devMonPrivateData = priv;
        priv->localUses++;
        remoteDriverUnlock(priv);
        return VIR_DRV_OPEN_SUCCESS;
    } else {
        /* Using a non-remote driver, so we need to open a
         * new connection for network APIs, forcing it to
         * use the UNIX transport. This handles Xen driver
         * which doesn't have its own impl of the network APIs.
         */
        struct private_data *priv;
6127 6128 6129 6130 6131 6132
        int ret;
        ret = remoteOpenSecondaryDriver(conn,
                                        auth,
                                        flags,
                                        &priv);
        if (ret == VIR_DRV_OPEN_SUCCESS)
6133 6134 6135
            conn->devMonPrivateData = priv;
        return ret;
    }
6136 6137 6138 6139 6140
}

static int remoteDevMonClose(virConnectPtr conn)
{
    int ret = 0;
6141 6142
    struct private_data *priv = conn->devMonPrivateData;

6143 6144 6145 6146 6147 6148 6149 6150
    remoteDriverLock(priv);
    priv->localUses--;
    if (!priv->localUses) {
        ret = doRemoteClose(conn, priv);
        conn->devMonPrivateData = NULL;
        remoteDriverUnlock(priv);
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
6151
    }
6152 6153
    if (priv)
        remoteDriverUnlock(priv);
6154 6155 6156 6157 6158 6159 6160
    return ret;
}

static int remoteNodeNumOfDevices(virConnectPtr conn,
                                  const char *cap,
                                  unsigned int flags)
{
6161
    int rv = -1;
6162 6163
    remote_node_num_of_devices_args args;
    remote_node_num_of_devices_ret ret;
6164
    struct private_data *priv = conn->devMonPrivateData;
6165

6166 6167
    remoteDriverLock(priv);

6168 6169 6170 6171 6172 6173 6174
    args.cap = cap ? (char **)&cap : NULL;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NODE_NUM_OF_DEVICES,
              (xdrproc_t) xdr_remote_node_num_of_devices_args, (char *) &args,
              (xdrproc_t) xdr_remote_node_num_of_devices_ret, (char *) &ret) == -1)
6175 6176 6177
        goto done;

    rv = ret.num;
6178

6179
done:
6180
    remoteDriverUnlock(priv);
6181
    return rv;
6182 6183 6184 6185 6186 6187 6188 6189 6190
}


static int remoteNodeListDevices(virConnectPtr conn,
                                 const char *cap,
                                 char **const names,
                                 int maxnames,
                                 unsigned int flags)
{
6191
    int rv = -1;
6192 6193 6194
    int i;
    remote_node_list_devices_args args;
    remote_node_list_devices_ret ret;
6195
    struct private_data *priv = conn->devMonPrivateData;
6196

6197 6198
    remoteDriverLock(priv);

6199
    if (maxnames > REMOTE_NODE_DEVICE_NAME_LIST_MAX) {
6200
        remoteError(VIR_ERR_RPC, "%s", _("too many device names requested"));
6201
        goto done;
6202 6203 6204 6205 6206 6207 6208 6209 6210
    }
    args.cap = cap ? (char **)&cap : NULL;
    args.maxnames = maxnames;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NODE_LIST_DEVICES,
              (xdrproc_t) xdr_remote_node_list_devices_args, (char *) &args,
              (xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret) == -1)
6211
        goto done;
6212 6213

    if (ret.names.names_len > maxnames) {
6214
        remoteError(VIR_ERR_RPC, "%s", _("too many device names received"));
6215
        goto cleanup;
6216 6217 6218 6219 6220 6221 6222
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
6223
    for (i = 0; i < ret.names.names_len; ++i) {
6224 6225
        names[i] = strdup (ret.names.names_val[i]);

6226 6227 6228 6229
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

6230
            virReportOOMError();
6231 6232 6233 6234
            goto cleanup;
        }
    }

6235 6236 6237
    rv = ret.names.names_len;

cleanup:
6238 6239
    xdr_free ((xdrproc_t) xdr_remote_node_list_devices_ret, (char *) &ret);

6240
done:
6241
    remoteDriverUnlock(priv);
6242
    return rv;
6243 6244 6245 6246 6247 6248 6249 6250
}


static virNodeDevicePtr remoteNodeDeviceLookupByName(virConnectPtr conn,
                                                     const char *name)
{
    remote_node_device_lookup_by_name_args args;
    remote_node_device_lookup_by_name_ret ret;
6251
    virNodeDevicePtr dev = NULL;
6252
    struct private_data *priv = conn->devMonPrivateData;
6253

6254 6255
    remoteDriverLock(priv);

6256 6257 6258 6259 6260 6261
    args.name = (char *)name;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_node_device_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret) == -1)
6262
        goto done;
6263 6264 6265 6266 6267

    dev = get_nonnull_node_device(conn, ret.dev);

    xdr_free ((xdrproc_t) xdr_remote_node_device_lookup_by_name_ret, (char *) &ret);

6268
done:
6269
    remoteDriverUnlock(priv);
6270 6271 6272 6273 6274 6275
    return dev;
}

static char *remoteNodeDeviceDumpXML(virNodeDevicePtr dev,
                                     unsigned int flags)
{
6276
    char *rv = NULL;
6277 6278
    remote_node_device_dump_xml_args args;
    remote_node_device_dump_xml_ret ret;
6279
    struct private_data *priv = dev->conn->devMonPrivateData;
6280

6281 6282
    remoteDriverLock(priv);

6283 6284 6285 6286 6287 6288 6289
    args.name = dev->name;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DUMP_XML,
              (xdrproc_t) xdr_remote_node_device_dump_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_node_device_dump_xml_ret, (char *) &ret) == -1)
6290
        goto done;
6291 6292

    /* Caller frees. */
6293 6294 6295
    rv = ret.xml;

done:
6296
    remoteDriverUnlock(priv);
6297
    return rv;
6298 6299 6300 6301
}

static char *remoteNodeDeviceGetParent(virNodeDevicePtr dev)
{
6302
    char *rv = NULL;
6303 6304
    remote_node_device_get_parent_args args;
    remote_node_device_get_parent_ret ret;
6305
    struct private_data *priv = dev->conn->devMonPrivateData;
6306

6307 6308
    remoteDriverLock(priv);

6309 6310 6311 6312 6313 6314
    args.name = dev->name;

    memset (&ret, 0, sizeof ret);
    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_GET_PARENT,
              (xdrproc_t) xdr_remote_node_device_get_parent_args, (char *) &args,
              (xdrproc_t) xdr_remote_node_device_get_parent_ret, (char *) &ret) == -1)
6315
        goto done;
6316 6317

    /* Caller frees. */
6318
    rv = ret.parent ? *ret.parent : NULL;
6319
    VIR_FREE(ret.parent);
6320 6321

done:
6322
    remoteDriverUnlock(priv);
6323
    return rv;
6324 6325 6326 6327
}

static int remoteNodeDeviceNumOfCaps(virNodeDevicePtr dev)
{
6328
    int rv = -1;
6329 6330
    remote_node_device_num_of_caps_args args;
    remote_node_device_num_of_caps_ret ret;
6331
    struct private_data *priv = dev->conn->devMonPrivateData;
6332

6333 6334
    remoteDriverLock(priv);

6335 6336 6337 6338 6339 6340
    args.name = dev->name;

    memset (&ret, 0, sizeof ret);
    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS,
              (xdrproc_t) xdr_remote_node_device_num_of_caps_args, (char *) &args,
              (xdrproc_t) xdr_remote_node_device_num_of_caps_ret, (char *) &ret) == -1)
6341 6342 6343
        goto done;

    rv = ret.num;
6344

6345
done:
6346
    remoteDriverUnlock(priv);
6347
    return rv;
6348 6349 6350 6351 6352 6353
}

static int remoteNodeDeviceListCaps(virNodeDevicePtr dev,
                                    char **const names,
                                    int maxnames)
{
6354
    int rv = -1;
6355 6356 6357
    int i;
    remote_node_device_list_caps_args args;
    remote_node_device_list_caps_ret ret;
6358
    struct private_data *priv = dev->conn->devMonPrivateData;
6359

6360 6361
    remoteDriverLock(priv);

6362
    if (maxnames > REMOTE_NODE_DEVICE_CAPS_LIST_MAX) {
6363
        remoteError(VIR_ERR_RPC, "%s", _("too many capability names requested"));
6364
        goto done;
6365 6366 6367 6368 6369 6370 6371 6372
    }
    args.maxnames = maxnames;
    args.name = dev->name;

    memset (&ret, 0, sizeof ret);
    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_LIST_CAPS,
              (xdrproc_t) xdr_remote_node_device_list_caps_args, (char *) &args,
              (xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret) == -1)
6373
        goto done;
6374 6375

    if (ret.names.names_len > maxnames) {
6376
        remoteError(VIR_ERR_RPC, "%s", _("too many capability names received"));
6377
        goto cleanup;
6378 6379 6380 6381 6382 6383 6384
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
6385
    for (i = 0; i < ret.names.names_len; ++i) {
6386 6387
        names[i] = strdup (ret.names.names_val[i]);

6388 6389 6390 6391
        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

6392
            virReportOOMError();
6393 6394 6395 6396
            goto cleanup;
        }
    }

6397 6398 6399
    rv = ret.names.names_len;

cleanup:
6400 6401
    xdr_free ((xdrproc_t) xdr_remote_node_device_list_caps_ret, (char *) &ret);

6402
done:
6403
    remoteDriverUnlock(priv);
6404
    return rv;
6405 6406
}

6407 6408 6409 6410 6411
static int
remoteNodeDeviceDettach (virNodeDevicePtr dev)
{
    int rv = -1;
    remote_node_device_dettach_args args;
6412 6413
    /* This method is unusual in that it uses the HV driver, not the devMon driver
     * hence its use of privateData, instead of devMonPrivateData */
6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436
    struct private_data *priv = dev->conn->privateData;

    remoteDriverLock(priv);

    args.name = dev->name;

    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DETTACH,
              (xdrproc_t) xdr_remote_node_device_dettach_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeDeviceReAttach (virNodeDevicePtr dev)
{
    int rv = -1;
    remote_node_device_re_attach_args args;
6437 6438
    /* This method is unusual in that it uses the HV driver, not the devMon driver
     * hence its use of privateData, instead of devMonPrivateData */
6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461
    struct private_data *priv = dev->conn->privateData;

    remoteDriverLock(priv);

    args.name = dev->name;

    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_RE_ATTACH,
              (xdrproc_t) xdr_remote_node_device_re_attach_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

static int
remoteNodeDeviceReset (virNodeDevicePtr dev)
{
    int rv = -1;
    remote_node_device_reset_args args;
6462 6463
    /* This method is unusual in that it uses the HV driver, not the devMon driver
     * hence its use of privateData, instead of devMonPrivateData */
6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481
    struct private_data *priv = dev->conn->privateData;

    remoteDriverLock(priv);

    args.name = dev->name;

    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_RESET,
              (xdrproc_t) xdr_remote_node_device_reset_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

6482

6483 6484 6485 6486 6487 6488 6489 6490
static virNodeDevicePtr
remoteNodeDeviceCreateXML(virConnectPtr conn,
                          const char *xmlDesc,
                          unsigned int flags)
{
    remote_node_device_create_xml_args args;
    remote_node_device_create_xml_ret ret;
    virNodeDevicePtr dev = NULL;
6491
    struct private_data *priv = conn->devMonPrivateData;
6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516

    remoteDriverLock(priv);

    memset(&ret, 0, sizeof ret);
    args.xml_desc = (char *)xmlDesc;
    args.flags = flags;

    if (call(conn, priv, 0, REMOTE_PROC_NODE_DEVICE_CREATE_XML,
             (xdrproc_t) xdr_remote_node_device_create_xml_args, (char *) &args,
             (xdrproc_t) xdr_remote_node_device_create_xml_ret, (char *) &ret) == -1)
        goto done;

    dev = get_nonnull_node_device(conn, ret.dev);
    xdr_free ((xdrproc_t) xdr_remote_node_device_create_xml_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return dev;
}

static int
remoteNodeDeviceDestroy(virNodeDevicePtr dev)
{
    int rv = -1;
    remote_node_device_destroy_args args;
6517
    struct private_data *priv = dev->conn->devMonPrivateData;
6518 6519 6520 6521 6522

    remoteDriverLock(priv);

    args.name = dev->name;

6523
    if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DESTROY,
6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534
             (xdrproc_t) xdr_remote_node_device_destroy_args, (char *) &args,
             (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684
/* ------------------------------------------------------------- */

static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
remoteNWFilterOpen (virConnectPtr conn,
                    virConnectAuthPtr auth,
                    int flags)
{
    if (inside_daemon)
        return VIR_DRV_OPEN_DECLINED;

    if (conn->driver &&
        STREQ (conn->driver->name, "remote")) {
        struct private_data *priv;

       /* If we're here, the remote driver is already
         * in use due to a) a QEMU uri, or b) a remote
         * URI. So we can re-use existing connection
         */
        priv = conn->privateData;
        remoteDriverLock(priv);
        priv->localUses++;
        conn->nwfilterPrivateData = priv;
        remoteDriverUnlock(priv);
        return VIR_DRV_OPEN_SUCCESS;
    } else {
        /* Using a non-remote driver, so we need to open a
         * new connection for network filtering APIs, forcing it to
         * use the UNIX transport. This handles Xen driver
         * which doesn't have its own impl of the network filtering APIs.
         */
        struct private_data *priv;
        int ret;
        ret = remoteOpenSecondaryDriver(conn,
                                        auth,
                                        flags,
                                        &priv);
        if (ret == VIR_DRV_OPEN_SUCCESS)
            conn->nwfilterPrivateData = priv;
        return ret;
    }
}

static int
remoteNWFilterClose (virConnectPtr conn)
{
    int rv = 0;
    struct private_data *priv = conn->nwfilterPrivateData;

    remoteDriverLock(priv);
    priv->localUses--;
    if (!priv->localUses) {
        rv = doRemoteClose(conn, priv);
        conn->nwfilterPrivateData = NULL;
        remoteDriverUnlock(priv);
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
    }
    if (priv)
        remoteDriverUnlock(priv);
    return rv;
}


static int
remoteNumOfNWFilters (virConnectPtr conn)
{
    int rv = -1;
    remote_num_of_nwfilters_ret ret;
    struct private_data *priv = conn->nwfilterPrivateData;

    remoteDriverLock(priv);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_NWFILTERS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_nwfilters_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}


static virNWFilterPtr
remoteNWFilterDefineXML (virConnectPtr conn, const char *xmlDesc,
                         unsigned int flags ATTRIBUTE_UNUSED)
{
    virNWFilterPtr net = NULL;
    remote_nwfilter_define_xml_args args;
    remote_nwfilter_define_xml_ret ret;
    struct private_data *priv = conn->nwfilterPrivateData;

    remoteDriverLock(priv);

    args.xml = (char *) xmlDesc;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NWFILTER_DEFINE_XML,
              (xdrproc_t) xdr_remote_nwfilter_define_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_nwfilter_define_xml_ret, (char *) &ret) == -1)
        goto done;

    net = get_nonnull_nwfilter (conn, ret.nwfilter);
    xdr_free ((xdrproc_t) &xdr_remote_nwfilter_define_xml_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return net;
}


static int
remoteNWFilterUndefine (virNWFilterPtr nwfilter)
{
    int rv = -1;
    remote_nwfilter_undefine_args args;
    struct private_data *priv = nwfilter->conn->nwfilterPrivateData;

    remoteDriverLock(priv);

    make_nonnull_nwfilter (&args.nwfilter, nwfilter);

    if (call (nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_UNDEFINE,
              (xdrproc_t) xdr_remote_nwfilter_undefine_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}


static int
remoteListNWFilters (virConnectPtr conn, char **const names, int maxnames)
{
    int rv = -1;
    int i;
    remote_list_nwfilters_args args;
    remote_list_nwfilters_ret ret;
    struct private_data *priv = conn->nwfilterPrivateData;

    remoteDriverLock(priv);

    if (maxnames > REMOTE_NWFILTER_NAME_LIST_MAX) {
6685 6686 6687
        remoteError(VIR_ERR_RPC,
                    _("too many remote nwfilters: %d > %d"),
                    maxnames, REMOTE_NWFILTER_NAME_LIST_MAX);
6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698
        goto done;
    }
    args.maxnames = maxnames;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_NWFILTERS,
              (xdrproc_t) xdr_remote_list_nwfilters_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_nwfilters_ret, (char *) &ret) == -1)
        goto done;

    if (ret.names.names_len > maxnames) {
6699 6700 6701
        remoteError(VIR_ERR_RPC,
                    _("too many remote nwfilters: %d > %d"),
                    ret.names.names_len, maxnames);
6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
    for (i = 0; i < ret.names.names_len; ++i) {
        names[i] = strdup (ret.names.names_val[i]);

        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

            virReportOOMError();
            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free ((xdrproc_t) xdr_remote_list_nwfilters_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}



static virNWFilterPtr
remoteNWFilterLookupByUUID (virConnectPtr conn,
                            const unsigned char *uuid)
{
    virNWFilterPtr net = NULL;
    remote_nwfilter_lookup_by_uuid_args args;
    remote_nwfilter_lookup_by_uuid_ret ret;
    struct private_data *priv = conn->nwfilterPrivateData;

    remoteDriverLock(priv);

    memcpy (args.uuid, uuid, VIR_UUID_BUFLEN);

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID,
              (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_args, (char *) &args,
              (xdrproc_t) xdr_remote_nwfilter_lookup_by_uuid_ret, (char *) &ret) == -1)
        goto done;

    net = get_nonnull_nwfilter (conn, ret.nwfilter);
    xdr_free ((xdrproc_t) &xdr_remote_nwfilter_lookup_by_uuid_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return net;
}

static virNWFilterPtr
remoteNWFilterLookupByName (virConnectPtr conn,
                            const char *name)
{
    virNWFilterPtr net = NULL;
    remote_nwfilter_lookup_by_name_args args;
    remote_nwfilter_lookup_by_name_ret ret;
    struct private_data *priv = conn->nwfilterPrivateData;

    remoteDriverLock(priv);

    args.name = (char *) name;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_nwfilter_lookup_by_name_ret, (char *) &ret) == -1)
        goto done;

    net = get_nonnull_nwfilter (conn, ret.nwfilter);
    xdr_free ((xdrproc_t) &xdr_remote_nwfilter_lookup_by_name_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return net;
}


static char *
remoteNWFilterGetXMLDesc (virNWFilterPtr nwfilter, unsigned int flags)
{
    char *rv = NULL;
    remote_nwfilter_get_xml_desc_args args;
    remote_nwfilter_get_xml_desc_ret ret;
    struct private_data *priv = nwfilter->conn->nwfilterPrivateData;

    remoteDriverLock(priv);

    make_nonnull_nwfilter (&args.nwfilter, nwfilter);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (nwfilter->conn, priv, 0, REMOTE_PROC_NWFILTER_GET_XML_DESC,
              (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_args, (char *) &args,
              (xdrproc_t) xdr_remote_nwfilter_get_xml_desc_ret, (char *) &ret) == -1)
        goto done;

    /* Caller frees. */
    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}

6816

6817 6818
/*----------------------------------------------------------------------*/

6819
static int
E
Eric Blake 已提交
6820 6821 6822
remoteAuthenticate (virConnectPtr conn, struct private_data *priv,
                    int in_open ATTRIBUTE_UNUSED,
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
6823
                    const char *authtype)
6824 6825
{
    struct remote_auth_list_ret ret;
6826
    int err, type = REMOTE_AUTH_NONE;
6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842

    memset(&ret, 0, sizeof ret);
    err = call (conn, priv,
                REMOTE_CALL_IN_OPEN | REMOTE_CALL_QUIET_MISSING_RPC,
                REMOTE_PROC_AUTH_LIST,
                (xdrproc_t) xdr_void, (char *) NULL,
                (xdrproc_t) xdr_remote_auth_list_ret, (char *) &ret);
    if (err == -2) /* Missing RPC - old server - ignore */
        return 0;

    if (err < 0)
        return -1;

    if (ret.types.types_len == 0)
        return 0;

6843 6844 6845 6846 6847 6848 6849 6850
    if (authtype) {
        int want, i;
        if (STRCASEEQ(authtype, "sasl") ||
            STRCASEEQLEN(authtype, "sasl.", 5)) {
            want = REMOTE_AUTH_SASL;
        } else if (STRCASEEQ(authtype, "polkit")) {
            want = REMOTE_AUTH_POLKIT;
        } else {
6851 6852
            remoteError(VIR_ERR_AUTH_FAILED,
                        _("unknown authentication type %s"), authtype);
6853 6854 6855 6856 6857 6858 6859
            return -1;
        }
        for (i = 0 ; i < ret.types.types_len ; i++) {
            if (ret.types.types_val[i] == want)
                type = want;
        }
        if (type == REMOTE_AUTH_NONE) {
6860 6861 6862
            remoteError(VIR_ERR_AUTH_FAILED,
                        _("requested authentication type %s rejected"),
                        authtype);
6863 6864 6865 6866 6867 6868 6869
            return -1;
        }
    } else {
        type = ret.types.types_val[0];
    }

    switch (type) {
6870
#if HAVE_SASL
6871 6872 6873 6874 6875 6876 6877
    case REMOTE_AUTH_SASL: {
        const char *mech = NULL;
        if (authtype &&
            STRCASEEQLEN(authtype, "sasl.", 5))
            mech = authtype + 5;

        if (remoteAuthSASL(conn, priv, in_open, auth, mech) < 0) {
6878
            VIR_FREE(ret.types.types_val);
6879 6880 6881
            return -1;
        }
        break;
6882
    }
6883 6884
#endif

6885 6886
#if HAVE_POLKIT
    case REMOTE_AUTH_POLKIT:
6887
        if (remoteAuthPolkit(conn, priv, in_open, auth) < 0) {
6888
            VIR_FREE(ret.types.types_val);
6889 6890 6891 6892 6893
            return -1;
        }
        break;
#endif

6894 6895 6896 6897 6898
    case REMOTE_AUTH_NONE:
        /* Nothing todo, hurrah ! */
        break;

    default:
6899 6900 6901
        remoteError(VIR_ERR_AUTH_FAILED,
                    _("unsupported authentication type %d"),
                    ret.types.types_val[0]);
6902
        VIR_FREE(ret.types.types_val);
6903 6904 6905
        return -1;
    }

6906
    VIR_FREE(ret.types.types_val);
6907 6908 6909 6910 6911 6912 6913

    return 0;
}



#if HAVE_SASL
6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991
static int remoteAuthCredVir2SASL(int vircred)
{
    switch (vircred) {
    case VIR_CRED_USERNAME:
        return SASL_CB_USER;

    case VIR_CRED_AUTHNAME:
        return SASL_CB_AUTHNAME;

    case VIR_CRED_LANGUAGE:
        return SASL_CB_LANGUAGE;

    case VIR_CRED_CNONCE:
        return SASL_CB_CNONCE;

    case VIR_CRED_PASSPHRASE:
        return SASL_CB_PASS;

    case VIR_CRED_ECHOPROMPT:
        return SASL_CB_ECHOPROMPT;

    case VIR_CRED_NOECHOPROMPT:
        return SASL_CB_NOECHOPROMPT;

    case VIR_CRED_REALM:
        return SASL_CB_GETREALM;
    }

    return 0;
}

static int remoteAuthCredSASL2Vir(int vircred)
{
    switch (vircred) {
    case SASL_CB_USER:
        return VIR_CRED_USERNAME;

    case SASL_CB_AUTHNAME:
        return VIR_CRED_AUTHNAME;

    case SASL_CB_LANGUAGE:
        return VIR_CRED_LANGUAGE;

    case SASL_CB_CNONCE:
        return VIR_CRED_CNONCE;

    case SASL_CB_PASS:
        return VIR_CRED_PASSPHRASE;

    case SASL_CB_ECHOPROMPT:
        return VIR_CRED_ECHOPROMPT;

    case SASL_CB_NOECHOPROMPT:
        return VIR_CRED_NOECHOPROMPT;

    case SASL_CB_GETREALM:
        return VIR_CRED_REALM;
    }

    return 0;
}

/*
 * @param credtype array of credential types client supports
 * @param ncredtype size of credtype array
 * @return the SASL callback structure, or NULL on error
 *
 * Build up the SASL callback structure. We register one callback for
 * each credential type that the libvirt client indicated they support.
 * We explicitly leav the callback function pointer at NULL though,
 * because we don't actually want to get SASL callbacks triggered.
 * Instead, we want the start/step functions to return SASL_INTERACT.
 * This lets us give the libvirt client a list of all required
 * credentials in one go, rather than triggering the callback one
 * credential at a time,
 */
static sasl_callback_t *remoteAuthMakeCallbacks(int *credtype, int ncredtype)
{
6992
    sasl_callback_t *cbs;
6993
    int i, n;
6994
    if (VIR_ALLOC_N(cbs, ncredtype+1) < 0) {
6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013
        return NULL;
    }

    for (i = 0, n = 0 ; i < ncredtype ; i++) {
        int id = remoteAuthCredVir2SASL(credtype[i]);
        if (id != 0)
            cbs[n++].id = id;
        /* Don't fill proc or context fields of sasl_callback_t
         * because we want to use interactions instead */
    }
    cbs[n].id = 0;
    return cbs;
}


/*
 * @param interact SASL interactions required
 * @param cred populated with libvirt credential metadata
 * @return the size of the cred array returned
7014
 *
7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028
 * Builds up an array of libvirt credential structs, populating
 * with data from the SASL interaction struct. These two structs
 * are basically a 1-to-1 copy of each other.
 */
static int remoteAuthMakeCredentials(sasl_interact_t *interact,
                                     virConnectCredentialPtr *cred)
{
    int ninteract;
    if (!cred)
        return -1;

    for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++)
        ; /* empty */

7029
    if (VIR_ALLOC_N(*cred, ninteract) < 0)
7030 7031 7032 7033 7034
        return -1;

    for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
        (*cred)[ninteract].type = remoteAuthCredSASL2Vir(interact[ninteract].id);
        if (!(*cred)[ninteract].type) {
7035
            VIR_FREE(*cred);
7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053
            return -1;
        }
        if (interact[ninteract].challenge)
            (*cred)[ninteract].challenge = interact[ninteract].challenge;
        (*cred)[ninteract].prompt = interact[ninteract].prompt;
        if (interact[ninteract].defresult)
            (*cred)[ninteract].defresult = interact[ninteract].defresult;
        (*cred)[ninteract].result = NULL;
    }

    return ninteract;
}

static void remoteAuthFreeCredentials(virConnectCredentialPtr cred,
                                      int ncred)
{
    int i;
    for (i = 0 ; i < ncred ; i++)
7054 7055
        VIR_FREE(cred[i].result);
    VIR_FREE(cred);
7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076
}


/*
 * @param cred the populated libvirt credentials
 * @param interact the SASL interactions to fill in results for
 *
 * Fills the SASL interactions with the result from the libvirt
 * callbacks
 */
static void remoteAuthFillInteract(virConnectCredentialPtr cred,
                                   sasl_interact_t *interact)
{
    int ninteract;
    for (ninteract = 0 ; interact[ninteract].id != 0 ; ninteract++) {
        interact[ninteract].result = cred[ninteract].result;
        interact[ninteract].len = cred[ninteract].resultlen;
    }
}

/* Perform the SASL authentication process
7077 7078
 */
static int
7079 7080
remoteAuthSASL (virConnectPtr conn, struct private_data *priv, int in_open,
                virConnectAuthPtr auth, const char *wantmech)
7081 7082
{
    sasl_conn_t *saslconn = NULL;
7083
    sasl_security_properties_t secprops;
7084 7085 7086 7087 7088 7089
    remote_auth_sasl_init_ret iret;
    remote_auth_sasl_start_args sargs;
    remote_auth_sasl_start_ret sret;
    remote_auth_sasl_step_args pargs;
    remote_auth_sasl_step_ret pret;
    const char *clientout;
7090
    char *serverin = NULL;
7091 7092 7093
    unsigned int clientoutlen, serverinlen;
    const char *mech;
    int err, complete;
7094
    virSocketAddr sa;
7095
    char *localAddr = NULL, *remoteAddr = NULL;
7096 7097
    const void *val;
    sasl_ssf_t ssf;
7098 7099 7100 7101 7102 7103
    sasl_callback_t *saslcb = NULL;
    sasl_interact_t *interact = NULL;
    virConnectCredentialPtr cred = NULL;
    int ncred = 0;
    int ret = -1;
    const char *mechlist;
7104

7105
    DEBUG0("Client initialize SASL authentication");
7106 7107 7108
    /* Sets up the SASL library as a whole */
    err = sasl_client_init(NULL);
    if (err != SASL_OK) {
7109 7110 7111
        remoteError(VIR_ERR_AUTH_FAILED,
                    _("failed to initialize SASL library: %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
7112
        goto cleanup;
7113 7114 7115
    }

    /* Get local address in form  IPADDR:PORT */
7116 7117
    sa.len = sizeof(sa.data.stor);
    if (getsockname(priv->sock, &sa.data.sa, &sa.len) < 0) {
7118
        virReportSystemError(errno, "%s",
7119
                             _("failed to get sock address"));
7120
        goto cleanup;
7121
    }
7122
    if ((localAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL)
7123
        goto cleanup;
7124 7125

    /* Get remote address in form  IPADDR:PORT */
7126 7127
    sa.len = sizeof(sa.data.stor);
    if (getpeername(priv->sock, &sa.data.sa, &sa.len) < 0) {
7128
        virReportSystemError(errno, "%s",
7129
                             _("failed to get peer address"));
7130
        goto cleanup;
7131
    }
7132
    if ((remoteAddr = virSocketFormatAddrFull(&sa, true, ";")) == NULL)
7133 7134
        goto cleanup;

7135 7136 7137 7138 7139 7140
    if (auth) {
        if ((saslcb = remoteAuthMakeCallbacks(auth->credtype, auth->ncredtype)) == NULL)
            goto cleanup;
    } else {
        saslcb = NULL;
    }
7141 7142 7143 7144 7145 7146

    /* Setup a handle for being a client */
    err = sasl_client_new("libvirt",
                          priv->hostname,
                          localAddr,
                          remoteAddr,
7147
                          saslcb,
7148 7149
                          SASL_SUCCESS_DATA,
                          &saslconn);
7150

7151
    if (err != SASL_OK) {
7152 7153 7154
        remoteError(VIR_ERR_AUTH_FAILED,
                    _("Failed to create SASL client context: %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
7155
        goto cleanup;
7156 7157
    }

7158 7159 7160 7161 7162 7163
    /* Initialize some connection props we care about */
    if (priv->uses_tls) {
        gnutls_cipher_algorithm_t cipher;

        cipher = gnutls_cipher_get(priv->session);
        if (!(ssf = (sasl_ssf_t)gnutls_cipher_get_key_size(cipher))) {
7164 7165
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("invalid cipher size for TLS session"));
7166
            goto cleanup;
7167 7168 7169
        }
        ssf *= 8; /* key size is bytes, sasl wants bits */

7170
        DEBUG("Setting external SSF %d", ssf);
7171 7172
        err = sasl_setprop(saslconn, SASL_SSF_EXTERNAL, &ssf);
        if (err != SASL_OK) {
7173 7174 7175
            remoteError(VIR_ERR_INTERNAL_ERROR,
                        _("cannot set external SSF %d (%s)"),
                        err, sasl_errstring(err, NULL, NULL));
7176
            goto cleanup;
7177 7178 7179 7180
        }
    }

    memset (&secprops, 0, sizeof secprops);
7181 7182 7183
    /* If we've got a secure channel (TLS or UNIX sock), we don't care about SSF */
    secprops.min_ssf = priv->is_secure ? 0 : 56; /* Equiv to DES supported by all Kerberos */
    secprops.max_ssf = priv->is_secure ? 0 : 100000; /* Very strong ! AES == 256 */
7184
    secprops.maxbufsize = 100000;
7185 7186
    /* If we're not secure, then forbid any anonymous or trivially crackable auth */
    secprops.security_flags = priv->is_secure ? 0 :
7187 7188 7189 7190
        SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT;

    err = sasl_setprop(saslconn, SASL_SEC_PROPS, &secprops);
    if (err != SASL_OK) {
7191 7192 7193
        remoteError(VIR_ERR_INTERNAL_ERROR,
                    _("cannot set security props %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
7194
        goto cleanup;
7195 7196
    }

7197 7198 7199 7200
    /* First call is to inquire about supported mechanisms in the server */
    memset (&iret, 0, sizeof iret);
    if (call (conn, priv, in_open, REMOTE_PROC_AUTH_SASL_INIT,
              (xdrproc_t) xdr_void, (char *)NULL,
7201 7202
              (xdrproc_t) xdr_remote_auth_sasl_init_ret, (char *) &iret) != 0)
        goto cleanup;
7203 7204


7205 7206 7207
    mechlist = iret.mechlist;
    if (wantmech) {
        if (strstr(mechlist, wantmech) == NULL) {
7208 7209 7210
            remoteError(VIR_ERR_AUTH_FAILED,
                        _("SASL mechanism %s not supported by server"),
                        wantmech);
7211
            VIR_FREE(iret.mechlist);
7212 7213 7214 7215 7216
            goto cleanup;
        }
        mechlist = wantmech;
    }
 restart:
7217
    /* Start the auth negotiation on the client end first */
7218
    DEBUG("Client start negotiation mechlist '%s'", mechlist);
7219
    err = sasl_client_start(saslconn,
7220 7221
                            mechlist,
                            &interact,
7222 7223 7224
                            &clientout,
                            &clientoutlen,
                            &mech);
7225
    if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) {
7226 7227 7228
        remoteError(VIR_ERR_AUTH_FAILED,
                    _("Failed to start SASL negotiation: %d (%s)"),
                    err, sasl_errdetail(saslconn));
7229
        VIR_FREE(iret.mechlist);
7230 7231 7232 7233 7234
        goto cleanup;
    }

    /* Need to gather some credentials from the client */
    if (err == SASL_INTERACT) {
7235
        const char *msg;
7236 7237 7238 7239
        if (cred) {
            remoteAuthFreeCredentials(cred, ncred);
            cred = NULL;
        }
7240 7241 7242
        if ((ncred = remoteAuthMakeCredentials(interact, &cred)) < 0) {
            remoteError(VIR_ERR_AUTH_FAILED, "%s",
                        _("Failed to make auth credentials"));
7243
            VIR_FREE(iret.mechlist);
7244 7245 7246
            goto cleanup;
        }
        /* Run the authentication callback */
7247
        if (auth && auth->cb) {
7248 7249 7250
            if ((*(auth->cb))(cred, ncred, auth->cbdata) >= 0) {
                remoteAuthFillInteract(cred, interact);
                goto restart;
7251
            }
7252
            msg = "Failed to collect auth credentials";
7253
        } else {
7254
            msg = "No authentication callback available";
7255
        }
7256
        remoteError(VIR_ERR_AUTH_FAILED, "%s", msg);
7257
        goto cleanup;
7258
    }
7259
    VIR_FREE(iret.mechlist);
7260 7261

    if (clientoutlen > REMOTE_AUTH_SASL_DATA_MAX) {
7262 7263 7264
        remoteError(VIR_ERR_AUTH_FAILED,
                    _("SASL negotiation data too long: %d bytes"),
                    clientoutlen);
7265
        goto cleanup;
7266 7267 7268 7269 7270 7271 7272
    }
    /* NB, distinction of NULL vs "" is *critical* in SASL */
    memset(&sargs, 0, sizeof sargs);
    sargs.nil = clientout ? 0 : 1;
    sargs.data.data_val = (char*)clientout;
    sargs.data.data_len = clientoutlen;
    sargs.mech = (char*)mech;
7273
    DEBUG("Server start negotiation with mech %s. Data %d bytes %p", mech, clientoutlen, clientout);
7274 7275 7276 7277 7278

    /* Now send the initial auth data to the server */
    memset (&sret, 0, sizeof sret);
    if (call (conn, priv, in_open, REMOTE_PROC_AUTH_SASL_START,
              (xdrproc_t) xdr_remote_auth_sasl_start_args, (char *) &sargs,
7279 7280
              (xdrproc_t) xdr_remote_auth_sasl_start_ret, (char *) &sret) != 0)
        goto cleanup;
7281 7282 7283 7284 7285

    complete = sret.complete;
    /* NB, distinction of NULL vs "" is *critical* in SASL */
    serverin = sret.nil ? NULL : sret.data.data_val;
    serverinlen = sret.data.data_len;
7286 7287
    DEBUG("Client step result complete: %d. Data %d bytes %p",
          complete, serverinlen, serverin);
7288 7289 7290

    /* Loop-the-loop...
     * Even if the server has completed, the client must *always* do at least one step
D
Daniel Veillard 已提交
7291
     * in this loop to verify the server isn't lying about something. Mutual auth */
7292
    for (;;) {
7293
    restep:
7294 7295 7296
        err = sasl_client_step(saslconn,
                               serverin,
                               serverinlen,
7297
                               &interact,
7298 7299
                               &clientout,
                               &clientoutlen);
7300
        if (err != SASL_OK && err != SASL_CONTINUE && err != SASL_INTERACT) {
7301 7302 7303
            remoteError(VIR_ERR_AUTH_FAILED,
                        _("Failed SASL step: %d (%s)"),
                        err, sasl_errdetail(saslconn));
7304 7305 7306 7307
            goto cleanup;
        }
        /* Need to gather some credentials from the client */
        if (err == SASL_INTERACT) {
7308
            const char *msg;
7309 7310 7311 7312 7313
            if (cred) {
                remoteAuthFreeCredentials(cred, ncred);
                cred = NULL;
            }
            if ((ncred = remoteAuthMakeCredentials(interact, &cred)) < 0) {
7314 7315
                remoteError(VIR_ERR_AUTH_FAILED, "%s",
                            _("Failed to make auth credentials"));
7316 7317 7318
                goto cleanup;
            }
            /* Run the authentication callback */
7319
            if (auth && auth->cb) {
7320 7321 7322
                if ((*(auth->cb))(cred, ncred, auth->cbdata) >= 0) {
                    remoteAuthFillInteract(cred, interact);
                    goto restep;
7323
                }
7324
                msg = _("Failed to collect auth credentials");
7325
            } else {
7326
                msg = _("No authentication callback available");
7327
            }
7328
            remoteError(VIR_ERR_AUTH_FAILED, "%s", msg);
7329
            goto cleanup;
7330 7331
        }

7332
        VIR_FREE(serverin);
7333
        DEBUG("Client step result %d. Data %d bytes %p", err, clientoutlen, clientout);
7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344

        /* Previous server call showed completion & we're now locally complete too */
        if (complete && err == SASL_OK)
            break;

        /* Not done, prepare to talk with the server for another iteration */
        /* NB, distinction of NULL vs "" is *critical* in SASL */
        memset(&pargs, 0, sizeof pargs);
        pargs.nil = clientout ? 0 : 1;
        pargs.data.data_val = (char*)clientout;
        pargs.data.data_len = clientoutlen;
7345
        DEBUG("Server step with %d bytes %p", clientoutlen, clientout);
7346 7347 7348 7349

        memset (&pret, 0, sizeof pret);
        if (call (conn, priv, in_open, REMOTE_PROC_AUTH_SASL_STEP,
                  (xdrproc_t) xdr_remote_auth_sasl_step_args, (char *) &pargs,
7350 7351
                  (xdrproc_t) xdr_remote_auth_sasl_step_ret, (char *) &pret) != 0)
            goto cleanup;
7352 7353 7354 7355 7356 7357

        complete = pret.complete;
        /* NB, distinction of NULL vs "" is *critical* in SASL */
        serverin = pret.nil ? NULL : pret.data.data_val;
        serverinlen = pret.data.data_len;

7358 7359
        DEBUG("Client step result complete: %d. Data %d bytes %p",
              complete, serverinlen, serverin);
7360 7361 7362

        /* This server call shows complete, and earlier client step was OK */
        if (complete && err == SASL_OK) {
7363
            VIR_FREE(serverin);
7364 7365 7366 7367
            break;
        }
    }

7368 7369
    /* Check for suitable SSF if not already secure (TLS or UNIX sock) */
    if (!priv->is_secure) {
7370 7371
        err = sasl_getprop(saslconn, SASL_SSF, &val);
        if (err != SASL_OK) {
7372 7373 7374
            remoteError(VIR_ERR_AUTH_FAILED,
                        _("cannot query SASL ssf on connection %d (%s)"),
                        err, sasl_errstring(err, NULL, NULL));
7375
            goto cleanup;
7376 7377
        }
        ssf = *(const int *)val;
7378
        DEBUG("SASL SSF value %d", ssf);
7379
        if (ssf < 56) { /* 56 == DES level, good for Kerberos */
7380 7381
            remoteError(VIR_ERR_AUTH_FAILED,
                        _("negotiation SSF %d was not strong enough"), ssf);
7382
            goto cleanup;
7383
        }
7384
        priv->is_secure = 1;
7385 7386
    }

7387
    DEBUG0("SASL authentication complete");
7388
    priv->saslconn = saslconn;
7389 7390 7391
    ret = 0;

 cleanup:
7392 7393 7394
    VIR_FREE(localAddr);
    VIR_FREE(remoteAddr);
    VIR_FREE(serverin);
7395

7396
    VIR_FREE(saslcb);
7397 7398 7399
    remoteAuthFreeCredentials(cred, ncred);
    if (ret != 0 && saslconn)
        sasl_dispose(&saslconn);
7400

7401
    return ret;
7402 7403 7404
}
#endif /* HAVE_SASL */

7405 7406

#if HAVE_POLKIT
7407
# if HAVE_POLKIT1
7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424
static int
remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
                  virConnectAuthPtr auth ATTRIBUTE_UNUSED)
{
    remote_auth_polkit_ret ret;
    DEBUG0("Client initialize PolicyKit-1 authentication");

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, in_open, REMOTE_PROC_AUTH_POLKIT,
              (xdrproc_t) xdr_void, (char *)NULL,
              (xdrproc_t) xdr_remote_auth_polkit_ret, (char *) &ret) != 0) {
        return -1; /* virError already set by call */
    }

    DEBUG0("PolicyKit-1 authentication complete");
    return 0;
}
7425
# elif HAVE_POLKIT0
7426 7427 7428 7429 7430 7431 7432
/* Perform the PolicyKit authentication process
 */
static int
remoteAuthPolkit (virConnectPtr conn, struct private_data *priv, int in_open,
                  virConnectAuthPtr auth)
{
    remote_auth_polkit_ret ret;
7433
    int i, allowcb = 0;
7434 7435 7436 7437 7438 7439 7440 7441
    virConnectCredential cred = {
        VIR_CRED_EXTERNAL,
        conn->flags & VIR_CONNECT_RO ? "org.libvirt.unix.monitor" : "org.libvirt.unix.manage",
        "PolicyKit",
        NULL,
        NULL,
        0,
    };
7442
    DEBUG0("Client initialize PolicyKit-0 authentication");
7443

7444
    if (auth && auth->cb) {
7445
        /* Check if the necessary credential type for PolicyKit is supported */
7446 7447 7448 7449
        for (i = 0 ; i < auth->ncredtype ; i++) {
            if (auth->credtype[i] == VIR_CRED_EXTERNAL)
                allowcb = 1;
        }
7450

7451
        if (allowcb) {
7452
            DEBUG0("Client run callback for PolicyKit authentication");
7453 7454
            /* Run the authentication callback */
            if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
7455 7456
                remoteError(VIR_ERR_AUTH_FAILED, "%s",
                            _("Failed to collect auth credentials"));
7457 7458
                return -1;
            }
7459
        } else {
7460
            DEBUG0("Client auth callback does not support PolicyKit");
7461 7462
        }
    } else {
7463
        DEBUG0("No auth callback provided");
7464 7465 7466 7467 7468 7469 7470 7471 7472
    }

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, in_open, REMOTE_PROC_AUTH_POLKIT,
              (xdrproc_t) xdr_void, (char *)NULL,
              (xdrproc_t) xdr_remote_auth_polkit_ret, (char *) &ret) != 0) {
        return -1; /* virError already set by call */
    }

7473
    DEBUG0("PolicyKit-0 authentication complete");
7474 7475
    return 0;
}
7476
# endif /* HAVE_POLKIT0 */
7477
#endif /* HAVE_POLKIT */
7478 7479
/*----------------------------------------------------------------------*/

7480 7481 7482 7483
static int remoteDomainEventRegister(virConnectPtr conn,
                                     virConnectDomainEventCallback callback,
                                     void *opaque,
                                     virFreeCallback freecb)
7484
{
7485
    int rv = -1;
7486 7487
    struct private_data *priv = conn->privateData;

7488 7489
    remoteDriverLock(priv);

7490
    if (priv->eventFlushTimer < 0) {
7491
         remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
7492
         goto done;
7493
    }
7494
    if (virDomainEventCallbackListAdd(conn, priv->callbackList,
7495
                                      callback, opaque, freecb) < 0) {
7496
         remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
7497
         goto done;
7498 7499
    }

7500
    if (virDomainEventCallbackListCountID(conn, priv->callbackList, VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 1) {
7501 7502 7503 7504
        /* Tell the server when we are the first callback deregistering */
        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER,
                (xdrproc_t) xdr_void, (char *) NULL,
                (xdrproc_t) xdr_void, (char *) NULL) == -1)
7505
            goto done;
7506 7507
    }

7508 7509 7510
    rv = 0;

done:
7511
    remoteDriverUnlock(priv);
7512
    return rv;
7513 7514
}

7515 7516
static int remoteDomainEventDeregister(virConnectPtr conn,
                                       virConnectDomainEventCallback callback)
7517 7518
{
    struct private_data *priv = conn->privateData;
7519
    int rv = -1;
7520

7521 7522
    remoteDriverLock(priv);

7523 7524 7525
    if (priv->domainEventDispatching) {
        if (virDomainEventCallbackListMarkDelete(conn, priv->callbackList,
                                                 callback) < 0) {
7526
            remoteError(VIR_ERR_RPC, "%s", _("marking cb for deletion"));
7527
            goto done;
7528 7529 7530 7531
        }
    } else {
        if (virDomainEventCallbackListRemove(conn, priv->callbackList,
                                             callback) < 0) {
7532
            remoteError(VIR_ERR_RPC, "%s", _("removing cb from list"));
7533 7534
            goto done;
        }
7535
    }
7536

7537 7538 7539 7540 7541 7542
    if (virDomainEventCallbackListCountID(conn, priv->callbackList, VIR_DOMAIN_EVENT_ID_LIFECYCLE) == 0) {
        /* Tell the server when we are the last callback deregistering */
        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER,
                  (xdrproc_t) xdr_void, (char *) NULL,
                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
            goto done;
7543 7544
    }

7545 7546 7547
    rv = 0;

done:
7548
    remoteDriverUnlock(priv);
7549
    return rv;
7550
}
7551

7552 7553 7554 7555 7556 7557 7558 7559
/**
 * remoteDomainReadEventLifecycle
 *
 * Read the domain lifecycle event data off the wire
 */
static virDomainEventPtr
remoteDomainReadEventLifecycle(virConnectPtr conn, XDR *xdr)
{
7560
    remote_domain_event_lifecycle_msg msg;
7561 7562 7563 7564 7565
    virDomainPtr dom;
    virDomainEventPtr event = NULL;
    memset (&msg, 0, sizeof msg);

    /* unmarshall parameters, and process it*/
7566
    if (! xdr_remote_domain_event_lifecycle_msg(xdr, &msg) ) {
7567 7568
        remoteError(VIR_ERR_RPC, "%s",
                    _("unable to demarshall lifecycle event"));
7569 7570 7571 7572 7573 7574 7575 7576
        return NULL;
    }

    dom = get_nonnull_domain(conn,msg.dom);
    if (!dom)
        return NULL;

    event = virDomainEventNewFromDom(dom, msg.event, msg.detail);
7577
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_lifecycle_msg, (char *) &msg);
7578 7579 7580 7581 7582 7583

    virDomainFree(dom);
    return event;
}


7584 7585 7586 7587 7588 7589 7590 7591 7592 7593
static virDomainEventPtr
remoteDomainReadEventReboot(virConnectPtr conn, XDR *xdr)
{
    remote_domain_event_reboot_msg msg;
    virDomainPtr dom;
    virDomainEventPtr event = NULL;
    memset (&msg, 0, sizeof msg);

    /* unmarshall parameters, and process it*/
    if (! xdr_remote_domain_event_reboot_msg(xdr, &msg) ) {
7594 7595
        remoteError(VIR_ERR_RPC, "%s",
                    _("unable to demarshall reboot event"));
7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610
        return NULL;
    }

    dom = get_nonnull_domain(conn,msg.dom);
    if (!dom)
        return NULL;

    event = virDomainEventRebootNewFromDom(dom);
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_reboot_msg, (char *) &msg);

    virDomainFree(dom);
    return event;
}


7611 7612 7613 7614 7615 7616 7617 7618 7619 7620
static virDomainEventPtr
remoteDomainReadEventRTCChange(virConnectPtr conn, XDR *xdr)
{
    remote_domain_event_rtc_change_msg msg;
    virDomainPtr dom;
    virDomainEventPtr event = NULL;
    memset (&msg, 0, sizeof msg);

    /* unmarshall parameters, and process it*/
    if (! xdr_remote_domain_event_rtc_change_msg(xdr, &msg) ) {
7621 7622
        remoteError(VIR_ERR_RPC, "%s",
                    _("unable to demarshall reboot event"));
7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637
        return NULL;
    }

    dom = get_nonnull_domain(conn,msg.dom);
    if (!dom)
        return NULL;

    event = virDomainEventRTCChangeNewFromDom(dom, msg.offset);
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_rtc_change_msg, (char *) &msg);

    virDomainFree(dom);
    return event;
}


7638 7639 7640 7641 7642 7643 7644 7645 7646 7647
static virDomainEventPtr
remoteDomainReadEventWatchdog(virConnectPtr conn, XDR *xdr)
{
    remote_domain_event_watchdog_msg msg;
    virDomainPtr dom;
    virDomainEventPtr event = NULL;
    memset (&msg, 0, sizeof msg);

    /* unmarshall parameters, and process it*/
    if (! xdr_remote_domain_event_watchdog_msg(xdr, &msg) ) {
7648 7649
        remoteError(VIR_ERR_RPC, "%s",
                    _("unable to demarshall reboot event"));
7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664
        return NULL;
    }

    dom = get_nonnull_domain(conn,msg.dom);
    if (!dom)
        return NULL;

    event = virDomainEventWatchdogNewFromDom(dom, msg.action);
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_watchdog_msg, (char *) &msg);

    virDomainFree(dom);
    return event;
}


7665 7666 7667 7668 7669 7670 7671 7672 7673 7674
static virDomainEventPtr
remoteDomainReadEventIOError(virConnectPtr conn, XDR *xdr)
{
    remote_domain_event_io_error_msg msg;
    virDomainPtr dom;
    virDomainEventPtr event = NULL;
    memset (&msg, 0, sizeof msg);

    /* unmarshall parameters, and process it*/
    if (! xdr_remote_domain_event_io_error_msg(xdr, &msg) ) {
7675 7676
        remoteError(VIR_ERR_RPC, "%s",
                    _("unable to demarshall reboot event"));
7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694
        return NULL;
    }

    dom = get_nonnull_domain(conn,msg.dom);
    if (!dom)
        return NULL;

    event = virDomainEventIOErrorNewFromDom(dom,
                                            msg.srcPath,
                                            msg.devAlias,
                                            msg.action);
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_io_error_msg, (char *) &msg);

    virDomainFree(dom);
    return event;
}


7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725
static virDomainEventPtr
remoteDomainReadEventIOErrorReason(virConnectPtr conn, XDR *xdr)
{
    remote_domain_event_io_error_reason_msg msg;
    virDomainPtr dom;
    virDomainEventPtr event = NULL;
    memset (&msg, 0, sizeof msg);

    /* unmarshall parameters, and process it*/
    if (! xdr_remote_domain_event_io_error_reason_msg(xdr, &msg) ) {
        remoteError(VIR_ERR_RPC, "%s",
                    _("unable to demarshall reboot event"));
        return NULL;
    }

    dom = get_nonnull_domain(conn,msg.dom);
    if (!dom)
        return NULL;

    event = virDomainEventIOErrorReasonNewFromDom(dom,
                                                  msg.srcPath,
                                                  msg.devAlias,
                                                  msg.action,
                                                  msg.reason);
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_io_error_reason_msg, (char *) &msg);

    virDomainFree(dom);
    return event;
}


7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740
static virDomainEventPtr
remoteDomainReadEventGraphics(virConnectPtr conn, XDR *xdr)
{
    remote_domain_event_graphics_msg msg;
    virDomainPtr dom;
    virDomainEventPtr event = NULL;
    virDomainEventGraphicsAddressPtr localAddr = NULL;
    virDomainEventGraphicsAddressPtr remoteAddr = NULL;
    virDomainEventGraphicsSubjectPtr subject = NULL;
    int i;

    memset (&msg, 0, sizeof msg);

    /* unmarshall parameters, and process it*/
    if (! xdr_remote_domain_event_graphics_msg(xdr, &msg) ) {
7741 7742
        remoteError(VIR_ERR_RPC, "%s",
                    _("unable to demarshall reboot event"));
7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810
        return NULL;
    }

    dom = get_nonnull_domain(conn,msg.dom);
    if (!dom)
        return NULL;

    if (VIR_ALLOC(localAddr) < 0)
        goto no_memory;
    localAddr->family = msg.local.family;
    if (!(localAddr->service = strdup(msg.local.service)) ||
        !(localAddr->node = strdup(msg.local.node)))
        goto no_memory;

    if (VIR_ALLOC(remoteAddr) < 0)
        goto no_memory;
    remoteAddr->family = msg.remote.family;
    if (!(remoteAddr->service = strdup(msg.remote.service)) ||
        !(remoteAddr->node = strdup(msg.remote.node)))
        goto no_memory;

    if (VIR_ALLOC(subject) < 0)
        goto no_memory;
    if (VIR_ALLOC_N(subject->identities, msg.subject.subject_len) < 0)
        goto no_memory;
    subject->nidentity = msg.subject.subject_len;
    for (i = 0 ; i < subject->nidentity ; i++) {
        if (!(subject->identities[i].type = strdup(msg.subject.subject_val[i].type)) ||
            !(subject->identities[i].name = strdup(msg.subject.subject_val[i].name)))
            goto no_memory;
    }

    event = virDomainEventGraphicsNewFromDom(dom,
                                             msg.phase,
                                             localAddr,
                                             remoteAddr,
                                             msg.authScheme,
                                             subject);
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_graphics_msg, (char *) &msg);

    virDomainFree(dom);
    return event;

no_memory:
    xdr_free ((xdrproc_t) &xdr_remote_domain_event_graphics_msg, (char *) &msg);

    if (localAddr) {
        VIR_FREE(localAddr->service);
        VIR_FREE(localAddr->node);
        VIR_FREE(localAddr);
    }
    if (remoteAddr) {
        VIR_FREE(remoteAddr->service);
        VIR_FREE(remoteAddr->node);
        VIR_FREE(remoteAddr);
    }
    if (subject) {
        for (i = 0 ; i < subject->nidentity ; i++) {
            VIR_FREE(subject->identities[i].type);
            VIR_FREE(subject->identities[i].name);
        }
        VIR_FREE(subject->identities);
        VIR_FREE(subject);
    }
    return NULL;
}


J
Jim Meyering 已提交
7811
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
7812 7813 7814 7815 7816 7817 7818
remoteSecretOpen (virConnectPtr conn,
                  virConnectAuthPtr auth,
                  int flags)
{
    if (inside_daemon)
        return VIR_DRV_OPEN_DECLINED;

J
Jim Meyering 已提交
7819
    if (conn->driver &&
7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911
        STREQ (conn->driver->name, "remote")) {
        struct private_data *priv;

        /* If we're here, the remote driver is already
         * in use due to a) a QEMU uri, or b) a remote
         * URI. So we can re-use existing connection
         */
        priv = conn->privateData;
        remoteDriverLock(priv);
        priv->localUses++;
        conn->secretPrivateData = priv;
        remoteDriverUnlock(priv);
        return VIR_DRV_OPEN_SUCCESS;
    } else if (conn->networkDriver &&
               STREQ (conn->networkDriver->name, "remote")) {
        struct private_data *priv = conn->networkPrivateData;
        remoteDriverLock(priv);
        conn->secretPrivateData = priv;
        priv->localUses++;
        remoteDriverUnlock(priv);
        return VIR_DRV_OPEN_SUCCESS;
    } else {
        /* Using a non-remote driver, so we need to open a
         * new connection for secret APIs, forcing it to
         * use the UNIX transport.
         */
        struct private_data *priv;
        int ret;
        ret = remoteOpenSecondaryDriver(conn,
                                        auth,
                                        flags,
                                        &priv);
        if (ret == VIR_DRV_OPEN_SUCCESS)
            conn->secretPrivateData = priv;
        return ret;
    }
}

static int
remoteSecretClose (virConnectPtr conn)
{
    int rv = 0;
    struct private_data *priv = conn->secretPrivateData;

    conn->secretPrivateData = NULL;
    remoteDriverLock(priv);
    priv->localUses--;
    if (!priv->localUses) {
        rv = doRemoteClose(conn, priv);
        remoteDriverUnlock(priv);
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
    }
    if (priv)
        remoteDriverUnlock(priv);
    return rv;
}

static int
remoteSecretNumOfSecrets (virConnectPtr conn)
{
    int rv = -1;
    remote_num_of_secrets_ret ret;
    struct private_data *priv = conn->secretPrivateData;

    remoteDriverLock (priv);

    memset (&ret, 0, sizeof (ret));
    if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_SECRETS,
              (xdrproc_t) xdr_void, (char *) NULL,
              (xdrproc_t) xdr_remote_num_of_secrets_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.num;

done:
    remoteDriverUnlock (priv);
    return rv;
}

static int
remoteSecretListSecrets (virConnectPtr conn, char **uuids, int maxuuids)
{
    int rv = -1;
    int i;
    remote_list_secrets_args args;
    remote_list_secrets_ret ret;
    struct private_data *priv = conn->secretPrivateData;

    remoteDriverLock(priv);

    if (maxuuids > REMOTE_SECRET_UUID_LIST_MAX) {
7912 7913
        remoteError(VIR_ERR_RPC, _("too many remote secret UUIDs: %d > %d"),
                    maxuuids, REMOTE_SECRET_UUID_LIST_MAX);
7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924
        goto done;
    }
    args.maxuuids = maxuuids;

    memset (&ret, 0, sizeof ret);
    if (call (conn, priv, 0, REMOTE_PROC_LIST_SECRETS,
              (xdrproc_t) xdr_remote_list_secrets_args, (char *) &args,
              (xdrproc_t) xdr_remote_list_secrets_ret, (char *) &ret) == -1)
        goto done;

    if (ret.uuids.uuids_len > maxuuids) {
7925 7926
        remoteError(VIR_ERR_RPC, _("too many remote secret UUIDs: %d > %d"),
                    ret.uuids.uuids_len, maxuuids);
7927 7928 7929 7930 7931 7932 7933
        goto cleanup;
    }

    /* This call is caller-frees.  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
7934
    for (i = 0; i < ret.uuids.uuids_len; ++i) {
7935 7936
        uuids[i] = strdup (ret.uuids.uuids_val[i]);

7937 7938 7939 7940
        if (uuids[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(uuids[i]);

7941
            virReportOOMError();
7942 7943 7944 7945
            goto cleanup;
        }
    }

7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956
    rv = ret.uuids.uuids_len;

cleanup:
    xdr_free ((xdrproc_t) xdr_remote_list_secrets_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

static virSecretPtr
7957
remoteSecretLookupByUUID (virConnectPtr conn, const unsigned char *uuid)
7958 7959
{
    virSecretPtr rv = NULL;
7960 7961
    remote_secret_lookup_by_uuid_args args;
    remote_secret_lookup_by_uuid_ret ret;
7962 7963 7964 7965
    struct private_data *priv = conn->secretPrivateData;

    remoteDriverLock (priv);

7966
    memcpy (args.uuid, uuid, VIR_UUID_BUFLEN);
7967 7968

    memset (&ret, 0, sizeof (ret));
7969 7970 7971
    if (call (conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_UUID,
              (xdrproc_t) xdr_remote_secret_lookup_by_uuid_args, (char *) &args,
              (xdrproc_t) xdr_remote_secret_lookup_by_uuid_ret, (char *) &ret) == -1)
7972 7973 7974
        goto done;

    rv = get_nonnull_secret (conn, ret.secret);
7975
    xdr_free ((xdrproc_t) xdr_remote_secret_lookup_by_uuid_ret,
7976 7977 7978 7979 7980 7981 7982
              (char *) &ret);

done:
    remoteDriverUnlock (priv);
    return rv;
}

7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010
static virSecretPtr
remoteSecretLookupByUsage (virConnectPtr conn, int usageType, const char *usageID)
{
    virSecretPtr rv = NULL;
    remote_secret_lookup_by_usage_args args;
    remote_secret_lookup_by_usage_ret ret;
    struct private_data *priv = conn->secretPrivateData;

    remoteDriverLock (priv);

    args.usageType = usageType;
    args.usageID = (char *)usageID;

    memset (&ret, 0, sizeof (ret));
    if (call (conn, priv, 0, REMOTE_PROC_SECRET_LOOKUP_BY_USAGE,
              (xdrproc_t) xdr_remote_secret_lookup_by_usage_args, (char *) &args,
              (xdrproc_t) xdr_remote_secret_lookup_by_usage_ret, (char *) &ret) == -1)
        goto done;

    rv = get_nonnull_secret (conn, ret.secret);
    xdr_free ((xdrproc_t) xdr_remote_secret_lookup_by_usage_ret,
              (char *) &ret);

done:
    remoteDriverUnlock (priv);
    return rv;
}

8011 8012 8013 8014 8015
static virSecretPtr
remoteSecretDefineXML (virConnectPtr conn, const char *xml, unsigned int flags)
{
    virSecretPtr rv = NULL;
    remote_secret_define_xml_args args;
8016
    remote_secret_define_xml_ret ret;
8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030
    struct private_data *priv = conn->secretPrivateData;

    remoteDriverLock (priv);

    args.xml = (char *) xml;
    args.flags = flags;

    memset (&ret, 0, sizeof (ret));
    if (call (conn, priv, 0, REMOTE_PROC_SECRET_DEFINE_XML,
              (xdrproc_t) xdr_remote_secret_define_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_secret_define_xml_ret, (char *) &ret) == -1)
        goto done;

    rv = get_nonnull_secret (conn, ret.secret);
8031
    xdr_free ((xdrproc_t) xdr_remote_secret_define_xml_ret,
8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143
              (char *) &ret);

done:
    remoteDriverUnlock (priv);
    return rv;
}

static char *
remoteSecretGetXMLDesc (virSecretPtr secret, unsigned int flags)
{
    char *rv = NULL;
    remote_secret_get_xml_desc_args args;
    remote_secret_get_xml_desc_ret ret;
    struct private_data *priv = secret->conn->secretPrivateData;

    remoteDriverLock (priv);

    make_nonnull_secret (&args.secret, secret);
    args.flags = flags;

    memset (&ret, 0, sizeof (ret));
    if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_GET_XML_DESC,
              (xdrproc_t) xdr_remote_secret_get_xml_desc_args, (char *) &args,
              (xdrproc_t) xdr_remote_secret_get_xml_desc_ret, (char *) &ret) == -1)
        goto done;

    /* Caller frees. */
    rv = ret.xml;

done:
    remoteDriverUnlock (priv);
    return rv;
}

static int
remoteSecretSetValue (virSecretPtr secret, const unsigned char *value,
                      size_t value_size, unsigned int flags)
{
    int rv = -1;
    remote_secret_set_value_args args;
    struct private_data *priv = secret->conn->secretPrivateData;

    remoteDriverLock (priv);

    make_nonnull_secret (&args.secret, secret);
    args.value.value_len = value_size;
    args.value.value_val = (char *) value;
    args.flags = flags;

    if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_SET_VALUE,
              (xdrproc_t) xdr_remote_secret_set_value_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock (priv);
    return rv;
}

static unsigned char *
remoteSecretGetValue (virSecretPtr secret, size_t *value_size,
                      unsigned int flags)
{
    unsigned char *rv = NULL;
    remote_secret_get_value_args args;
    remote_secret_get_value_ret ret;
    struct private_data *priv = secret->conn->secretPrivateData;

    remoteDriverLock (priv);

    make_nonnull_secret (&args.secret, secret);
    args.flags = flags;

    memset (&ret, 0, sizeof (ret));
    if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_GET_VALUE,
              (xdrproc_t) xdr_remote_secret_get_value_args, (char *) &args,
              (xdrproc_t) xdr_remote_secret_get_value_ret, (char *) &ret) == -1)
        goto done;

    *value_size = ret.value.value_len;
    rv = (unsigned char *) ret.value.value_val; /* Caller frees. */

done:
    remoteDriverUnlock (priv);
    return rv;
}

static int
remoteSecretUndefine (virSecretPtr secret)
{
    int rv = -1;
    remote_secret_undefine_args args;
    struct private_data *priv = secret->conn->secretPrivateData;

    remoteDriverLock (priv);

    make_nonnull_secret (&args.secret, secret);

    if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_UNDEFINE,
              (xdrproc_t) xdr_remote_secret_undefine_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock (priv);
    return rv;
}

8144 8145 8146 8147 8148 8149 8150 8151 8152 8153

static struct private_stream_data *
remoteStreamOpen(virStreamPtr st,
                 int output ATTRIBUTE_UNUSED,
                 unsigned int proc_nr,
                 unsigned int serial)
{
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *stpriv;

8154
    if (VIR_ALLOC(stpriv) < 0) {
8155
        virReportOOMError();
8156
        return NULL;
8157
    }
8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169

    /* Initialize call object used to receive replies */
    stpriv->proc_nr = proc_nr;
    stpriv->serial = serial;

    stpriv->next = priv->streams;
    priv->streams = stpriv;

    return stpriv;
}


8170 8171 8172 8173 8174 8175
static void
remoteStreamEventTimerUpdate(struct private_stream_data *privst)
{
    if (!privst->cb)
        return;

8176 8177 8178 8179 8180
    VIR_DEBUG("Check timer offset=%d %d", privst->incomingOffset, privst->cbEvents);
    if ((privst->incomingOffset &&
         (privst->cbEvents & VIR_STREAM_EVENT_READABLE)) ||
        (privst->cbEvents & VIR_STREAM_EVENT_WRITABLE)) {
        VIR_DEBUG0("Enabling event timer");
8181
        virEventUpdateTimeout(privst->cbTimer, 0);
8182 8183 8184 8185
    } else {
        VIR_DEBUG0("Disabling event timer");
        virEventUpdateTimeout(privst->cbTimer, -1);
    }
8186 8187 8188
}


8189 8190 8191 8192 8193 8194
static int
remoteStreamPacket(virStreamPtr st,
                   int status,
                   const char *data,
                   size_t nbytes)
{
8195
    DEBUG("st=%p status=%d data=%p nbytes=%zu", st, status, data, nbytes);
8196 8197 8198 8199 8200
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *privst = st->privateData;
    XDR xdr;
    struct remote_thread_call *thiscall;
    remote_message_header hdr;
8201
    int ret;
8202 8203 8204 8205

    memset(&hdr, 0, sizeof hdr);

    if (VIR_ALLOC(thiscall) < 0) {
8206
        virReportOOMError();
8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218
        return -1;
    }

    thiscall->mode = REMOTE_MODE_WAIT_TX;
    thiscall->serial = privst->serial;
    thiscall->proc_nr = privst->proc_nr;
    if (status == REMOTE_OK ||
        status == REMOTE_ERROR)
        thiscall->want_reply = 1;

    if (virCondInit(&thiscall->cond) < 0) {
        VIR_FREE(thiscall);
8219 8220
        remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("cannot initialize mutex"));
8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244
        return -1;
    }

    /* Don't fill in any other fields in 'thiscall' since
     * we're not expecting a reply for this */

    hdr.prog = REMOTE_PROGRAM;
    hdr.vers = REMOTE_PROTOCOL_VERSION;
    hdr.proc = privst->proc_nr;
    hdr.type = REMOTE_STREAM;
    hdr.serial = privst->serial;
    hdr.status = status;


    /* Length must include the length word itself (always encoded in
     * 4 bytes as per RFC 4506), so offset start length. We write this
     * later.
     */
    thiscall->bufferLength = REMOTE_MESSAGE_HEADER_XDR_LEN;

    /* Serialise header followed by args. */
    xdrmem_create (&xdr, thiscall->buffer + thiscall->bufferLength,
                   REMOTE_MESSAGE_MAX, XDR_ENCODE);
    if (!xdr_remote_message_header (&xdr, &hdr)) {
8245
        remoteError(VIR_ERR_RPC, "%s", _("xdr_remote_message_header failed"));
8246 8247 8248 8249 8250 8251 8252 8253
        goto error;
    }

    thiscall->bufferLength += xdr_getpos (&xdr);
    xdr_destroy (&xdr);

    if (status == REMOTE_CONTINUE) {
        if (((4 + REMOTE_MESSAGE_MAX) - thiscall->bufferLength) < nbytes) {
8254 8255
            remoteError(VIR_ERR_RPC, _("data size %zu too large for payload %d"),
                        nbytes, ((4 + REMOTE_MESSAGE_MAX) - thiscall->bufferLength));
8256 8257 8258 8259 8260 8261 8262 8263 8264 8265
            goto error;
        }

        memcpy(thiscall->buffer + thiscall->bufferLength, data, nbytes);
        thiscall->bufferLength += nbytes;
    }

    /* Go back to packet start and encode the length word. */
    xdrmem_create (&xdr, thiscall->buffer, REMOTE_MESSAGE_HEADER_XDR_LEN, XDR_ENCODE);
    if (!xdr_u_int (&xdr, &thiscall->bufferLength)) {
8266
        remoteError(VIR_ERR_RPC, "%s", _("xdr_u_int (length word)"));
8267 8268 8269 8270
        goto error;
    }
    xdr_destroy (&xdr);

8271 8272 8273
    ret = remoteIO(st->conn, priv, 0, thiscall);
    VIR_FREE(thiscall);
    if (ret < 0)
8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290
        return -1;

    return nbytes;

error:
    xdr_destroy (&xdr);
    VIR_FREE(thiscall);
    return -1;
}

static int
remoteStreamHasError(virStreamPtr st) {
    struct private_stream_data *privst = st->privateData;
    if (!privst->has_error) {
        return 0;
    }

8291
    VIR_DEBUG0("Raising async error");
8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339
    virRaiseErrorFull(st->conn,
                      __FILE__, __FUNCTION__, __LINE__,
                      privst->err.domain,
                      privst->err.code,
                      privst->err.level,
                      privst->err.str1 ? *privst->err.str1 : NULL,
                      privst->err.str2 ? *privst->err.str2 : NULL,
                      privst->err.str3 ? *privst->err.str3 : NULL,
                      privst->err.int1,
                      privst->err.int2,
                      "%s", privst->err.message ? *privst->err.message : NULL);

    return 1;
}

static void
remoteStreamRelease(virStreamPtr st)
{
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *privst = st->privateData;

    if (priv->streams == privst)
        priv->streams = privst->next;
    else {
        struct private_stream_data *tmp = priv->streams;
        while (tmp && tmp->next) {
            if (tmp->next == privst) {
                tmp->next = privst->next;
                break;
            }
        }
    }

    if (privst->has_error)
        xdr_free((xdrproc_t)xdr_remote_error,  (char *)&privst->err);

    VIR_FREE(privst);

    st->driver = NULL;
    st->privateData = NULL;
}


static int
remoteStreamSend(virStreamPtr st,
                 const char *data,
                 size_t nbytes)
{
8340
    DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368
    struct private_data *priv = st->conn->privateData;
    int rv = -1;

    remoteDriverLock(priv);

    if (remoteStreamHasError(st))
        goto cleanup;

    rv = remoteStreamPacket(st,
                            REMOTE_CONTINUE,
                            data,
                            nbytes);

cleanup:
    if (rv == -1)
        remoteStreamRelease(st);

    remoteDriverUnlock(priv);

    return rv;
}


static int
remoteStreamRecv(virStreamPtr st,
                 char *data,
                 size_t nbytes)
{
8369
    DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *privst = st->privateData;
    int rv = -1;

    remoteDriverLock(priv);

    if (remoteStreamHasError(st))
        goto cleanup;

    if (!privst->incomingOffset) {
        struct remote_thread_call *thiscall;
8381
        int ret;
8382

8383 8384 8385 8386 8387 8388
        if (st->flags & VIR_STREAM_NONBLOCK) {
            DEBUG0("Non-blocking mode and no data available");
            rv = -2;
            goto cleanup;
        }

8389
        if (VIR_ALLOC(thiscall) < 0) {
8390
            virReportOOMError();
8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402
            goto cleanup;
        }

        /* We're not really doing an RPC calls, so we're
         * skipping straight to RX part */
        thiscall->mode = REMOTE_MODE_WAIT_RX;
        thiscall->serial = privst->serial;
        thiscall->proc_nr = privst->proc_nr;
        thiscall->want_reply = 1;

        if (virCondInit(&thiscall->cond) < 0) {
            VIR_FREE(thiscall);
8403 8404
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("cannot initialize mutex"));
8405 8406 8407
            goto cleanup;
        }

8408 8409 8410
        ret = remoteIO(st->conn, priv, 0, thiscall);
        VIR_FREE(thiscall);
        if (ret < 0)
8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431
            goto cleanup;
    }

    DEBUG("After IO %d", privst->incomingOffset);
    if (privst->incomingOffset) {
        int want = privst->incomingOffset;
        if (want > nbytes)
            want = nbytes;
        memcpy(data, privst->incoming, want);
        if (want < privst->incomingOffset) {
            memmove(privst->incoming, privst->incoming + want, privst->incomingOffset - want);
            privst->incomingOffset -= want;
        } else {
            VIR_FREE(privst->incoming);
            privst->incomingOffset = privst->incomingLength = 0;
        }
        rv = want;
    } else {
        rv = 0;
    }

8432 8433
    remoteStreamEventTimerUpdate(privst);

8434 8435 8436 8437 8438 8439 8440 8441 8442 8443
    DEBUG("Done %d", rv);

cleanup:
    if (rv == -1)
        remoteStreamRelease(st);
    remoteDriverUnlock(priv);

    return rv;
}

8444 8445 8446 8447 8448 8449 8450

static void
remoteStreamEventTimer(int timer ATTRIBUTE_UNUSED, void *opaque)
{
    virStreamPtr st = opaque;
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *privst = st->privateData;
8451
    int events = 0;
8452 8453

    remoteDriverLock(priv);
8454

8455 8456
    if (privst->cb &&
        (privst->cbEvents & VIR_STREAM_EVENT_READABLE) &&
8457 8458 8459 8460 8461 8462 8463
        privst->incomingOffset)
        events |= VIR_STREAM_EVENT_READABLE;
    if (privst->cb &&
        (privst->cbEvents & VIR_STREAM_EVENT_WRITABLE))
        events |= VIR_STREAM_EVENT_WRITABLE;
    VIR_DEBUG("Got Timer dispatch %d %d offset=%d", events, privst->cbEvents, privst->incomingOffset);
    if (events) {
8464 8465 8466 8467 8468 8469
        virStreamEventCallback cb = privst->cb;
        void *cbOpaque = privst->cbOpaque;
        virFreeCallback cbFree = privst->cbFree;

        privst->cbDispatch = 1;
        remoteDriverUnlock(priv);
8470
        (cb)(st, events, cbOpaque);
8471 8472 8473 8474 8475 8476
        remoteDriverLock(priv);
        privst->cbDispatch = 0;

        if (!privst->cb && cbFree)
            (cbFree)(cbOpaque);
    }
8477

8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489
    remoteDriverUnlock(priv);
}


static void
remoteStreamEventTimerFree(void *opaque)
{
    virStreamPtr st = opaque;
    virUnrefStream(st);
}


8490
static int
8491 8492 8493 8494 8495
remoteStreamEventAddCallback(virStreamPtr st,
                             int events,
                             virStreamEventCallback cb,
                             void *opaque,
                             virFreeCallback ff)
8496
{
8497 8498 8499 8500 8501 8502 8503 8504
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *privst = st->privateData;
    int ret = -1;

    remoteDriverLock(priv);

    if (privst->cb) {
        remoteError(VIR_ERR_INTERNAL_ERROR,
8505
                    "%s", _("multiple stream callbacks not supported"));
8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523
        goto cleanup;
    }

    virStreamRef(st);
    if ((privst->cbTimer =
         virEventAddTimeout(-1,
                            remoteStreamEventTimer,
                            st,
                            remoteStreamEventTimerFree)) < 0) {
        virUnrefStream(st);
        goto cleanup;
    }

    privst->cb = cb;
    privst->cbOpaque = opaque;
    privst->cbFree = ff;
    privst->cbEvents = events;

8524 8525
    remoteStreamEventTimerUpdate(privst);

8526 8527 8528 8529 8530
    ret = 0;

cleanup:
    remoteDriverUnlock(priv);
    return ret;
8531 8532 8533
}

static int
8534 8535
remoteStreamEventUpdateCallback(virStreamPtr st,
                                int events)
8536
{
8537 8538 8539 8540 8541 8542 8543 8544
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *privst = st->privateData;
    int ret = -1;

    remoteDriverLock(priv);

    if (!privst->cb) {
        remoteError(VIR_ERR_INTERNAL_ERROR,
8545
                    "%s", _("no stream callback registered"));
8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557
        goto cleanup;
    }

    privst->cbEvents = events;

    remoteStreamEventTimerUpdate(privst);

    ret = 0;

cleanup:
    remoteDriverUnlock(priv);
    return ret;
8558 8559 8560 8561
}


static int
8562
remoteStreamEventRemoveCallback(virStreamPtr st)
8563
{
8564 8565 8566 8567 8568 8569 8570 8571
    struct private_data *priv = st->conn->privateData;
    struct private_stream_data *privst = st->privateData;
    int ret = -1;

    remoteDriverLock(priv);

    if (!privst->cb) {
        remoteError(VIR_ERR_INTERNAL_ERROR,
8572
                    "%s", _("no stream callback registered"));
8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589
        goto cleanup;
    }

    if (!privst->cbDispatch &&
        privst->cbFree)
        (privst->cbFree)(privst->cbOpaque);
    privst->cb = NULL;
    privst->cbOpaque = NULL;
    privst->cbFree = NULL;
    privst->cbEvents = 0;
    virEventRemoveTimeout(privst->cbTimer);

    ret = 0;

cleanup:
    remoteDriverUnlock(priv);
    return ret;
8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650
}

static int
remoteStreamFinish(virStreamPtr st)
{
    struct private_data *priv = st->conn->privateData;
    int ret = -1;

    remoteDriverLock(priv);

    if (remoteStreamHasError(st))
        goto cleanup;

    ret = remoteStreamPacket(st,
                             REMOTE_OK,
                             NULL,
                             0);

cleanup:
    remoteStreamRelease(st);

    remoteDriverUnlock(priv);
    return ret;
}

static int
remoteStreamAbort(virStreamPtr st)
{
    struct private_data *priv = st->conn->privateData;
    int ret = -1;

    remoteDriverLock(priv);

    if (remoteStreamHasError(st))
        goto cleanup;

    ret = remoteStreamPacket(st,
                             REMOTE_ERROR,
                             NULL,
                             0);

cleanup:
    remoteStreamRelease(st);

    remoteDriverUnlock(priv);
    return ret;
}



static virStreamDriver remoteStreamDrv = {
    .streamRecv = remoteStreamRecv,
    .streamSend = remoteStreamSend,
    .streamFinish = remoteStreamFinish,
    .streamAbort = remoteStreamAbort,
    .streamAddCallback = remoteStreamEventAddCallback,
    .streamUpdateCallback = remoteStreamEventUpdateCallback,
    .streamRemoveCallback = remoteStreamEventRemoveCallback,
};


C
Chris Lalancette 已提交
8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691
static int
remoteDomainMigratePrepareTunnel(virConnectPtr conn,
                                 virStreamPtr st,
                                 unsigned long flags,
                                 const char *dname,
                                 unsigned long resource,
                                 const char *dom_xml)
{
    struct private_data *priv = conn->privateData;
    struct private_stream_data *privst = NULL;
    int rv = -1;
    remote_domain_migrate_prepare_tunnel_args args;

    remoteDriverLock(priv);

    if (!(privst = remoteStreamOpen(st, 1, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL, priv->counter)))
        goto done;

    st->driver = &remoteStreamDrv;
    st->privateData = privst;

    args.flags = flags;
    args.dname = dname == NULL ? NULL : (char **) &dname;
    args.resource = resource;
    args.dom_xml = (char *) dom_xml;

    if (call(conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL,
             (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel_args, (char *) &args,
             (xdrproc_t) xdr_void, NULL) == -1) {
        remoteStreamRelease(st);
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);

    return rv;
}

J
Jiri Denemark 已提交
8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718

static int
remoteCPUCompare(virConnectPtr conn, const char *xmlDesc,
                 unsigned int flags ATTRIBUTE_UNUSED)
{
    struct private_data *priv = conn->privateData;
    remote_cpu_compare_args args;
    remote_cpu_compare_ret ret;
    int rv = VIR_CPU_COMPARE_ERROR;

    remoteDriverLock(priv);

    args.xml = (char *) xmlDesc;

    memset(&ret, 0, sizeof (ret));
    if (call(conn, priv, 0, REMOTE_PROC_CPU_COMPARE,
             (xdrproc_t) xdr_remote_cpu_compare_args, (char *) &args,
             (xdrproc_t) xdr_remote_cpu_compare_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.result;

done:
    remoteDriverUnlock(priv);
    return rv;
}

8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749

static char *
remoteCPUBaseline(virConnectPtr conn,
                  const char **xmlCPUs,
                  unsigned int ncpus,
                  unsigned int flags)
{
    struct private_data *priv = conn->privateData;
    remote_cpu_baseline_args args;
    remote_cpu_baseline_ret ret;
    char *cpu = NULL;

    remoteDriverLock(priv);

    args.xmlCPUs.xmlCPUs_len = ncpus;
    args.xmlCPUs.xmlCPUs_val = (char **) xmlCPUs;
    args.flags = flags;

    memset(&ret, 0, sizeof (ret));
    if (call(conn, priv, 0, REMOTE_PROC_CPU_BASELINE,
             (xdrproc_t) xdr_remote_cpu_baseline_args, (char *) &args,
             (xdrproc_t) xdr_remote_cpu_baseline_ret, (char *) &ret) == -1)
        goto done;

    cpu = ret.cpu;

done:
    remoteDriverUnlock(priv);
    return cpu;
}

8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789

static int
remoteDomainGetJobInfo (virDomainPtr domain, virDomainJobInfoPtr info)
{
    int rv = -1;
    remote_domain_get_job_info_args args;
    remote_domain_get_job_info_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_JOB_INFO,
              (xdrproc_t) xdr_remote_domain_get_job_info_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_get_job_info_ret, (char *) &ret) == -1)
        goto done;

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

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}


8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813
static int
remoteDomainAbortJob (virDomainPtr domain)
{
    int rv = -1;
    remote_domain_abort_job_args args;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.dom, domain);

    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_ABORT_JOB,
              (xdrproc_t) xdr_remote_domain_abort_job_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}


8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842
static int
remoteDomainMigrateSetMaxDowntime(virDomainPtr domain,
                                  unsigned long long downtime,
                                  unsigned int flags)
{
    struct private_data *priv = domain->conn->privateData;
    remote_domain_migrate_set_max_downtime_args args;
    int rv = -1;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.dom, domain);
    args.downtime = downtime;
    args.flags = flags;

    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME,
             (xdrproc_t) xdr_remote_domain_migrate_set_max_downtime_args,
             (char *) &args,
             (xdrproc_t) xdr_void,
             (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}

C
Chris Lalancette 已提交
8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941
static virDomainSnapshotPtr
remoteDomainSnapshotCreateXML(virDomainPtr domain,
                              const char *xmlDesc,
                              unsigned int flags)
{
    virDomainSnapshotPtr snapshot = NULL;
    remote_domain_snapshot_create_xml_args args;
    remote_domain_snapshot_create_xml_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.domain, domain);
    args.xml_desc = (char *) xmlDesc;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML,
              (xdrproc_t) xdr_remote_domain_snapshot_create_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_snapshot_create_xml_ret, (char *) &ret) == -1)
        goto done;

    snapshot = get_nonnull_domain_snapshot(domain, ret.snap);
    xdr_free ((xdrproc_t) &xdr_remote_domain_snapshot_create_xml_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return snapshot;
}


static char *
remoteDomainSnapshotDumpXML(virDomainSnapshotPtr snapshot, unsigned int flags)
{
    char *rv = NULL;
    remote_domain_snapshot_dump_xml_args args;
    remote_domain_snapshot_dump_xml_ret ret;
    struct private_data *priv = snapshot->domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snapshot);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DUMP_XML,
              (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_snapshot_dump_xml_ret, (char *) &ret) == -1)
        goto done;

    /* Caller frees. */
    rv = ret.xml;

done:
    remoteDriverUnlock(priv);
    return rv;
}


static int
remoteDomainSnapshotNum (virDomainPtr domain, unsigned int flags)
{
    int rv = -1;
    remote_domain_snapshot_num_args args;
    remote_domain_snapshot_num_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain (&args.domain, domain);
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_NUM,
              (xdrproc_t) xdr_remote_domain_snapshot_num_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_snapshot_num_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.num;

done:
    remoteDriverUnlock(priv);
    return rv;
}


static int
remoteDomainSnapshotListNames (virDomainPtr domain, char **const names,
                               int nameslen, unsigned int flags)
{
    int rv = -1;
    int i;
    remote_domain_snapshot_list_names_args args;
    remote_domain_snapshot_list_names_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    if (nameslen > REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX) {
8942 8943 8944
        remoteError(VIR_ERR_RPC,
                    _("too many remote domain snapshot names: %d > %d"),
                    nameslen, REMOTE_DOMAIN_SNAPSHOT_LIST_NAMES_MAX);
C
Chris Lalancette 已提交
8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958
        goto done;
    }

    make_nonnull_domain(&args.domain, domain);
    args.nameslen = nameslen;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES,
              (xdrproc_t) xdr_remote_domain_snapshot_list_names_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_snapshot_list_names_ret, (char *) &ret) == -1)
        goto done;

    if (ret.names.names_len > nameslen) {
8959 8960 8961
        remoteError(VIR_ERR_RPC,
                    _("too many remote domain snapshots: %d > %d"),
                    ret.names.names_len, nameslen);
C
Chris Lalancette 已提交
8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127
        goto cleanup;
    }

    /* This call is caller-frees (although that isn't clear from
     * the documentation).  However xdr_free will free up both the
     * names and the list of pointers, so we have to strdup the
     * names here.
     */
    for (i = 0; i < ret.names.names_len; ++i) {
        names[i] = strdup (ret.names.names_val[i]);

        if (names[i] == NULL) {
            for (--i; i >= 0; --i)
                VIR_FREE(names[i]);

            virReportOOMError();
            goto cleanup;
        }
    }

    rv = ret.names.names_len;

cleanup:
    xdr_free ((xdrproc_t) xdr_remote_domain_snapshot_list_names_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}


static virDomainSnapshotPtr
remoteDomainSnapshotLookupByName (virDomainPtr domain, const char *name,
                                  unsigned int flags)
{
    virDomainSnapshotPtr snapshot = NULL;
    remote_domain_snapshot_lookup_by_name_args args;
    remote_domain_snapshot_lookup_by_name_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.domain, domain);
    args.name = (char *) name;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME,
              (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_args, (char *) &args,
              (xdrproc_t) xdr_remote_domain_snapshot_lookup_by_name_ret, (char *) &ret) == -1)
        goto done;

    snapshot = get_nonnull_domain_snapshot (domain, ret.snap);
    xdr_free ((xdrproc_t) &xdr_remote_domain_snapshot_lookup_by_name_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return snapshot;
}


static int
remoteDomainHasCurrentSnapshot(virDomainPtr domain, unsigned int flags)
{
    int rv = -1;
    remote_domain_has_current_snapshot_args args;
    remote_domain_has_current_snapshot_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.domain, domain);
    args.flags = flags;

    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT,
             (xdrproc_t) xdr_remote_domain_has_current_snapshot_args, (char *) &args,
             (xdrproc_t) xdr_remote_domain_has_current_snapshot_ret, (char *) &ret) == -1)
        goto done;

    rv = ret.result;

done:
    remoteDriverUnlock(priv);
    return rv;
}


static virDomainSnapshotPtr
remoteDomainSnapshotCurrent(virDomainPtr domain,
                            unsigned int flags)
{
    virDomainSnapshotPtr snapshot = NULL;
    remote_domain_snapshot_current_args args;
    remote_domain_snapshot_current_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.domain, domain);
    args.flags = flags;

    memset(&ret, 0, sizeof ret);
    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT,
             (xdrproc_t) xdr_remote_domain_snapshot_current_args, (char *) &args,
             (xdrproc_t) xdr_remote_domain_snapshot_current_ret, (char *) &ret) == -1)
        goto done;

    snapshot = get_nonnull_domain_snapshot(domain, ret.snap);
    xdr_free((xdrproc_t) &xdr_remote_domain_snapshot_current_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return snapshot;
}


static int
remoteDomainRevertToSnapshot (virDomainSnapshotPtr snapshot,
                              unsigned int flags)
{
    int rv = -1;
    remote_domain_revert_to_snapshot_args args;
    struct private_data *priv = snapshot->domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snapshot);
    args.flags = flags;

    if (call (snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT,
              (xdrproc_t) xdr_remote_domain_revert_to_snapshot_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}


static int
remoteDomainSnapshotDelete (virDomainSnapshotPtr snapshot,
                            unsigned int flags)
{
    int rv = -1;
    remote_domain_snapshot_delete_args args;
    struct private_data *priv = snapshot->domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain_snapshot(&args.snap, snapshot);
    args.flags = flags;

    if (call (snapshot->domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE,
              (xdrproc_t) xdr_remote_domain_snapshot_delete_args, (char *) &args,
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
        goto done;

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}
9128

9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143
static int remoteDomainEventRegisterAny(virConnectPtr conn,
                                        virDomainPtr dom,
                                        int eventID,
                                        virConnectDomainEventGenericCallback callback,
                                        void *opaque,
                                        virFreeCallback freecb)
{
    int rv = -1;
    struct private_data *priv = conn->privateData;
    remote_domain_events_register_any_args args;
    int callbackID;

    remoteDriverLock(priv);

    if (priv->eventFlushTimer < 0) {
9144
         remoteError(VIR_ERR_NO_SUPPORT, "%s", _("no event support"));
9145 9146 9147 9148 9149 9150
         goto done;
    }

    if ((callbackID = virDomainEventCallbackListAddID(conn, priv->callbackList,
                                                      dom, eventID,
                                                      callback, opaque, freecb)) < 0) {
9151
         remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186
         goto done;
    }

    /* If this is the first callback for this eventID, we need to enable
     * events on the server */
    if (virDomainEventCallbackListCountID(conn, priv->callbackList, eventID) == 1) {
        args.eventID = eventID;

        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY,
                  (xdrproc_t) xdr_remote_domain_events_register_any_args, (char *) &args,
                  (xdrproc_t) xdr_void, (char *)NULL) == -1) {
            virDomainEventCallbackListRemoveID(conn, priv->callbackList, callbackID);
            goto done;
        }
    }

    rv = callbackID;

done:
    remoteDriverUnlock(priv);
    return rv;
}


static int remoteDomainEventDeregisterAny(virConnectPtr conn,
                                          int callbackID)
{
    struct private_data *priv = conn->privateData;
    int rv = -1;
    remote_domain_events_deregister_any_args args;
    int eventID;

    remoteDriverLock(priv);

    if ((eventID = virDomainEventCallbackListEventID(conn, priv->callbackList, callbackID)) < 0) {
9187
        remoteError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
9188 9189 9190 9191 9192 9193
        goto done;
    }

    if (priv->domainEventDispatching) {
        if (virDomainEventCallbackListMarkDeleteID(conn, priv->callbackList,
                                                   callbackID) < 0) {
9194
            remoteError(VIR_ERR_RPC, "%s", _("marking cb for deletion"));
9195 9196 9197 9198 9199
            goto done;
        }
    } else {
        if (virDomainEventCallbackListRemoveID(conn, priv->callbackList,
                                               callbackID) < 0) {
9200
            remoteError(VIR_ERR_RPC, "%s", _("removing cb from list"));
9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223
            goto done;
        }
    }

    /* If that was the last callback for this eventID, we need to disable
     * events on the server */
    if (virDomainEventCallbackListCountID(conn, priv->callbackList, eventID) == 0) {
        args.eventID = eventID;

        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY,
                  (xdrproc_t) xdr_remote_domain_events_deregister_any_args, (char *) &args,
                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
            goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);
    return rv;
}


9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263
static int
remoteDomainOpenConsole(virDomainPtr dom,
                        const char *devname,
                        virStreamPtr st,
                        unsigned int flags)
{
    struct private_data *priv = dom->conn->privateData;
    struct private_stream_data *privst = NULL;
    int rv = -1;
    remote_domain_open_console_args args;

    remoteDriverLock(priv);

    if (!(privst = remoteStreamOpen(st, 1, REMOTE_PROC_DOMAIN_OPEN_CONSOLE, priv->counter)))
        goto done;

    st->driver = &remoteStreamDrv;
    st->privateData = privst;

    make_nonnull_domain (&args.domain, dom);
    args.devname = devname ? (char **)&devname : NULL;
    args.flags = flags;

    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_OPEN_CONSOLE,
             (xdrproc_t) xdr_remote_domain_open_console_args, (char *) &args,
             (xdrproc_t) xdr_void, NULL) == -1) {
        remoteStreamRelease(st);
        goto done;
    }

    rv = 0;

done:
    remoteDriverUnlock(priv);

    return rv;

}


9264 9265
/*----------------------------------------------------------------------*/

C
Chris Lalancette 已提交
9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281
static int
remoteQemuDomainMonitorCommand (virDomainPtr domain, const char *cmd,
                                char **result, unsigned int flags)
{
    int rv = -1;
    qemu_monitor_command_args args;
    qemu_monitor_command_ret ret;
    struct private_data *priv = domain->conn->privateData;

    remoteDriverLock(priv);

    make_nonnull_domain(&args.domain, domain);
    args.cmd = (char *)cmd;
    args.flags = flags;

    memset (&ret, 0, sizeof ret);
9282
    if (call (domain->conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_MONITOR_COMMAND,
C
Chris Lalancette 已提交
9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304
              (xdrproc_t) xdr_qemu_monitor_command_args, (char *) &args,
              (xdrproc_t) xdr_qemu_monitor_command_ret, (char *) &ret) == -1)
        goto done;

    *result = strdup(ret.result);
    if (*result == NULL) {

        virReportOOMError();
        goto cleanup;
    }

    rv = 0;

cleanup:
    xdr_free ((xdrproc_t) xdr_qemu_monitor_command_ret, (char *) &ret);

done:
    remoteDriverUnlock(priv);
    return rv;
}

/*----------------------------------------------------------------------*/
9305

9306
static struct remote_thread_call *
9307
prepareCall(struct private_data *priv,
C
Chris Lalancette 已提交
9308
            int flags,
9309 9310 9311 9312
            int proc_nr,
            xdrproc_t args_filter, char *args,
            xdrproc_t ret_filter, char *ret)
{
9313
    XDR xdr;
9314 9315 9316
    struct remote_message_header hdr;
    struct remote_thread_call *rv;

9317
    if (VIR_ALLOC(rv) < 0) {
9318
        virReportOOMError();
9319
        return NULL;
9320
    }
9321 9322 9323

    if (virCondInit(&rv->cond) < 0) {
        VIR_FREE(rv);
9324 9325
        remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("cannot initialize mutex"));
9326 9327
        return NULL;
    }
9328 9329

    /* Get a unique serial number for this message. */
9330 9331 9332 9333
    rv->serial = priv->counter++;
    rv->proc_nr = proc_nr;
    rv->ret_filter = ret_filter;
    rv->ret = ret;
9334
    rv->want_reply = 1;
9335

9336
    if (flags & REMOTE_CALL_QEMU) {
C
Chris Lalancette 已提交
9337 9338 9339 9340 9341 9342 9343
        hdr.prog = QEMU_PROGRAM;
        hdr.vers = QEMU_PROTOCOL_VERSION;
    }
    else {
        hdr.prog = REMOTE_PROGRAM;
        hdr.vers = REMOTE_PROTOCOL_VERSION;
    }
9344
    hdr.proc = proc_nr;
9345
    hdr.type = REMOTE_CALL;
9346
    hdr.serial = rv->serial;
9347 9348 9349
    hdr.status = REMOTE_OK;

    /* Serialise header followed by args. */
9350
    xdrmem_create (&xdr, rv->buffer+4, REMOTE_MESSAGE_MAX, XDR_ENCODE);
9351
    if (!xdr_remote_message_header (&xdr, &hdr)) {
9352
        remoteError(VIR_ERR_RPC, "%s", _("xdr_remote_message_header failed"));
9353
        goto error;
9354 9355 9356
    }

    if (!(*args_filter) (&xdr, args)) {
9357
        remoteError(VIR_ERR_RPC, "%s", _("marshalling args"));
9358
        goto error;
9359 9360 9361
    }

    /* Get the length stored in buffer. */
9362
    rv->bufferLength = xdr_getpos (&xdr);
9363 9364 9365 9366 9367
    xdr_destroy (&xdr);

    /* Length must include the length word itself (always encoded in
     * 4 bytes as per RFC 4506).
     */
9368
    rv->bufferLength += REMOTE_MESSAGE_HEADER_XDR_LEN;
9369 9370

    /* Encode the length word. */
9371 9372
    xdrmem_create (&xdr, rv->buffer, REMOTE_MESSAGE_HEADER_XDR_LEN, XDR_ENCODE);
    if (!xdr_u_int (&xdr, &rv->bufferLength)) {
9373
        remoteError(VIR_ERR_RPC, "%s", _("xdr_u_int (length word)"));
9374
        goto error;
9375 9376 9377
    }
    xdr_destroy (&xdr);

9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388
    return rv;

error:
    xdr_destroy (&xdr);
    VIR_FREE(rv);
    return NULL;
}



static int
9389
remoteIOWriteBuffer(struct private_data *priv,
9390
                    const char *bytes, int len)
9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402
{
    int ret;

    if (priv->uses_tls) {
    tls_resend:
        ret = gnutls_record_send (priv->session, bytes, len);
        if (ret < 0) {
            if (ret == GNUTLS_E_INTERRUPTED)
                goto tls_resend;
            if (ret == GNUTLS_E_AGAIN)
                return 0;

9403
            remoteError(VIR_ERR_GNUTLS_ERROR, "%s", gnutls_strerror (ret));
9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414
            return -1;
        }
    } else {
    resend:
        ret = send (priv->sock, bytes, len, 0);
        if (ret == -1) {
            if (errno == EINTR)
                goto resend;
            if (errno == EWOULDBLOCK)
                return 0;

9415
            virReportSystemError(errno, "%s", _("cannot send data"));
9416 9417 9418 9419 9420 9421 9422 9423 9424 9425
            return -1;

        }
    }

    return ret;
}


static int
9426
remoteIOReadBuffer(struct private_data *priv,
9427
                   char *bytes, int len)
9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441
{
    int ret;

    if (priv->uses_tls) {
    tls_resend:
        ret = gnutls_record_recv (priv->session, bytes, len);
        if (ret == GNUTLS_E_INTERRUPTED)
            goto tls_resend;
        if (ret == GNUTLS_E_AGAIN)
            return 0;

        /* Treat 0 == EOF as an error */
        if (ret <= 0) {
            if (ret < 0)
9442 9443 9444
                remoteError(VIR_ERR_GNUTLS_ERROR,
                            _("failed to read from TLS socket %s"),
                            gnutls_strerror (ret));
9445
            else
9446 9447
                remoteError(VIR_ERR_SYSTEM_ERROR, "%s",
                            _("server closed connection"));
9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459
            return -1;
        }
    } else {
    resend:
        ret = recv (priv->sock, bytes, len, 0);
        if (ret <= 0) {
            if (ret == -1) {
                if (errno == EINTR)
                    goto resend;
                if (errno == EWOULDBLOCK)
                    return 0;

9460 9461
                char errout[1024] = "\0";
                if (priv->errfd != -1) {
9462 9463 9464 9465 9466
                    if (saferead(priv->errfd, errout, sizeof(errout)) < 0) {
                        virReportSystemError(errno, "%s",
                                             _("cannot recv data"));
                        return -1;
                    }
9467 9468
                }

9469
                virReportSystemError(errno,
9470 9471
                                     _("cannot recv data: %s"), errout);

9472
            } else {
9473 9474
                char errout[1024] = "\0";
                if (priv->errfd != -1) {
9475 9476 9477 9478 9479 9480
                    if (saferead(priv->errfd, errout, sizeof(errout)) < 0) {
                        remoteError(VIR_ERR_SYSTEM_ERROR,
                                    _("server closed connection: %s"),
                                    virStrerror(errno, errout, sizeof errout));
                        return -1;
                    }
9481 9482
                }

9483 9484
                remoteError(VIR_ERR_SYSTEM_ERROR,
                            _("server closed connection: %s"), errout);
9485 9486 9487 9488 9489 9490 9491 9492 9493 9494
            }
            return -1;
        }
    }

    return ret;
}


static int
9495
remoteIOWriteMessage(struct private_data *priv,
9496
                     struct remote_thread_call *thecall)
9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509
{
#if HAVE_SASL
    if (priv->saslconn) {
        const char *output;
        unsigned int outputlen;
        int err, ret;

        if (!priv->saslEncoded) {
            err = sasl_encode(priv->saslconn,
                              thecall->buffer + thecall->bufferOffset,
                              thecall->bufferLength - thecall->bufferOffset,
                              &output, &outputlen);
            if (err != SASL_OK) {
9510 9511 9512
                remoteError(VIR_ERR_INTERNAL_ERROR,
                            _("failed to encode SASL data: %s"),
                            sasl_errstring(err, NULL, NULL));
9513 9514 9515 9516 9517 9518 9519 9520 9521
                return -1;
            }
            priv->saslEncoded = output;
            priv->saslEncodedLength = outputlen;
            priv->saslEncodedOffset = 0;

            thecall->bufferOffset = thecall->bufferLength;
        }

9522
        ret = remoteIOWriteBuffer(priv,
9523 9524
                                  priv->saslEncoded + priv->saslEncodedOffset,
                                  priv->saslEncodedLength - priv->saslEncodedOffset);
9525 9526 9527 9528 9529 9530 9531
        if (ret < 0)
            return ret;
        priv->saslEncodedOffset += ret;

        if (priv->saslEncodedOffset == priv->saslEncodedLength) {
            priv->saslEncoded = NULL;
            priv->saslEncodedOffset = priv->saslEncodedLength = 0;
9532 9533 9534 9535
            if (thecall->want_reply)
                thecall->mode = REMOTE_MODE_WAIT_RX;
            else
                thecall->mode = REMOTE_MODE_COMPLETE;
9536 9537 9538 9539
        }
    } else {
#endif
        int ret;
9540
        ret = remoteIOWriteBuffer(priv,
9541 9542
                                  thecall->buffer + thecall->bufferOffset,
                                  thecall->bufferLength - thecall->bufferOffset);
9543 9544 9545 9546 9547 9548
        if (ret < 0)
            return ret;
        thecall->bufferOffset += ret;

        if (thecall->bufferOffset == thecall->bufferLength) {
            thecall->bufferOffset = thecall->bufferLength = 0;
9549 9550 9551 9552
            if (thecall->want_reply)
                thecall->mode = REMOTE_MODE_WAIT_RX;
            else
                thecall->mode = REMOTE_MODE_COMPLETE;
9553 9554 9555 9556 9557 9558 9559 9560 9561
        }
#if HAVE_SASL
    }
#endif
    return 0;
}


static int
9562
remoteIOHandleOutput(struct private_data *priv) {
9563 9564 9565 9566 9567 9568 9569 9570 9571 9572
    struct remote_thread_call *thecall = priv->waitDispatch;

    while (thecall &&
           thecall->mode != REMOTE_MODE_WAIT_TX)
        thecall = thecall->next;

    if (!thecall)
        return -1; /* Shouldn't happen, but you never know... */

    while (thecall) {
9573
        int ret = remoteIOWriteMessage(priv, thecall);
9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586
        if (ret < 0)
            return ret;

        if (thecall->mode == REMOTE_MODE_WAIT_TX)
            return 0; /* Blocking write, to back to event loop */

        thecall = thecall->next;
    }

    return 0; /* No more calls to send, all done */
}

static int
9587
remoteIOReadMessage(struct private_data *priv) {
9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600
    unsigned int wantData;

    /* Start by reading length word */
    if (priv->bufferLength == 0)
        priv->bufferLength = 4;

    wantData = priv->bufferLength - priv->bufferOffset;

#if HAVE_SASL
    if (priv->saslconn) {
        if (priv->saslDecoded == NULL) {
            char encoded[8192];
            int ret, err;
9601
            ret = remoteIOReadBuffer(priv, encoded, sizeof(encoded));
9602 9603 9604 9605 9606 9607 9608 9609
            if (ret < 0)
                return -1;
            if (ret == 0)
                return 0;

            err = sasl_decode(priv->saslconn, encoded, ret,
                              &priv->saslDecoded, &priv->saslDecodedLength);
            if (err != SASL_OK) {
9610 9611 9612
                remoteError(VIR_ERR_INTERNAL_ERROR,
                            _("failed to decode SASL data: %s"),
                            sasl_errstring(err, NULL, NULL));
9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626
                return -1;
            }
            priv->saslDecodedOffset = 0;
        }

        if ((priv->saslDecodedLength - priv->saslDecodedOffset) < wantData)
            wantData = (priv->saslDecodedLength - priv->saslDecodedOffset);

        memcpy(priv->buffer + priv->bufferOffset,
               priv->saslDecoded + priv->saslDecodedOffset,
               wantData);
        priv->saslDecodedOffset += wantData;
        priv->bufferOffset += wantData;
        if (priv->saslDecodedOffset == priv->saslDecodedLength) {
9627
            priv->saslDecodedOffset = priv->saslDecodedLength = 0;
9628 9629 9630 9631 9632 9633 9634 9635
            priv->saslDecoded = NULL;
        }

        return wantData;
    } else {
#endif
        int ret;

9636
        ret = remoteIOReadBuffer(priv,
9637 9638
                                 priv->buffer + priv->bufferOffset,
                                 wantData);
9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650
        if (ret < 0)
            return -1;
        if (ret == 0)
            return 0;

        priv->bufferOffset += ret;

        return ret;
#if HAVE_SASL
    }
#endif
}
9651 9652


9653
static int
9654
remoteIODecodeMessageLength(struct private_data *priv) {
9655
    XDR xdr;
9656
    unsigned int len;
9657 9658

    xdrmem_create (&xdr, priv->buffer, priv->bufferLength, XDR_DECODE);
9659
    if (!xdr_u_int (&xdr, &len)) {
9660
        remoteError(VIR_ERR_RPC, "%s", _("xdr_u_int (length word, reply)"));
9661 9662 9663 9664
        return -1;
    }
    xdr_destroy (&xdr);

9665
    if (len < REMOTE_MESSAGE_HEADER_XDR_LEN) {
9666 9667
        remoteError(VIR_ERR_RPC, "%s",
                    _("packet received from server too small"));
9668 9669 9670
        return -1;
    }

9671
    /* Length includes length word - adjust to real length to read. */
9672
    len -= REMOTE_MESSAGE_HEADER_XDR_LEN;
9673

9674
    if (len > REMOTE_MESSAGE_MAX) {
9675 9676
        remoteError(VIR_ERR_RPC, "%s",
                    _("packet received from server too large"));
9677 9678 9679
        return -1;
    }

9680 9681 9682 9683 9684 9685 9686 9687 9688
    /* Extend our declared buffer length and carry
       on reading the header + payload */
    priv->bufferLength += len;
    DEBUG("Got length, now need %d total (%d more)", priv->bufferLength, len);
    return 0;
}


static int
9689 9690 9691 9692 9693 9694 9695 9696 9697 9698
processCallDispatchReply(virConnectPtr conn, struct private_data *priv,
                         remote_message_header *hdr,
                         XDR *xdr);

static int
processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
                           int in_open,
                           remote_message_header *hdr,
                           XDR *xdr);

9699 9700 9701 9702 9703
static int
processCallDispatchStream(virConnectPtr conn, struct private_data *priv,
                          remote_message_header *hdr,
                          XDR *xdr);

9704 9705 9706

static int
processCallDispatch(virConnectPtr conn, struct private_data *priv,
C
Chris Lalancette 已提交
9707
                    int flags) {
9708 9709 9710
    XDR xdr;
    struct remote_message_header hdr;
    int len = priv->bufferLength - 4;
9711
    int rv = -1;
C
Chris Lalancette 已提交
9712 9713
    int expectedprog;
    int expectedvers;
9714

9715 9716 9717
    /* Length word has already been read */
    priv->bufferOffset = 4;

9718
    /* Deserialise reply header. */
9719
    xdrmem_create (&xdr, priv->buffer + priv->bufferOffset, len, XDR_DECODE);
9720
    if (!xdr_remote_message_header (&xdr, &hdr)) {
9721
        remoteError(VIR_ERR_RPC, "%s", _("invalid header in reply"));
9722 9723 9724
        return -1;
    }

9725 9726
    priv->bufferOffset += xdr_getpos(&xdr);

C
Chris Lalancette 已提交
9727 9728
    expectedprog = REMOTE_PROGRAM;
    expectedvers = REMOTE_PROTOCOL_VERSION;
9729
    if (flags & REMOTE_CALL_QEMU) {
C
Chris Lalancette 已提交
9730 9731 9732 9733
        expectedprog = QEMU_PROGRAM;
        expectedvers = QEMU_PROTOCOL_VERSION;
    }

9734
    /* Check program, version, etc. are what we expect. */
C
Chris Lalancette 已提交
9735
    if (hdr.prog != expectedprog) {
9736 9737
        remoteError(VIR_ERR_RPC,
                    _("unknown program (received %x, expected %x)"),
C
Chris Lalancette 已提交
9738
                    hdr.prog, expectedprog);
9739 9740
        return -1;
    }
C
Chris Lalancette 已提交
9741
    if (hdr.vers != expectedvers) {
9742 9743
        remoteError(VIR_ERR_RPC,
                    _("unknown protocol version (received %x, expected %x)"),
C
Chris Lalancette 已提交
9744
                    hdr.vers, expectedvers);
9745 9746 9747
        return -1;
    }

9748

9749 9750
    switch (hdr.type) {
    case REMOTE_REPLY: /* Normal RPC replies */
C
Chris Lalancette 已提交
9751
        rv = processCallDispatchReply(conn, priv, &hdr, &xdr);
9752
        break;
9753

9754
    case REMOTE_MESSAGE: /* Async notifications */
C
Chris Lalancette 已提交
9755
        rv = processCallDispatchMessage(conn, priv, flags & REMOTE_CALL_IN_OPEN,
9756 9757 9758
                                        &hdr, &xdr);
        break;

9759
    case REMOTE_STREAM: /* Stream protocol */
C
Chris Lalancette 已提交
9760
        rv = processCallDispatchStream(conn, priv, &hdr, &xdr);
9761 9762
        break;

9763
    default:
9764 9765 9766
        remoteError(VIR_ERR_RPC,
                    _("got unexpected RPC call %d from server"),
                    hdr.proc);
9767 9768
        rv = -1;
        break;
9769
    }
9770

9771 9772 9773 9774 9775 9776
    xdr_destroy(&xdr);
    return rv;
}


static int
9777 9778
processCallDispatchReply(virConnectPtr conn ATTRIBUTE_UNUSED,
                         struct private_data *priv,
9779 9780 9781 9782
                         remote_message_header *hdr,
                         XDR *xdr) {
    struct remote_thread_call *thecall;

9783 9784 9785 9786
    /* Ok, definitely got an RPC reply now find
       out who's been waiting for it */
    thecall = priv->waitDispatch;
    while (thecall &&
9787
           thecall->serial != hdr->serial)
9788 9789 9790
        thecall = thecall->next;

    if (!thecall) {
9791 9792 9793
        remoteError(VIR_ERR_RPC,
                    _("no call waiting for reply with serial %d"),
                    hdr->serial);
9794 9795
        return -1;
    }
9796

9797
    if (hdr->proc != thecall->proc_nr) {
9798 9799 9800
        remoteError(VIR_ERR_RPC,
                    _("unknown procedure (received %x, expected %x)"),
                    hdr->proc, thecall->proc_nr);
9801 9802 9803 9804 9805 9806 9807
        return -1;
    }

    /* Status is either REMOTE_OK (meaning that what follows is a ret
     * structure), or REMOTE_ERROR (and what follows is a remote_error
     * structure).
     */
9808
    switch (hdr->status) {
9809
    case REMOTE_OK:
9810
        if (!(*thecall->ret_filter) (xdr, thecall->ret)) {
9811
            remoteError(VIR_ERR_RPC, "%s", _("unmarshalling ret"));
9812 9813
            return -1;
        }
9814
        thecall->mode = REMOTE_MODE_COMPLETE;
9815 9816 9817
        return 0;

    case REMOTE_ERROR:
9818
        memset (&thecall->err, 0, sizeof thecall->err);
9819
        if (!xdr_remote_error (xdr, &thecall->err)) {
9820
            remoteError(VIR_ERR_RPC, "%s", _("unmarshalling remote_error"));
9821 9822
            return -1;
        }
9823 9824
        thecall->mode = REMOTE_MODE_ERROR;
        return 0;
9825 9826

    default:
9827
        remoteError(VIR_ERR_RPC, _("unknown status (received %x)"), hdr->status);
9828 9829 9830 9831
        return -1;
    }
}

9832 9833 9834 9835 9836
static int
processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
                           int in_open,
                           remote_message_header *hdr,
                           XDR *xdr) {
9837
    virDomainEventPtr event = NULL;
9838 9839 9840 9841 9842 9843 9844 9845 9846 9847
    /* An async message has come in while we were waiting for the
     * response. Process it to pull it off the wire, and try again
     */
    DEBUG0("Encountered an event while waiting for a response");

    if (in_open) {
        DEBUG("Ignoring bogus event %d received while in open", hdr->proc);
        return -1;
    }

9848
    switch (hdr->proc) {
9849
    case REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE:
9850 9851 9852
        event = remoteDomainReadEventLifecycle(conn, xdr);
        break;

9853 9854 9855 9856
    case REMOTE_PROC_DOMAIN_EVENT_REBOOT:
        event = remoteDomainReadEventReboot(conn, xdr);
        break;

9857 9858 9859 9860
    case REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE:
        event = remoteDomainReadEventRTCChange(conn, xdr);
        break;

9861 9862 9863 9864
    case REMOTE_PROC_DOMAIN_EVENT_WATCHDOG:
        event = remoteDomainReadEventWatchdog(conn, xdr);
        break;

9865 9866 9867 9868
    case REMOTE_PROC_DOMAIN_EVENT_IO_ERROR:
        event = remoteDomainReadEventIOError(conn, xdr);
        break;

9869 9870 9871 9872
    case REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON:
        event = remoteDomainReadEventIOErrorReason(conn, xdr);
        break;

9873 9874 9875 9876
    case REMOTE_PROC_DOMAIN_EVENT_GRAPHICS:
        event = remoteDomainReadEventGraphics(conn, xdr);
        break;

9877
    default:
9878
        DEBUG("Unexpected event proc %d", hdr->proc);
9879
        break;
9880
    }
9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891

    if (!event)
        return -1;

    if (virDomainEventQueuePush(priv->domainEvents,
                                event) < 0) {
        DEBUG0("Error adding event to queue");
        virDomainEventFree(event);
    }
    virEventUpdateTimeout(priv->eventFlushTimer, 0);

9892 9893 9894
    return 0;
}

9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910
static int
processCallDispatchStream(virConnectPtr conn ATTRIBUTE_UNUSED,
                          struct private_data *priv,
                          remote_message_header *hdr,
                          XDR *xdr) {
    struct private_stream_data *privst;
    struct remote_thread_call *thecall;

    /* Try and find a matching stream */
    privst = priv->streams;
    while (privst &&
           privst->serial != hdr->serial &&
           privst->proc_nr != hdr->proc)
        privst = privst->next;

    if (!privst) {
9911 9912
        VIR_DEBUG("No registered stream matching serial=%d, proc=%d",
                  hdr->serial, hdr->proc);
9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930
        return -1;
    }

    /* See if there's also a (optional) call waiting for this reply */
    thecall = priv->waitDispatch;
    while (thecall &&
           thecall->serial != hdr->serial)
        thecall = thecall->next;


    /* Status is either REMOTE_OK (meaning that what follows is a ret
     * structure), or REMOTE_ERROR (and what follows is a remote_error
     * structure).
     */
    switch (hdr->status) {
    case REMOTE_CONTINUE: {
        int avail = privst->incomingLength - privst->incomingOffset;
        int need = priv->bufferLength - priv->bufferOffset;
9931
        VIR_DEBUG0("Got a stream data packet");
9932 9933 9934 9935 9936 9937 9938

        /* XXX flag stream as complete somwhere if need==0 */

        if (need > avail) {
            int extra = need - avail;
            if (VIR_REALLOC_N(privst->incoming,
                              privst->incomingLength + extra) < 0) {
9939
                VIR_DEBUG0("Out of memory handling stream data");
9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950
                return -1;
            }
            privst->incomingLength += extra;
        }

        memcpy(privst->incoming + privst->incomingOffset,
               priv->buffer + priv->bufferOffset,
               priv->bufferLength - priv->bufferOffset);
        privst->incomingOffset += (priv->bufferLength - priv->bufferOffset);

        if (thecall && thecall->want_reply) {
9951
            VIR_DEBUG("Got sync data packet offset=%d", privst->incomingOffset);
9952 9953
            thecall->mode = REMOTE_MODE_COMPLETE;
        } else {
9954
            VIR_DEBUG("Got aysnc data packet offset=%d", privst->incomingOffset);
9955
            remoteStreamEventTimerUpdate(privst);
9956 9957 9958 9959 9960
        }
        return 0;
    }

    case REMOTE_OK:
9961
        VIR_DEBUG0("Got a synchronous confirm");
9962
        if (!thecall) {
9963
            VIR_DEBUG0("Got unexpected stream finish confirmation");
9964 9965 9966 9967 9968 9969 9970
            return -1;
        }
        thecall->mode = REMOTE_MODE_COMPLETE;
        return 0;

    case REMOTE_ERROR:
        if (thecall && thecall->want_reply) {
9971
            VIR_DEBUG0("Got a synchronous error");
9972 9973 9974
            /* Give the error straight to this call */
            memset (&thecall->err, 0, sizeof thecall->err);
            if (!xdr_remote_error (xdr, &thecall->err)) {
9975
                remoteError(VIR_ERR_RPC, "%s", _("unmarshalling remote_error"));
9976 9977 9978 9979
                return -1;
            }
            thecall->mode = REMOTE_MODE_ERROR;
        } else {
9980
            VIR_DEBUG0("Got a asynchronous error");
9981 9982
            /* No call, so queue the error against the stream */
            if (privst->has_error) {
9983
                VIR_DEBUG0("Got unexpected duplicate stream error");
9984 9985 9986 9987 9988
                return -1;
            }
            privst->has_error = 1;
            memset (&privst->err, 0, sizeof privst->err);
            if (!xdr_remote_error (xdr, &privst->err)) {
9989
                VIR_DEBUG0("Failed to unmarshall error");
9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000
                return -1;
            }
        }
        return 0;

    default:
        VIR_WARN("Stream with unexpected serial=%d, proc=%d, status=%d",
                 hdr->serial, hdr->proc, hdr->status);
        return -1;
    }
}
10001 10002

static int
10003
remoteIOHandleInput(virConnectPtr conn, struct private_data *priv,
C
Chris Lalancette 已提交
10004
                    int flags)
10005
{
10006
    /* Read as much data as is available, until we get
10007
     * EAGAIN
10008
     */
10009
    for (;;) {
10010
        int ret = remoteIOReadMessage(priv);
10011

10012 10013 10014 10015
        if (ret < 0)
            return -1;
        if (ret == 0)
            return 0;  /* Blocking on read */
10016

10017 10018 10019
        /* Check for completion of our goal */
        if (priv->bufferOffset == priv->bufferLength) {
            if (priv->bufferOffset == 4) {
10020
                ret = remoteIODecodeMessageLength(priv);
10021 10022 10023 10024 10025 10026 10027 10028 10029
                if (ret < 0)
                    return -1;

                /*
                 * We'll carry on around the loop to immediately
                 * process the message body, because it has probably
                 * already arrived. Worst case, we'll get EAGAIN on
                 * next iteration.
                 */
10030
            } else {
C
Chris Lalancette 已提交
10031
                ret = processCallDispatch(conn, priv, flags);
10032
                priv->bufferOffset = priv->bufferLength = 0;
10033 10034 10035 10036 10037 10038 10039 10040
                /*
                 * We've completed one call, so return even
                 * though there might still be more data on
                 * the wire. We need to actually let the caller
                 * deal with this arrived message to keep good
                 * response, and also to correctly handle EOF.
                 */
                return ret;
10041 10042 10043
            }
        }
    }
10044 10045
}

10046 10047 10048 10049 10050
/*
 * Process all calls pending dispatch/receive until we
 * get a reply to our own call. Then quit and pass the buck
 * to someone else.
 */
10051
static int
10052 10053
remoteIOEventLoop(virConnectPtr conn,
                  struct private_data *priv,
C
Chris Lalancette 已提交
10054
                  int flags,
10055
                  struct remote_thread_call *thiscall)
10056
{
10057 10058
    struct pollfd fds[2];
    int ret;
10059

10060 10061 10062 10063 10064 10065 10066
    fds[0].fd = priv->sock;
    fds[1].fd = priv->wakeupReadFD;

    for (;;) {
        struct remote_thread_call *tmp = priv->waitDispatch;
        struct remote_thread_call *prev;
        char ignore;
10067
#ifdef HAVE_PTHREAD_SIGMASK
10068
        sigset_t oldmask, blockedsigs;
10069
#endif
10070 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 10081 10082 10083

        fds[0].events = fds[0].revents = 0;
        fds[1].events = fds[1].revents = 0;

        fds[1].events = POLLIN;
        while (tmp) {
            if (tmp->mode == REMOTE_MODE_WAIT_RX)
                fds[0].events |= POLLIN;
            if (tmp->mode == REMOTE_MODE_WAIT_TX)
                fds[0].events |= POLLOUT;

            tmp = tmp->next;
        }

10084 10085 10086
        if (priv->streams)
            fds[0].events |= POLLIN;

10087 10088 10089 10090
        /* Release lock while poll'ing so other threads
         * can stuff themselves on the queue */
        remoteDriverUnlock(priv);

10091 10092 10093 10094 10095
        /* Block SIGWINCH from interrupting poll in curses programs,
         * then restore the original signal mask again immediately
         * after the call (RHBZ#567931).  Same for SIGCHLD and SIGPIPE
         * at the suggestion of Paolo Bonzini and Daniel Berrange.
         */
10096
#ifdef HAVE_PTHREAD_SIGMASK
10097 10098 10099 10100
        sigemptyset (&blockedsigs);
        sigaddset (&blockedsigs, SIGWINCH);
        sigaddset (&blockedsigs, SIGCHLD);
        sigaddset (&blockedsigs, SIGPIPE);
10101
        ignore_value(pthread_sigmask(SIG_BLOCK, &blockedsigs, &oldmask));
10102
#endif
10103

10104 10105
    repoll:
        ret = poll(fds, ARRAY_CARDINALITY(fds), -1);
10106
        if (ret < 0 && errno == EAGAIN)
10107
            goto repoll;
10108

10109
#ifdef HAVE_PTHREAD_SIGMASK
10110
        ignore_value(pthread_sigmask(SIG_SETMASK, &oldmask, NULL));
10111
#endif
10112

10113 10114 10115
        remoteDriverLock(priv);

        if (fds[1].revents) {
10116
            ssize_t s;
10117
            DEBUG0("Woken up from poll by other thread");
10118 10119 10120 10121 10122 10123 10124 10125 10126 10127
            s = saferead(priv->wakeupReadFD, &ignore, sizeof(ignore));
            if (s < 0) {
                virReportSystemError(errno, "%s",
                                     _("read on wakeup fd failed"));
                goto error;
            } else if (s != sizeof(ignore)) {
                remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("read on wakeup fd failed"));
                goto error;
            }
10128 10129 10130 10131 10132
        }

        if (ret < 0) {
            if (errno == EWOULDBLOCK)
                continue;
10133
            virReportSystemError(errno,
10134
                                 "%s", _("poll on socket failed"));
10135
            goto error;
10136 10137 10138
        }

        if (fds[0].revents & POLLOUT) {
10139
            if (remoteIOHandleOutput(priv) < 0)
10140
                goto error;
10141
        }
10142 10143

        if (fds[0].revents & POLLIN) {
C
Chris Lalancette 已提交
10144
            if (remoteIOHandleInput(conn, priv, flags) < 0)
10145
                goto error;
10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169
        }

        /* Iterate through waiting threads and if
         * any are complete then tell 'em to wakeup
         */
        tmp = priv->waitDispatch;
        prev = NULL;
        while (tmp) {
            if (tmp != thiscall &&
                (tmp->mode == REMOTE_MODE_COMPLETE ||
                 tmp->mode == REMOTE_MODE_ERROR)) {
                /* Take them out of the list */
                if (prev)
                    prev->next = tmp->next;
                else
                    priv->waitDispatch = tmp->next;

                /* And wake them up....
                 * ...they won't actually wakeup until
                 * we release our mutex a short while
                 * later...
                 */
                DEBUG("Waking up sleep %d %p %p", tmp->proc_nr, tmp, priv->waitDispatch);
                virCondSignal(&tmp->cond);
10170
            }
10171 10172
            prev = tmp;
            tmp = tmp->next;
10173 10174
        }

10175 10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190
        /* Now see if *we* are done */
        if (thiscall->mode == REMOTE_MODE_COMPLETE ||
            thiscall->mode == REMOTE_MODE_ERROR) {
            /* We're at head of the list already, so
             * remove us
             */
            priv->waitDispatch = thiscall->next;
            DEBUG("Giving up the buck %d %p %p", thiscall->proc_nr, thiscall, priv->waitDispatch);
            /* See if someone else is still waiting
             * and if so, then pass the buck ! */
            if (priv->waitDispatch) {
                DEBUG("Passing the buck to %d %p", priv->waitDispatch->proc_nr, priv->waitDispatch);
                virCondSignal(&priv->waitDispatch->cond);
            }
            return 0;
        }
10191

10192 10193

        if (fds[0].revents & (POLLHUP | POLLERR)) {
10194 10195
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("received hangup / error event on socket"));
10196
            goto error;
10197 10198
        }
    }
10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210


error:
    priv->waitDispatch = thiscall->next;
    DEBUG("Giving up the buck due to I/O error %d %p %p", thiscall->proc_nr, thiscall, priv->waitDispatch);
    /* See if someone else is still waiting
     * and if so, then pass the buck ! */
    if (priv->waitDispatch) {
        DEBUG("Passing the buck to %d %p", priv->waitDispatch->proc_nr, priv->waitDispatch);
        virCondSignal(&priv->waitDispatch->cond);
    }
    return -1;
10211 10212
}

10213
/*
10214
 * This function sends a message to remote server and awaits a reply
10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228
 *
 * NB. This does not free the args structure (not desirable, since you
 * often want this allocated on the stack or else it contains strings
 * which come from the user).  It does however free any intermediate
 * results, eg. the error structure if there is one.
 *
 * NB(2). Make sure to memset (&ret, 0, sizeof ret) before calling,
 * else Bad Things will happen in the XDR code.
 *
 * NB(3) You must have the private_data lock before calling this
 *
 * NB(4) This is very complicated. Due to connection cloning, multiple
 * threads can want to use the socket at once. Obviously only one of
 * them can. So if someone's using the socket, other threads are put
10229
 * to sleep on condition variables. The existing thread may completely
10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245
 * send & receive their RPC call/reply while they're asleep. Or it
 * may only get around to dealing with sending the call. Or it may
 * get around to neither. So upon waking up from slumber, the other
 * thread may or may not have more work todo.
 *
 * We call this dance  'passing the buck'
 *
 *      http://en.wikipedia.org/wiki/Passing_the_buck
 *
 *   "Buck passing or passing the buck is the action of transferring
 *    responsibility or blame unto another person. It is also used as
 *    a strategy in power politics when the actions of one country/
 *    nation are blamed on another, providing an opportunity for war."
 *
 * NB(5) Don't Panic!
 */
10246
static int
10247 10248 10249 10250
remoteIO(virConnectPtr conn,
         struct private_data *priv,
         int flags,
         struct remote_thread_call *thiscall)
10251
{
10252 10253
    int rv;

10254 10255 10256
    DEBUG("Do proc=%d serial=%d length=%d wait=%p",
          thiscall->proc_nr, thiscall->serial,
          thiscall->bufferLength, priv->waitDispatch);
10257

10258 10259 10260 10261 10262
    /* Check to see if another thread is dispatching */
    if (priv->waitDispatch) {
        /* Stick ourselves on the end of the wait queue */
        struct remote_thread_call *tmp = priv->waitDispatch;
        char ignore = 1;
10263
        ssize_t s;
10264 10265 10266 10267 10268 10269
        while (tmp && tmp->next)
            tmp = tmp->next;
        if (tmp)
            tmp->next = thiscall;
        else
            priv->waitDispatch = thiscall;
10270

10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283
        /* Force other thread to wakeup from poll */
        s = safewrite(priv->wakeupSendFD, &ignore, sizeof(ignore));
        if (s < 0) {
            char errout[1024];
            remoteError(VIR_ERR_INTERNAL_ERROR,
                        _("failed to wake up polling thread: %s"),
                        virStrerror(errno, errout, sizeof errout));
            return -1;
        } else if (s != sizeof(ignore)) {
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("failed to wake up polling thread"));
            return -1;
        }
10284

10285
        DEBUG("Going to sleep %d %p %p", thiscall->proc_nr, priv->waitDispatch, thiscall);
10286 10287 10288 10289 10290 10291 10292 10293 10294 10295 10296 10297 10298
        /* Go to sleep while other thread is working... */
        if (virCondWait(&thiscall->cond, &priv->lock) < 0) {
            if (priv->waitDispatch == thiscall) {
                priv->waitDispatch = thiscall->next;
            } else {
                tmp = priv->waitDispatch;
                while (tmp && tmp->next &&
                       tmp->next != thiscall) {
                    tmp = tmp->next;
                }
                if (tmp && tmp->next == thiscall)
                    tmp->next = thiscall->next;
            }
10299 10300
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("failed to wait on condition"));
10301
            return -1;
10302
        }
10303

10304
        DEBUG("Wokeup from sleep %d %p %p", thiscall->proc_nr, priv->waitDispatch, thiscall);
10305 10306 10307 10308 10309 10310 10311 10312 10313 10314 10315 10316 10317 10318
        /* Two reasons we can be woken up
         *  1. Other thread has got our reply ready for us
         *  2. Other thread is all done, and it is our turn to
         *     be the dispatcher to finish waiting for
         *     our reply
         */
        if (thiscall->mode == REMOTE_MODE_COMPLETE ||
            thiscall->mode == REMOTE_MODE_ERROR) {
            /*
             * We avoided catching the buck and our reply is ready !
             * We've already had 'thiscall' removed from the list
             * so just need to (maybe) handle errors & free it
             */
            goto cleanup;
10319
        }
10320 10321 10322

        /* Grr, someone passed the buck onto us ... */

10323
    } else {
10324 10325 10326 10327
        /* We're first to catch the buck */
        priv->waitDispatch = thiscall;
    }

10328
    DEBUG("We have the buck %d %p %p", thiscall->proc_nr, priv->waitDispatch, thiscall);
10329 10330 10331 10332 10333 10334 10335 10336 10337 10338 10339 10340 10341 10342 10343 10344 10345
    /*
     * The buck stops here!
     *
     * At this point we're about to own the dispatch
     * process...
     */

    /*
     * Avoid needless wake-ups of the event loop in the
     * case where this call is being made from a different
     * thread than the event loop. These wake-ups would
     * cause the event loop thread to be blocked on the
     * mutex for the duration of the call
     */
    if (priv->watch >= 0)
        virEventUpdateHandle(priv->watch, 0);

C
Chris Lalancette 已提交
10346
    rv = remoteIOEventLoop(conn, priv, flags, thiscall);
10347 10348 10349 10350

    if (priv->watch >= 0)
        virEventUpdateHandle(priv->watch, VIR_EVENT_HANDLE_READABLE);

10351
    if (rv < 0)
10352 10353 10354
        return -1;

cleanup:
10355
    DEBUG("All done with our call %d %p %p", thiscall->proc_nr, priv->waitDispatch, thiscall);
10356 10357 10358 10359 10360 10361 10362
    if (thiscall->mode == REMOTE_MODE_ERROR) {
        /* See if caller asked us to keep quiet about missing RPCs
         * eg for interop with older servers */
        if (flags & REMOTE_CALL_QUIET_MISSING_RPC &&
            thiscall->err.domain == VIR_FROM_REMOTE &&
            thiscall->err.code == VIR_ERR_RPC &&
            thiscall->err.level == VIR_ERR_ERROR &&
10363
            thiscall->err.message &&
10364 10365
            STRPREFIX(*thiscall->err.message, "unknown procedure")) {
            rv = -2;
10366 10367 10368 10369 10370 10371 10372 10373 10374 10375 10376 10377 10378 10379 10380 10381 10382 10383 10384 10385 10386
        } else if (thiscall->err.domain == VIR_FROM_REMOTE &&
                   thiscall->err.code == VIR_ERR_RPC &&
                   thiscall->err.level == VIR_ERR_ERROR &&
                   thiscall->err.message &&
                   STRPREFIX(*thiscall->err.message, "unknown procedure")) {
            /*
             * convert missing remote entry points into the unsupported
             * feature error
             */
            virRaiseErrorFull(flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
                              __FILE__, __FUNCTION__, __LINE__,
                              thiscall->err.domain,
                              VIR_ERR_NO_SUPPORT,
                              thiscall->err.level,
                              thiscall->err.str1 ? *thiscall->err.str1 : NULL,
                              thiscall->err.str2 ? *thiscall->err.str2 : NULL,
                              thiscall->err.str3 ? *thiscall->err.str3 : NULL,
                              thiscall->err.int1,
                              thiscall->err.int2,
                              "%s", *thiscall->err.message);
            rv = -1;
10387
        } else {
10388 10389 10390 10391 10392 10393 10394 10395 10396 10397
            virRaiseErrorFull(flags & REMOTE_CALL_IN_OPEN ? NULL : conn,
                              __FILE__, __FUNCTION__, __LINE__,
                              thiscall->err.domain,
                              thiscall->err.code,
                              thiscall->err.level,
                              thiscall->err.str1 ? *thiscall->err.str1 : NULL,
                              thiscall->err.str2 ? *thiscall->err.str2 : NULL,
                              thiscall->err.str3 ? *thiscall->err.str3 : NULL,
                              thiscall->err.int1,
                              thiscall->err.int2,
10398
                              "%s", thiscall->err.message ? *thiscall->err.message : "unknown");
10399
            rv = -1;
10400
        }
10401
        xdr_free((xdrproc_t)xdr_remote_error,  (char *)&thiscall->err);
10402 10403
    } else {
        rv = 0;
10404
    }
10405 10406
    return rv;
}
10407

10408 10409 10410 10411 10412 10413 10414

/*
 * Serial a set of arguments into a method call message,
 * send that to the server and wait for reply
 */
static int
call (virConnectPtr conn, struct private_data *priv,
C
Chris Lalancette 已提交
10415
      int flags,
10416 10417 10418 10419 10420
      int proc_nr,
      xdrproc_t args_filter, char *args,
      xdrproc_t ret_filter, char *ret)
{
    struct remote_thread_call *thiscall;
10421
    int rv;
10422

C
Chris Lalancette 已提交
10423
    thiscall = prepareCall(priv, flags, proc_nr, args_filter, args,
10424 10425 10426
                           ret_filter, ret);

    if (!thiscall) {
10427
        virReportOOMError();
10428 10429 10430
        return -1;
    }

10431 10432 10433
    rv = remoteIO(conn, priv, flags, thiscall);
    VIR_FREE(thiscall);
    return rv;
10434 10435 10436
}


10437 10438 10439 10440 10441 10442 10443 10444 10445 10446
/** remoteDomainEventFired:
 *
 * The callback for monitoring the remote socket
 * for event data
 */
void
remoteDomainEventFired(int watch,
                       int fd,
                       int event,
                       void *opaque)
10447
{
10448 10449
    virConnectPtr        conn = opaque;
    struct private_data *priv = conn->privateData;
10450

10451
    remoteDriverLock(priv);
10452

10453 10454 10455
    /* This should be impossible, but it doesn't hurt to check */
    if (priv->waitDispatch)
        goto done;
10456

10457
    DEBUG("Event fired %d %d %d %X", watch, fd, event, event);
10458

10459 10460 10461 10462 10463 10464 10465 10466 10467 10468 10469 10470 10471 10472
    if (event & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR)) {
         DEBUG("%s : VIR_EVENT_HANDLE_HANGUP or "
               "VIR_EVENT_HANDLE_ERROR encountered", __FUNCTION__);
         virEventRemoveHandle(watch);
         priv->watch = -1;
         goto done;
    }

    if (fd != priv->sock) {
        virEventRemoveHandle(watch);
        priv->watch = -1;
        goto done;
    }

10473
    if (remoteIOHandleInput(conn, priv, 0) < 0)
10474 10475 10476 10477
        DEBUG0("Something went wrong during async message processing");

done:
    remoteDriverUnlock(priv);
10478 10479
}

10480 10481
static void remoteDomainEventDispatchFunc(virConnectPtr conn,
                                          virDomainEventPtr event,
10482
                                          virConnectDomainEventGenericCallback cb,
10483 10484 10485 10486 10487 10488 10489 10490 10491 10492 10493
                                          void *cbopaque,
                                          void *opaque)
{
    struct private_data *priv = opaque;

    /* Drop the lock whle dispatching, for sake of re-entrancy */
    remoteDriverUnlock(priv);
    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
    remoteDriverLock(priv);
}

10494 10495
void
remoteDomainEventQueueFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
10496
{
10497 10498
    virConnectPtr conn = opaque;
    struct private_data *priv = conn->privateData;
10499
    virDomainEventQueue tempQueue;
10500 10501 10502

    remoteDriverLock(priv);

10503 10504 10505 10506 10507 10508 10509 10510 10511 10512
    priv->domainEventDispatching = 1;

    /* Copy the queue, so we're reentrant safe */
    tempQueue.count = priv->domainEvents->count;
    tempQueue.events = priv->domainEvents->events;
    priv->domainEvents->count = 0;
    priv->domainEvents->events = NULL;

    virDomainEventQueueDispatch(&tempQueue, priv->callbackList,
                                remoteDomainEventDispatchFunc, priv);
10513 10514
    virEventUpdateTimeout(priv->eventFlushTimer, -1);

10515 10516 10517 10518 10519
    /* Purge any deleted callbacks */
    virDomainEventCallbackListPurgeMarked(priv->callbackList);

    priv->domainEventDispatching = 0;

10520
    remoteDriverUnlock(priv);
10521 10522
}

10523

10524 10525
/* get_nonnull_domain and get_nonnull_network turn an on-wire
 * (name, uuid) pair into virDomainPtr or virNetworkPtr object.
10526
 * These can return NULL if underlying memory allocations fail,
10527
 * but if they do then virterror_internal.has been set.
10528 10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 10539 10540 10541 10542 10543
 */
static virDomainPtr
get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain)
{
    virDomainPtr dom;
    dom = virGetDomain (conn, domain.name, BAD_CAST domain.uuid);
    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 已提交
10544
static virInterfacePtr
10545
get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface)
D
Daniel Veillard 已提交
10546
{
10547
    return virGetInterface (conn, iface.name, iface.mac);
D
Daniel Veillard 已提交
10548 10549
}

10550 10551 10552 10553 10554 10555 10556 10557 10558 10559 10560 10561
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)
{
    return virGetStorageVol (conn, vol.pool, vol.name, vol.key);
}

10562 10563 10564 10565 10566 10567
static virNodeDevicePtr
get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev)
{
    return virGetNodeDevice(conn, dev.name);
}

10568 10569 10570
static virSecretPtr
get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret)
{
10571
    return virGetSecret(conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
10572 10573
}

10574 10575 10576 10577 10578 10579
static virNWFilterPtr
get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter)
{
    return virGetNWFilter (conn, nwfilter.name, BAD_CAST nwfilter.uuid);
}

C
Chris Lalancette 已提交
10580 10581 10582 10583 10584 10585
static virDomainSnapshotPtr
get_nonnull_domain_snapshot (virDomainPtr domain, remote_nonnull_domain_snapshot snapshot)
{
    return virGetDomainSnapshot(domain, snapshot.name);
}

10586

10587 10588 10589 10590
/* Make remote_nonnull_domain and remote_nonnull_network. */
static void
make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
{
10591
    dom_dst->id = dom_src->id;
10592 10593 10594 10595 10596 10597 10598 10599 10600 10601 10602
    dom_dst->name = 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 = net_src->name;
    memcpy (net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN);
}

D
Daniel Veillard 已提交
10603 10604 10605 10606 10607 10608 10609 10610
static void
make_nonnull_interface (remote_nonnull_interface *interface_dst,
                        virInterfacePtr interface_src)
{
    interface_dst->name = interface_src->name;
    interface_dst->mac = interface_src->mac;
}

10611 10612 10613 10614 10615 10616 10617 10618 10619 10620 10621 10622 10623 10624 10625
static void
make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
{
    pool_dst->name = 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 = vol_src->pool;
    vol_dst->name = vol_src->name;
    vol_dst->key = vol_src->key;
}

10626 10627 10628
static void
make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
{
10629
    memcpy (secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
10630 10631
    secret_dst->usageType = secret_src->usageType;
    secret_dst->usageID = secret_src->usageID;
10632 10633
}

10634 10635 10636 10637 10638 10639 10640
static void
make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src)
{
    nwfilter_dst->name = nwfilter_src->name;
    memcpy (nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
}

C
Chris Lalancette 已提交
10641 10642 10643 10644 10645 10646 10647
static void
make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src)
{
    snapshot_dst->name = snapshot_src->name;
    make_nonnull_domain(&snapshot_dst->domain, snapshot_src->domain);
}

10648 10649
/*----------------------------------------------------------------------*/

10650 10651 10652 10653 10654
unsigned long remoteVersion(void)
{
    return REMOTE_PROTOCOL_VERSION;
}

10655
static virDriver remote_driver = {
10656 10657 10658 10659 10660 10661 10662
    VIR_DRV_REMOTE,
    "remote",
    remoteOpen, /* open */
    remoteClose, /* close */
    remoteSupportsFeature, /* supports_feature */
    remoteType, /* type */
    remoteGetVersion, /* version */
10663
    remoteGetLibVersion, /* libvirtVersion */
10664 10665 10666 10667 10668 10669 10670 10671 10672 10673 10674 10675 10676 10677 10678 10679 10680 10681 10682 10683 10684 10685 10686 10687
    remoteGetHostname, /* getHostname */
    remoteGetMaxVcpus, /* getMaxVcpus */
    remoteNodeGetInfo, /* nodeGetInfo */
    remoteGetCapabilities, /* getCapabilities */
    remoteListDomains, /* listDomains */
    remoteNumOfDomains, /* numOfDomains */
    remoteDomainCreateXML, /* domainCreateXML */
    remoteDomainLookupByID, /* domainLookupByID */
    remoteDomainLookupByUUID, /* domainLookupByUUID */
    remoteDomainLookupByName, /* domainLookupByName */
    remoteDomainSuspend, /* domainSuspend */
    remoteDomainResume, /* domainResume */
    remoteDomainShutdown, /* domainShutdown */
    remoteDomainReboot, /* domainReboot */
    remoteDomainDestroy, /* domainDestroy */
    remoteDomainGetOSType, /* domainGetOSType */
    remoteDomainGetMaxMemory, /* domainGetMaxMemory */
    remoteDomainSetMaxMemory, /* domainSetMaxMemory */
    remoteDomainSetMemory, /* domainSetMemory */
    remoteDomainGetInfo, /* domainGetInfo */
    remoteDomainSave, /* domainSave */
    remoteDomainRestore, /* domainRestore */
    remoteDomainCoreDump, /* domainCoreDump */
    remoteDomainSetVcpus, /* domainSetVcpus */
E
Eric Blake 已提交
10688 10689
    remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */
    remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */
10690 10691 10692 10693 10694 10695
    remoteDomainPinVcpu, /* domainPinVcpu */
    remoteDomainGetVcpus, /* domainGetVcpus */
    remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */
    remoteDomainGetSecurityLabel, /* domainGetSecurityLabel */
    remoteNodeGetSecurityModel, /* nodeGetSecurityModel */
    remoteDomainDumpXML, /* domainDumpXML */
10696 10697
    remoteDomainXMLFromNative, /* domainXMLFromNative */
    remoteDomainXMLToNative, /* domainXMLToNative */
10698 10699 10700
    remoteListDefinedDomains, /* listDefinedDomains */
    remoteNumOfDefinedDomains, /* numOfDefinedDomains */
    remoteDomainCreate, /* domainCreate */
10701
    remoteDomainCreateWithFlags, /* domainCreateWithFlags */
10702 10703 10704
    remoteDomainDefineXML, /* domainDefineXML */
    remoteDomainUndefine, /* domainUndefine */
    remoteDomainAttachDevice, /* domainAttachDevice */
J
Jim Fehlig 已提交
10705
    remoteDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
10706
    remoteDomainDetachDevice, /* domainDetachDevice */
J
Jim Fehlig 已提交
10707
    remoteDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
10708
    remoteDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */
10709 10710 10711 10712 10713 10714 10715 10716 10717 10718
    remoteDomainGetAutostart, /* domainGetAutostart */
    remoteDomainSetAutostart, /* domainSetAutostart */
    remoteDomainGetSchedulerType, /* domainGetSchedulerType */
    remoteDomainGetSchedulerParameters, /* domainGetSchedulerParameters */
    remoteDomainSetSchedulerParameters, /* domainSetSchedulerParameters */
    remoteDomainMigratePrepare, /* domainMigratePrepare */
    remoteDomainMigratePerform, /* domainMigratePerform */
    remoteDomainMigrateFinish, /* domainMigrateFinish */
    remoteDomainBlockStats, /* domainBlockStats */
    remoteDomainInterfaceStats, /* domainInterfaceStats */
10719
    remoteDomainMemoryStats, /* domainMemoryStats */
10720 10721
    remoteDomainBlockPeek, /* domainBlockPeek */
    remoteDomainMemoryPeek, /* domainMemoryPeek */
10722
    remoteDomainGetBlockInfo, /* domainGetBlockInfo */
10723 10724 10725 10726 10727 10728 10729 10730 10731
    remoteNodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
    remoteNodeGetFreeMemory, /* getFreeMemory */
    remoteDomainEventRegister, /* domainEventRegister */
    remoteDomainEventDeregister, /* domainEventDeregister */
    remoteDomainMigratePrepare2, /* domainMigratePrepare2 */
    remoteDomainMigrateFinish2, /* domainMigrateFinish2 */
    remoteNodeDeviceDettach, /* nodeDeviceDettach */
    remoteNodeDeviceReAttach, /* nodeDeviceReAttach */
    remoteNodeDeviceReset, /* nodeDeviceReset */
C
Chris Lalancette 已提交
10732
    remoteDomainMigratePrepareTunnel, /* domainMigratePrepareTunnel */
10733 10734 10735 10736
    remoteIsEncrypted, /* isEncrypted */
    remoteIsSecure, /* isSecure */
    remoteDomainIsActive, /* domainIsActive */
    remoteDomainIsPersistent, /* domainIsPersistent */
O
Osier Yang 已提交
10737
    NULL, /* domainIsUpdated */
J
Jiri Denemark 已提交
10738
    remoteCPUCompare, /* cpuCompare */
10739
    remoteCPUBaseline, /* cpuBaseline */
10740
    remoteDomainGetJobInfo, /* domainGetJobInfo */
10741
    remoteDomainAbortJob, /* domainFinishJob */
10742
    remoteDomainMigrateSetMaxDowntime, /* domainMigrateSetMaxDowntime */
10743 10744
    remoteDomainEventRegisterAny, /* domainEventRegisterAny */
    remoteDomainEventDeregisterAny, /* domainEventDeregisterAny */
10745 10746 10747
    remoteDomainManagedSave, /* domainManagedSave */
    remoteDomainHasManagedSaveImage, /* domainHasManagedSaveImage */
    remoteDomainManagedSaveRemove, /* domainManagedSaveRemove */
C
Chris Lalancette 已提交
10748 10749 10750 10751 10752 10753 10754 10755 10756
    remoteDomainSnapshotCreateXML, /* domainSnapshotCreateXML */
    remoteDomainSnapshotDumpXML, /* domainSnapshotDumpXML */
    remoteDomainSnapshotNum, /* domainSnapshotNum */
    remoteDomainSnapshotListNames, /* domainSnapshotListNames */
    remoteDomainSnapshotLookupByName, /* domainSnapshotLookupByName */
    remoteDomainHasCurrentSnapshot, /* domainHasCurrentSnapshot */
    remoteDomainSnapshotCurrent, /* domainSnapshotCurrent */
    remoteDomainRevertToSnapshot, /* domainRevertToSnapshot */
    remoteDomainSnapshotDelete, /* domainSnapshotDelete */
C
Chris Lalancette 已提交
10757
    remoteQemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
10758 10759
    remoteDomainSetMemoryParameters, /* domainSetMemoryParameters */
    remoteDomainGetMemoryParameters, /* domainGetMemoryParameters */
10760
    remoteDomainOpenConsole, /* domainOpenConsole */
10761 10762 10763
};

static virNetworkDriver network_driver = {
10764
    .name = "remote",
10765 10766 10767 10768 10769 10770 10771 10772 10773 10774 10775 10776 10777 10778 10779 10780 10781
    .open = remoteNetworkOpen,
    .close = remoteNetworkClose,
    .numOfNetworks = remoteNumOfNetworks,
    .listNetworks = remoteListNetworks,
    .numOfDefinedNetworks = remoteNumOfDefinedNetworks,
    .listDefinedNetworks = remoteListDefinedNetworks,
    .networkLookupByUUID = remoteNetworkLookupByUUID,
    .networkLookupByName = remoteNetworkLookupByName,
    .networkCreateXML = remoteNetworkCreateXML,
    .networkDefineXML = remoteNetworkDefineXML,
    .networkUndefine = remoteNetworkUndefine,
    .networkCreate = remoteNetworkCreate,
    .networkDestroy = remoteNetworkDestroy,
    .networkDumpXML = remoteNetworkDumpXML,
    .networkGetBridgeName = remoteNetworkGetBridgeName,
    .networkGetAutostart = remoteNetworkGetAutostart,
    .networkSetAutostart = remoteNetworkSetAutostart,
10782 10783
    .networkIsActive = remoteNetworkIsActive,
    .networkIsPersistent = remoteNetworkIsPersistent,
10784 10785
};

D
Daniel Veillard 已提交
10786 10787 10788 10789 10790 10791
static virInterfaceDriver interface_driver = {
    .name = "remote",
    .open = remoteInterfaceOpen,
    .close = remoteInterfaceClose,
    .numOfInterfaces = remoteNumOfInterfaces,
    .listInterfaces = remoteListInterfaces,
10792 10793
    .numOfDefinedInterfaces = remoteNumOfDefinedInterfaces,
    .listDefinedInterfaces = remoteListDefinedInterfaces,
D
Daniel Veillard 已提交
10794 10795 10796 10797 10798 10799 10800
    .interfaceLookupByName = remoteInterfaceLookupByName,
    .interfaceLookupByMACString = remoteInterfaceLookupByMACString,
    .interfaceGetXMLDesc = remoteInterfaceGetXMLDesc,
    .interfaceDefineXML = remoteInterfaceDefineXML,
    .interfaceUndefine = remoteInterfaceUndefine,
    .interfaceCreate = remoteInterfaceCreate,
    .interfaceDestroy = remoteInterfaceDestroy,
10801
    .interfaceIsActive = remoteInterfaceIsActive,
D
Daniel Veillard 已提交
10802 10803
};

10804 10805 10806 10807 10808 10809 10810 10811
static virStorageDriver storage_driver = {
    .name = "remote",
    .open = remoteStorageOpen,
    .close = remoteStorageClose,
    .numOfPools = remoteNumOfStoragePools,
    .listPools = remoteListStoragePools,
    .numOfDefinedPools = remoteNumOfDefinedStoragePools,
    .listDefinedPools = remoteListDefinedStoragePools,
10812
    .findPoolSources = remoteFindStoragePoolSources,
10813
    .poolLookupByName = remoteStoragePoolLookupByName,
10814
    .poolLookupByUUID = remoteStoragePoolLookupByUUID,
10815 10816 10817
    .poolLookupByVolume = remoteStoragePoolLookupByVolume,
    .poolCreateXML = remoteStoragePoolCreateXML,
    .poolDefineXML = remoteStoragePoolDefineXML,
10818
    .poolBuild = remoteStoragePoolBuild,
10819 10820 10821 10822 10823 10824 10825 10826 10827 10828 10829 10830 10831 10832 10833 10834
    .poolUndefine = remoteStoragePoolUndefine,
    .poolCreate = remoteStoragePoolCreate,
    .poolDestroy = remoteStoragePoolDestroy,
    .poolDelete = remoteStoragePoolDelete,
    .poolRefresh = remoteStoragePoolRefresh,
    .poolGetInfo = remoteStoragePoolGetInfo,
    .poolGetXMLDesc = remoteStoragePoolDumpXML,
    .poolGetAutostart = remoteStoragePoolGetAutostart,
    .poolSetAutostart = remoteStoragePoolSetAutostart,
    .poolNumOfVolumes = remoteStoragePoolNumOfVolumes,
    .poolListVolumes = remoteStoragePoolListVolumes,

    .volLookupByName = remoteStorageVolLookupByName,
    .volLookupByKey = remoteStorageVolLookupByKey,
    .volLookupByPath = remoteStorageVolLookupByPath,
    .volCreateXML = remoteStorageVolCreateXML,
10835
    .volCreateXMLFrom = remoteStorageVolCreateXMLFrom,
10836
    .volDelete = remoteStorageVolDelete,
10837
    .volWipe = remoteStorageVolWipe,
10838 10839 10840
    .volGetInfo = remoteStorageVolGetInfo,
    .volGetXMLDesc = remoteStorageVolDumpXML,
    .volGetPath = remoteStorageVolGetPath,
10841 10842
    .poolIsActive = remoteStoragePoolIsActive,
    .poolIsPersistent = remoteStoragePoolIsPersistent,
10843 10844
};

10845 10846 10847 10848 10849 10850
static virSecretDriver secret_driver = {
    .name = "remote",
    .open = remoteSecretOpen,
    .close = remoteSecretClose,
    .numOfSecrets = remoteSecretNumOfSecrets,
    .listSecrets = remoteSecretListSecrets,
10851
    .lookupByUUID = remoteSecretLookupByUUID,
10852
    .lookupByUsage = remoteSecretLookupByUsage,
10853 10854 10855 10856 10857 10858 10859
    .defineXML = remoteSecretDefineXML,
    .getXMLDesc = remoteSecretGetXMLDesc,
    .setValue = remoteSecretSetValue,
    .getValue = remoteSecretGetValue,
    .undefine = remoteSecretUndefine
};

10860 10861 10862 10863 10864 10865 10866 10867 10868 10869 10870
static virDeviceMonitor dev_monitor = {
    .name = "remote",
    .open = remoteDevMonOpen,
    .close = remoteDevMonClose,
    .numOfDevices = remoteNodeNumOfDevices,
    .listDevices = remoteNodeListDevices,
    .deviceLookupByName = remoteNodeDeviceLookupByName,
    .deviceDumpXML = remoteNodeDeviceDumpXML,
    .deviceGetParent = remoteNodeDeviceGetParent,
    .deviceNumOfCaps = remoteNodeDeviceNumOfCaps,
    .deviceListCaps = remoteNodeDeviceListCaps,
10871 10872
    .deviceCreateXML = remoteNodeDeviceCreateXML,
    .deviceDestroy = remoteNodeDeviceDestroy
10873 10874
};

10875 10876 10877 10878 10879 10880 10881 10882 10883 10884 10885 10886 10887
static virNWFilterDriver nwfilter_driver = {
    .name = "remote",
    .open = remoteNWFilterOpen,
    .close = remoteNWFilterClose,
    .nwfilterLookupByUUID = remoteNWFilterLookupByUUID,
    .nwfilterLookupByName = remoteNWFilterLookupByName,
    .getXMLDesc           = remoteNWFilterGetXMLDesc,
    .defineXML            = remoteNWFilterDefineXML,
    .undefine             = remoteNWFilterUndefine,
    .numOfNWFilters       = remoteNumOfNWFilters,
    .listNWFilters        = remoteListNWFilters,
};

10888

A
Atsushi SAKAI 已提交
10889
#ifdef WITH_LIBVIRTD
10890
static virStateDriver state_driver = {
10891
    .name = "Remote",
10892
    .initialize = remoteStartup,
10893
};
A
Atsushi SAKAI 已提交
10894
#endif
10895 10896


10897
/** remoteRegister:
10898 10899
 *
 * Register driver with libvirt driver system.
10900 10901
 *
 * Returns -1 on error.
10902 10903 10904 10905
 */
int
remoteRegister (void)
{
10906
    if (virRegisterDriver (&remote_driver) == -1) return -1;
10907
    if (virRegisterNetworkDriver (&network_driver) == -1) return -1;
D
Daniel Veillard 已提交
10908
    if (virRegisterInterfaceDriver (&interface_driver) == -1) return -1;
10909
    if (virRegisterStorageDriver (&storage_driver) == -1) return -1;
10910
    if (virRegisterDeviceMonitor (&dev_monitor) == -1) return -1;
10911
    if (virRegisterSecretDriver (&secret_driver) == -1) return -1;
10912
    if (virRegisterNWFilterDriver(&nwfilter_driver) == -1) return -1;
A
Atsushi SAKAI 已提交
10913
#ifdef WITH_LIBVIRTD
10914
    if (virRegisterStateDriver (&state_driver) == -1) return -1;
A
Atsushi SAKAI 已提交
10915
#endif
10916 10917 10918

    return 0;
}