~smb/ubuntu/quantal/libvirt/proposed

« back to all changes in this revision

Viewing changes to .pc/lp1039678.patch/src/remote/remote_driver.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-09-26 11:49:45 UTC
  • mfrom: (221.1.2 quantal)
  • Revision ID: package-import@ubuntu.com-20120926114945-qfxa3lw60vn8cw4p
Tags: 0.9.13-0ubuntu11
* SECURITY UPDATE: denial of service via invalid RPC command
  - debian/patches/CVE-2012-3445.patch: make sure nparams isn't set to
    zero in daemon/remote.c.
  - CVE-2012-3445

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * remote_driver.c: driver to provide access to libvirtd running
 
3
 *   on a remote machine
 
4
 *
 
5
 * Copyright (C) 2007-2012 Red Hat, Inc.
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
20
 *
 
21
 * Author: Richard Jones <rjones@redhat.com>
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include <unistd.h>
 
27
#include <assert.h>
 
28
 
 
29
#include "virnetclient.h"
 
30
#include "virnetclientprogram.h"
 
31
#include "virnetclientstream.h"
 
32
#include "virterror_internal.h"
 
33
#include "logging.h"
 
34
#include "datatypes.h"
 
35
#include "domain_event.h"
 
36
#include "driver.h"
 
37
#include "buf.h"
 
38
#include "remote_driver.h"
 
39
#include "remote_protocol.h"
 
40
#include "qemu_protocol.h"
 
41
#include "memory.h"
 
42
#include "util.h"
 
43
#include "virfile.h"
 
44
#include "command.h"
 
45
#include "intprops.h"
 
46
#include "virtypedparam.h"
 
47
#include "viruri.h"
 
48
#include "virauth.h"
 
49
#include "virauthconfig.h"
 
50
 
 
51
#define VIR_FROM_THIS VIR_FROM_REMOTE
 
52
 
 
53
#if SIZEOF_LONG < 8
 
54
# define HYPER_TO_TYPE(_type, _to, _from)                                     \
 
55
    do {                                                                      \
 
56
        if ((_from) != (_type)(_from)) {                                      \
 
57
            remoteError(VIR_ERR_INTERNAL_ERROR,                               \
 
58
                        _("conversion from hyper to %s overflowed"), #_type); \
 
59
            goto done;                                                        \
 
60
        }                                                                     \
 
61
        (_to) = (_from);                                                      \
 
62
    } while (0)
 
63
 
 
64
# define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
 
65
# define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
 
66
#else
 
67
# define HYPER_TO_LONG(_to, _from) (_to) = (_from)
 
68
# define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
 
69
#endif
 
70
 
 
71
static int inside_daemon = 0;
 
72
static virDriverPtr remoteDriver = NULL;
 
73
 
 
74
struct private_data {
 
75
    virMutex lock;
 
76
 
 
77
    virNetClientPtr client;
 
78
    virNetClientProgramPtr remoteProgram;
 
79
    virNetClientProgramPtr qemuProgram;
 
80
 
 
81
    int counter; /* Serial number for RPC */
 
82
 
 
83
    virNetTLSContextPtr tls;
 
84
 
 
85
    int is_secure;              /* Secure if TLS or SASL or UNIX sockets */
 
86
    char *type;                 /* Cached return from remoteType. */
 
87
    int localUses;              /* Ref count for private data */
 
88
    char *hostname;             /* Original hostname */
 
89
    bool serverKeepAlive;       /* Does server support keepalive protocol? */
 
90
 
 
91
    virDomainEventStatePtr domainEventState;
 
92
};
 
93
 
 
94
enum {
 
95
    REMOTE_CALL_QEMU              = (1 << 0),
 
96
};
 
97
 
 
98
 
 
99
static void remoteDriverLock(struct private_data *driver)
 
100
{
 
101
    virMutexLock(&driver->lock);
 
102
}
 
103
 
 
104
static void remoteDriverUnlock(struct private_data *driver)
 
105
{
 
106
    virMutexUnlock(&driver->lock);
 
107
}
 
108
 
 
109
static int call(virConnectPtr conn, struct private_data *priv,
 
110
                unsigned int flags, int proc_nr,
 
111
                xdrproc_t args_filter, char *args,
 
112
                xdrproc_t ret_filter, char *ret);
 
113
static int callWithFD(virConnectPtr conn, struct private_data *priv,
 
114
                      unsigned int flags, int fd, int proc_nr,
 
115
                      xdrproc_t args_filter, char *args,
 
116
                      xdrproc_t ret_filter, char *ret);
 
117
static int remoteAuthenticate (virConnectPtr conn, struct private_data *priv,
 
118
                               virConnectAuthPtr auth, const char *authtype);
 
119
#if HAVE_SASL
 
120
static int remoteAuthSASL (virConnectPtr conn, struct private_data *priv,
 
121
                           virConnectAuthPtr auth, const char *mech);
 
122
#endif
 
123
#if HAVE_POLKIT
 
124
static int remoteAuthPolkit (virConnectPtr conn, struct private_data *priv,
 
125
                             virConnectAuthPtr auth);
 
126
#endif /* HAVE_POLKIT */
 
127
 
 
128
#define remoteError(code, ...)                                    \
 
129
    virReportErrorHelper(VIR_FROM_REMOTE, code, __FILE__,         \
 
130
                         __FUNCTION__, __LINE__, __VA_ARGS__)
 
131
 
 
132
static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain);
 
133
static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network);
 
134
static virNWFilterPtr get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter);
 
135
static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface);
 
136
static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool);
 
137
static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol);
 
138
static virNodeDevicePtr get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev);
 
139
static virSecretPtr get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret);
 
140
static virDomainSnapshotPtr get_nonnull_domain_snapshot (virDomainPtr domain, remote_nonnull_domain_snapshot snapshot);
 
141
static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
 
142
static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src);
 
143
static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
 
144
static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src);
 
145
static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
 
146
static void make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
 
147
static void make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src);
 
148
static void make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
 
149
static void remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event);
 
150
/*----------------------------------------------------------------------*/
 
151
 
 
152
/* Helper functions for remoteOpen. */
 
153
static char *get_transport_from_scheme (char *scheme);
 
154
 
 
155
#ifdef WITH_LIBVIRTD
 
156
static int
 
157
remoteStartup(int privileged ATTRIBUTE_UNUSED)
 
158
{
 
159
    /* Mark that we're inside the daemon so we can avoid
 
160
     * re-entering ourselves
 
161
     */
 
162
    inside_daemon = 1;
 
163
    return 0;
 
164
}
 
165
#endif
 
166
 
 
167
#ifndef WIN32
 
168
/**
 
169
 * remoteFindDaemonPath:
 
170
 *
 
171
 * Tries to find the path to the libvirtd binary.
 
172
 *
 
173
 * Returns path on success or NULL in case of error.
 
174
 */
 
175
static const char *
 
176
remoteFindDaemonPath(void)
 
177
{
 
178
    static const char *serverPaths[] = {
 
179
        SBINDIR "/libvirtd",
 
180
        SBINDIR "/libvirtd_dbg",
 
181
        NULL
 
182
    };
 
183
    int i;
 
184
    const char *customDaemon = getenv("LIBVIRTD_PATH");
 
185
 
 
186
    if (customDaemon)
 
187
        return customDaemon;
 
188
 
 
189
    for (i = 0; serverPaths[i]; i++) {
 
190
        if (virFileIsExecutable(serverPaths[i])) {
 
191
            return serverPaths[i];
 
192
        }
 
193
    }
 
194
    return NULL;
 
195
}
 
196
#endif
 
197
 
 
198
 
 
199
static void
 
200
remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
201
                                virNetClientPtr client ATTRIBUTE_UNUSED,
 
202
                                void *evdata, void *opaque);
 
203
static void
 
204
remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
205
                             virNetClientPtr client ATTRIBUTE_UNUSED,
 
206
                             void *evdata, void *opaque);
 
207
static void
 
208
remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog,
 
209
                                virNetClientPtr client,
 
210
                                void *evdata, void *opaque);
 
211
static void
 
212
remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog,
 
213
                               virNetClientPtr client,
 
214
                               void *evdata, void *opaque);
 
215
static void
 
216
remoteDomainBuildEventIOError(virNetClientProgramPtr prog,
 
217
                              virNetClientPtr client,
 
218
                              void *evdata, void *opaque);
 
219
static void
 
220
remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog,
 
221
                                    virNetClientPtr client,
 
222
                                    void *evdata, void *opaque);
 
223
static void
 
224
remoteDomainBuildEventGraphics(virNetClientProgramPtr prog,
 
225
                               virNetClientPtr client,
 
226
                               void *evdata, void *opaque);
 
227
static void
 
228
remoteDomainBuildEventControlError(virNetClientProgramPtr prog,
 
229
                                   virNetClientPtr client,
 
230
                                   void *evdata, void *opaque);
 
231
 
 
232
static void
 
233
remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog,
 
234
                               virNetClientPtr client,
 
235
                               void *evdata, void *opaque);
 
236
 
 
237
static void
 
238
remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog,
 
239
                                 virNetClientPtr client,
 
240
                                 void *evdata, void *opaque);
 
241
 
 
242
static void
 
243
remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog,
 
244
                                 virNetClientPtr client,
 
245
                                 void *evdata, void *opaque);
 
246
 
 
247
static void
 
248
remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog,
 
249
                               virNetClientPtr client,
 
250
                               void *evdata, void *opaque);
 
251
 
 
252
static void
 
253
remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog,
 
254
                                virNetClientPtr client,
 
255
                                void *evdata, void *opaque);
 
256
 
 
257
static virNetClientProgramEvent remoteDomainEvents[] = {
 
258
    { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
 
259
      remoteDomainBuildEventRTCChange,
 
260
      sizeof(remote_domain_event_rtc_change_msg),
 
261
      (xdrproc_t)xdr_remote_domain_event_rtc_change_msg },
 
262
    { REMOTE_PROC_DOMAIN_EVENT_REBOOT,
 
263
      remoteDomainBuildEventReboot,
 
264
      sizeof(remote_domain_event_reboot_msg),
 
265
      (xdrproc_t)xdr_remote_domain_event_reboot_msg },
 
266
    { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
 
267
      remoteDomainBuildEventLifecycle,
 
268
      sizeof(remote_domain_event_lifecycle_msg),
 
269
      (xdrproc_t)xdr_remote_domain_event_lifecycle_msg },
 
270
    { REMOTE_PROC_DOMAIN_EVENT_WATCHDOG,
 
271
      remoteDomainBuildEventWatchdog,
 
272
      sizeof(remote_domain_event_watchdog_msg),
 
273
      (xdrproc_t)xdr_remote_domain_event_watchdog_msg},
 
274
    { REMOTE_PROC_DOMAIN_EVENT_IO_ERROR,
 
275
      remoteDomainBuildEventIOError,
 
276
      sizeof(remote_domain_event_io_error_msg),
 
277
      (xdrproc_t)xdr_remote_domain_event_io_error_msg },
 
278
    { REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON,
 
279
      remoteDomainBuildEventIOErrorReason,
 
280
      sizeof(remote_domain_event_io_error_reason_msg),
 
281
      (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg },
 
282
    { REMOTE_PROC_DOMAIN_EVENT_GRAPHICS,
 
283
      remoteDomainBuildEventGraphics,
 
284
      sizeof(remote_domain_event_graphics_msg),
 
285
      (xdrproc_t)xdr_remote_domain_event_graphics_msg },
 
286
    { REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR,
 
287
      remoteDomainBuildEventControlError,
 
288
      sizeof(remote_domain_event_control_error_msg),
 
289
      (xdrproc_t)xdr_remote_domain_event_control_error_msg },
 
290
    { REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB,
 
291
      remoteDomainBuildEventBlockJob,
 
292
      sizeof(remote_domain_event_block_job_msg),
 
293
      (xdrproc_t)xdr_remote_domain_event_block_job_msg },
 
294
    { REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE,
 
295
      remoteDomainBuildEventDiskChange,
 
296
      sizeof(remote_domain_event_disk_change_msg),
 
297
      (xdrproc_t)xdr_remote_domain_event_disk_change_msg },
 
298
    { REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE,
 
299
      remoteDomainBuildEventTrayChange,
 
300
      sizeof(remote_domain_event_tray_change_msg),
 
301
      (xdrproc_t)xdr_remote_domain_event_tray_change_msg },
 
302
    { REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP,
 
303
      remoteDomainBuildEventPMWakeup,
 
304
      sizeof(remote_domain_event_pmwakeup_msg),
 
305
      (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg },
 
306
    { REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND,
 
307
      remoteDomainBuildEventPMSuspend,
 
308
      sizeof(remote_domain_event_pmsuspend_msg),
 
309
      (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg },
 
310
};
 
311
 
 
312
enum virDrvOpenRemoteFlags {
 
313
    VIR_DRV_OPEN_REMOTE_RO = (1 << 0),
 
314
    VIR_DRV_OPEN_REMOTE_USER      = (1 << 1), /* Use the per-user socket path */
 
315
    VIR_DRV_OPEN_REMOTE_AUTOSTART = (1 << 2), /* Autostart a per-user daemon */
 
316
};
 
317
 
 
318
 
 
319
/*
 
320
 * URIs that this driver needs to handle:
 
321
 *
 
322
 * The easy answer:
 
323
 *   - Everything that no one else has yet claimed, but nothing if
 
324
 *     we're inside the libvirtd daemon
 
325
 *
 
326
 * The hard answer:
 
327
 *   - Plain paths (///var/lib/xen/xend-socket)  -> UNIX domain socket
 
328
 *   - xxx://servername/      -> TLS connection
 
329
 *   - xxx+tls://servername/  -> TLS connection
 
330
 *   - xxx+tls:///            -> TLS connection to localhost
 
331
 *   - xxx+tcp://servername/  -> TCP connection
 
332
 *   - xxx+tcp:///            -> TCP connection to localhost
 
333
 *   - xxx+unix:///           -> UNIX domain socket
 
334
 *   - xxx:///                -> UNIX domain socket
 
335
 */
 
336
static int
 
337
doRemoteOpen (virConnectPtr conn,
 
338
              struct private_data *priv,
 
339
              virConnectAuthPtr auth ATTRIBUTE_UNUSED,
 
340
              unsigned int flags)
 
341
{
 
342
    char *transport_str = NULL;
 
343
    enum {
 
344
        trans_tls,
 
345
        trans_unix,
 
346
        trans_ssh,
 
347
        trans_ext,
 
348
        trans_tcp,
 
349
    } transport;
 
350
#ifndef WIN32
 
351
    const char *daemonPath;
 
352
#endif
 
353
 
 
354
    /* We handle *ALL*  URIs here. The caller has rejected any
 
355
     * URIs we don't care about */
 
356
 
 
357
    if (conn->uri) {
 
358
        if (!conn->uri->scheme) {
 
359
            /* This is the ///var/lib/xen/xend-socket local path style */
 
360
            if (!conn->uri->path)
 
361
                return VIR_DRV_OPEN_DECLINED;
 
362
            if (conn->uri->path[0] != '/')
 
363
                return VIR_DRV_OPEN_DECLINED;
 
364
 
 
365
            transport = trans_unix;
 
366
        } else {
 
367
            transport_str = get_transport_from_scheme (conn->uri->scheme);
 
368
 
 
369
            if (!transport_str) {
 
370
                if (conn->uri->server)
 
371
                    transport = trans_tls;
 
372
                else
 
373
                    transport = trans_unix;
 
374
            } else {
 
375
                if (STRCASEEQ (transport_str, "tls"))
 
376
                    transport = trans_tls;
 
377
                else if (STRCASEEQ (transport_str, "unix")) {
 
378
                    if (conn->uri->server) {
 
379
                        remoteError(VIR_ERR_INVALID_ARG,
 
380
                                    _("using unix socket and remote "
 
381
                                      "server '%s' is not supported."),
 
382
                                    conn->uri->server);
 
383
                        return VIR_DRV_OPEN_ERROR;
 
384
                    } else {
 
385
                        transport = trans_unix;
 
386
                    }
 
387
                } else if (STRCASEEQ (transport_str, "ssh"))
 
388
                    transport = trans_ssh;
 
389
                else if (STRCASEEQ (transport_str, "ext"))
 
390
                    transport = trans_ext;
 
391
                else if (STRCASEEQ (transport_str, "tcp"))
 
392
                    transport = trans_tcp;
 
393
                else {
 
394
                    remoteError(VIR_ERR_INVALID_ARG, "%s",
 
395
                                _("remote_open: transport in URL not recognised "
 
396
                                  "(should be tls|unix|ssh|ext|tcp)"));
 
397
                    return VIR_DRV_OPEN_ERROR;
 
398
                }
 
399
            }
 
400
        }
 
401
    } else {
 
402
        /* No URI, then must be probing so use UNIX socket */
 
403
        transport = trans_unix;
 
404
    }
 
405
 
 
406
    /* Local variables which we will initialize. These can
 
407
     * get freed in the failed: path.
 
408
     */
 
409
    char *name = NULL, *command = NULL, *sockname = NULL, *netcat = NULL;
 
410
    char *port = NULL, *authtype = NULL, *username = NULL;
 
411
    bool sanity = true, verify = true, tty ATTRIBUTE_UNUSED = true;
 
412
    char *pkipath = NULL, *keyfile = NULL;
 
413
 
 
414
    /* Return code from this function, and the private data. */
 
415
    int retcode = VIR_DRV_OPEN_ERROR;
 
416
 
 
417
    /* Remote server defaults to "localhost" if not specified. */
 
418
    if (conn->uri && conn->uri->port != 0) {
 
419
        if (virAsprintf(&port, "%d", conn->uri->port) == -1) goto out_of_memory;
 
420
    } else if (transport == trans_tls) {
 
421
        port = strdup (LIBVIRTD_TLS_PORT);
 
422
        if (!port) goto out_of_memory;
 
423
    } else if (transport == trans_tcp) {
 
424
        port = strdup (LIBVIRTD_TCP_PORT);
 
425
        if (!port) goto out_of_memory;
 
426
    } else
 
427
        port = NULL; /* Port not used for unix, ext., default for ssh */
 
428
 
 
429
 
 
430
    priv->hostname = strdup (conn->uri && conn->uri->server ?
 
431
                             conn->uri->server : "localhost");
 
432
    if (!priv->hostname)
 
433
        goto out_of_memory;
 
434
    if (conn->uri && conn->uri->user) {
 
435
        username = strdup (conn->uri->user);
 
436
        if (!username)
 
437
            goto out_of_memory;
 
438
    }
 
439
 
 
440
    /* Get the variables from the query string.
 
441
     * Then we need to reconstruct the query string (because
 
442
     * feasibly it might contain variables needed by the real driver,
 
443
     * although that won't be the case for now).
 
444
     */
 
445
    int i;
 
446
 
 
447
    if (conn->uri) {
 
448
        for (i = 0; i < conn->uri->paramsCount ; i++) {
 
449
            virURIParamPtr var = &conn->uri->params[i];
 
450
            if (STRCASEEQ (var->name, "name")) {
 
451
                VIR_FREE(name);
 
452
                name = strdup (var->value);
 
453
                if (!name) goto out_of_memory;
 
454
                var->ignore = 1;
 
455
            } else if (STRCASEEQ (var->name, "command")) {
 
456
                VIR_FREE(command);
 
457
                command = strdup (var->value);
 
458
                if (!command) goto out_of_memory;
 
459
                var->ignore = 1;
 
460
            } else if (STRCASEEQ (var->name, "socket")) {
 
461
                VIR_FREE(sockname);
 
462
                sockname = strdup (var->value);
 
463
                if (!sockname) goto out_of_memory;
 
464
                var->ignore = 1;
 
465
            } else if (STRCASEEQ (var->name, "auth")) {
 
466
                VIR_FREE(authtype);
 
467
                authtype = strdup (var->value);
 
468
                if (!authtype) goto out_of_memory;
 
469
                var->ignore = 1;
 
470
            } else if (STRCASEEQ (var->name, "netcat")) {
 
471
                VIR_FREE(netcat);
 
472
                netcat = strdup (var->value);
 
473
                if (!netcat) goto out_of_memory;
 
474
                var->ignore = 1;
 
475
            } else if (STRCASEEQ (var->name, "keyfile")) {
 
476
                VIR_FREE(keyfile);
 
477
                keyfile = strdup (var->value);
 
478
                if (!keyfile) goto out_of_memory;
 
479
            } else if (STRCASEEQ (var->name, "no_sanity")) {
 
480
                sanity = atoi(var->value) == 0;
 
481
                var->ignore = 1;
 
482
            } else if (STRCASEEQ (var->name, "no_verify")) {
 
483
                verify = atoi (var->value) == 0;
 
484
                var->ignore = 1;
 
485
            } else if (STRCASEEQ (var->name, "no_tty")) {
 
486
                tty = atoi (var->value) == 0;
 
487
                var->ignore = 1;
 
488
            } else if (STRCASEEQ(var->name, "pkipath")) {
 
489
                VIR_FREE(pkipath);
 
490
                pkipath = strdup(var->value);
 
491
                if (!pkipath) goto out_of_memory;
 
492
                var->ignore = 1;
 
493
            } else if (STRCASEEQ(var->name, "authfile")) {
 
494
                /* Strip this param, used by virauth.c */
 
495
                var->ignore = 1;
 
496
            } else {
 
497
                VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
 
498
                      var->name, var->value);
 
499
            }
 
500
        }
 
501
 
 
502
        /* Construct the original name. */
 
503
        if (!name) {
 
504
            if (conn->uri->scheme &&
 
505
                (STREQ(conn->uri->scheme, "remote") ||
 
506
                 STRPREFIX(conn->uri->scheme, "remote+"))) {
 
507
                /* Allow remote serve to probe */
 
508
                if (!(name = strdup("")))
 
509
                    goto out_of_memory;
 
510
            } else {
 
511
                virURI tmpuri = {
 
512
                    .scheme = conn->uri->scheme,
 
513
                    .query = virURIFormatParams(conn->uri),
 
514
                    .path = conn->uri->path,
 
515
                    .fragment = conn->uri->fragment,
 
516
                };
 
517
 
 
518
                /* Evil, blank out transport scheme temporarily */
 
519
                if (transport_str) {
 
520
                    assert (transport_str[-1] == '+');
 
521
                    transport_str[-1] = '\0';
 
522
                }
 
523
 
 
524
                name = virURIFormat(&tmpuri);
 
525
 
 
526
                VIR_FREE(tmpuri.query);
 
527
 
 
528
                /* Restore transport scheme */
 
529
                if (transport_str)
 
530
                    transport_str[-1] = '+';
 
531
 
 
532
                if (!name)
 
533
                    goto failed;
 
534
            }
 
535
        }
 
536
    } else {
 
537
        /* Probe URI server side */
 
538
        if (!(name = strdup("")))
 
539
            goto out_of_memory;
 
540
    }
 
541
 
 
542
    VIR_DEBUG("proceeding with name = %s", name);
 
543
 
 
544
    /* For ext transport, command is required. */
 
545
    if (transport == trans_ext && !command) {
 
546
        remoteError(VIR_ERR_INVALID_ARG, "%s",
 
547
                    _("remote_open: for 'ext' transport, command is required"));
 
548
        goto failed;
 
549
    }
 
550
 
 
551
 
 
552
    VIR_DEBUG("Connecting with transport %d", transport);
 
553
    /* Connect to the remote service. */
 
554
    switch (transport) {
 
555
    case trans_tls:
 
556
        priv->tls = virNetTLSContextNewClientPath(pkipath,
 
557
                                                  geteuid() != 0 ? true : false,
 
558
                                                  sanity, verify);
 
559
        if (!priv->tls)
 
560
            goto failed;
 
561
        priv->is_secure = 1;
 
562
 
 
563
        /*FALLTHROUGH*/
 
564
    case trans_tcp:
 
565
        priv->client = virNetClientNewTCP(priv->hostname, port);
 
566
        if (!priv->client)
 
567
            goto failed;
 
568
 
 
569
        if (priv->tls) {
 
570
            VIR_DEBUG("Starting TLS session");
 
571
            if (virNetClientSetTLSSession(priv->client, priv->tls) < 0)
 
572
                goto failed;
 
573
        }
 
574
 
 
575
        break;
 
576
 
 
577
#ifndef WIN32
 
578
    case trans_unix:
 
579
        if (!sockname) {
 
580
            if (flags & VIR_DRV_OPEN_REMOTE_USER) {
 
581
                char *userdir = virGetUserRuntimeDirectory();
 
582
 
 
583
                if (!userdir)
 
584
                    goto failed;
 
585
 
 
586
                if (virAsprintf(&sockname, "%s/" LIBVIRTD_USER_UNIX_SOCKET, userdir) < 0) {
 
587
                    VIR_FREE(userdir);
 
588
                    goto out_of_memory;
 
589
                }
 
590
                VIR_FREE(userdir);
 
591
            } else {
 
592
                if (flags & VIR_DRV_OPEN_REMOTE_RO)
 
593
                    sockname = strdup(LIBVIRTD_PRIV_UNIX_SOCKET_RO);
 
594
                else
 
595
                    sockname = strdup(LIBVIRTD_PRIV_UNIX_SOCKET);
 
596
                if (sockname == NULL)
 
597
                    goto out_of_memory;
 
598
            }
 
599
            VIR_DEBUG("Proceeding with sockname %s", sockname);
 
600
        }
 
601
 
 
602
        if (!(daemonPath = remoteFindDaemonPath())) {
 
603
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
604
                        _("Unable to locate libvirtd daemon in $PATH"));
 
605
            goto failed;
 
606
        }
 
607
        if (!(priv->client = virNetClientNewUNIX(sockname,
 
608
                                                 flags & VIR_DRV_OPEN_REMOTE_AUTOSTART,
 
609
                                                 daemonPath)))
 
610
            goto failed;
 
611
 
 
612
        priv->is_secure = 1;
 
613
        break;
 
614
 
 
615
    case trans_ssh:
 
616
        command = command ? command : strdup ("ssh");
 
617
        if (command == NULL)
 
618
            goto out_of_memory;
 
619
 
 
620
        if (!sockname) {
 
621
            if (flags & VIR_DRV_OPEN_REMOTE_RO)
 
622
                sockname = strdup(LIBVIRTD_PRIV_UNIX_SOCKET_RO);
 
623
            else
 
624
                sockname = strdup(LIBVIRTD_PRIV_UNIX_SOCKET);
 
625
            if (sockname == NULL)
 
626
                goto out_of_memory;
 
627
        }
 
628
 
 
629
        if (!(priv->client = virNetClientNewSSH(priv->hostname,
 
630
                                                port,
 
631
                                                command,
 
632
                                                username,
 
633
                                                !tty,
 
634
                                                !verify,
 
635
                                                netcat ? netcat : "nc",
 
636
                                                keyfile,
 
637
                                                sockname)))
 
638
            goto failed;
 
639
 
 
640
        priv->is_secure = 1;
 
641
        break;
 
642
 
 
643
    case trans_ext: {
 
644
        char const *cmd_argv[] = { command, NULL };
 
645
        if (!(priv->client = virNetClientNewExternal(cmd_argv)))
 
646
            goto failed;
 
647
 
 
648
        /* Do not set 'is_secure' flag since we can't guarantee
 
649
         * an external program is secure, and this flag must be
 
650
         * pessimistic */
 
651
    }   break;
 
652
 
 
653
#else /* WIN32 */
 
654
 
 
655
    case trans_unix:
 
656
    case trans_ssh:
 
657
    case trans_ext:
 
658
        remoteError(VIR_ERR_INVALID_ARG, "%s",
 
659
                    _("transport methods unix, ssh and ext are not supported "
 
660
                      "under Windows"));
 
661
        goto failed;
 
662
 
 
663
#endif /* WIN32 */
 
664
    } /* switch (transport) */
 
665
 
 
666
    if (!(priv->remoteProgram = virNetClientProgramNew(REMOTE_PROGRAM,
 
667
                                                       REMOTE_PROTOCOL_VERSION,
 
668
                                                       remoteDomainEvents,
 
669
                                                       ARRAY_CARDINALITY(remoteDomainEvents),
 
670
                                                       conn)))
 
671
        goto failed;
 
672
    if (!(priv->qemuProgram = virNetClientProgramNew(QEMU_PROGRAM,
 
673
                                                     QEMU_PROTOCOL_VERSION,
 
674
                                                     NULL,
 
675
                                                     0,
 
676
                                                     NULL)))
 
677
        goto failed;
 
678
 
 
679
    if (virNetClientAddProgram(priv->client, priv->remoteProgram) < 0 ||
 
680
        virNetClientAddProgram(priv->client, priv->qemuProgram) < 0)
 
681
        goto failed;
 
682
 
 
683
    /* Try and authenticate with server */
 
684
    VIR_DEBUG("Trying authentication");
 
685
    if (remoteAuthenticate(conn, priv, auth, authtype) == -1)
 
686
        goto failed;
 
687
 
 
688
    if (virNetClientKeepAliveIsSupported(priv->client)) {
 
689
        remote_supports_feature_args args =
 
690
            { VIR_DRV_FEATURE_PROGRAM_KEEPALIVE };
 
691
        remote_supports_feature_ret ret = { 0 };
 
692
        int rc;
 
693
 
 
694
        rc = call(conn, priv, 0, REMOTE_PROC_SUPPORTS_FEATURE,
 
695
                  (xdrproc_t)xdr_remote_supports_feature_args, (char *) &args,
 
696
                  (xdrproc_t)xdr_remote_supports_feature_ret, (char *) &ret);
 
697
 
 
698
        if (rc != -1 && ret.supported) {
 
699
            priv->serverKeepAlive = true;
 
700
        } else {
 
701
            VIR_INFO("Disabling keepalive protocol since it is not supported"
 
702
                     " by the server");
 
703
        }
 
704
    }
 
705
 
 
706
    /* Finally we can call the remote side's open function. */
 
707
    {
 
708
        remote_open_args args = { &name, flags };
 
709
 
 
710
        VIR_DEBUG("Trying to open URI %s", name);
 
711
        if (call (conn, priv, 0, REMOTE_PROC_OPEN,
 
712
                  (xdrproc_t) xdr_remote_open_args, (char *) &args,
 
713
                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
714
            goto failed;
 
715
    }
 
716
 
 
717
    /* Now try and find out what URI the daemon used */
 
718
    if (conn->uri == NULL) {
 
719
        remote_get_uri_ret uriret;
 
720
 
 
721
        VIR_DEBUG("Trying to query remote URI");
 
722
        memset (&uriret, 0, sizeof(uriret));
 
723
        if (call (conn, priv, 0,
 
724
                  REMOTE_PROC_GET_URI,
 
725
                  (xdrproc_t) xdr_void, (char *) NULL,
 
726
                  (xdrproc_t) xdr_remote_get_uri_ret, (char *) &uriret) < 0)
 
727
            goto failed;
 
728
 
 
729
        VIR_DEBUG("Auto-probed URI is %s", uriret.uri);
 
730
        conn->uri = virURIParse(uriret.uri);
 
731
        VIR_FREE(uriret.uri);
 
732
        if (!conn->uri)
 
733
            goto failed;
 
734
    }
 
735
 
 
736
    if (!(priv->domainEventState = virDomainEventStateNew()))
 
737
        goto failed;
 
738
 
 
739
    /* Successful. */
 
740
    retcode = VIR_DRV_OPEN_SUCCESS;
 
741
 
 
742
 cleanup:
 
743
    /* Free up the URL and strings. */
 
744
    VIR_FREE(name);
 
745
    VIR_FREE(command);
 
746
    VIR_FREE(sockname);
 
747
    VIR_FREE(authtype);
 
748
    VIR_FREE(netcat);
 
749
    VIR_FREE(keyfile);
 
750
    VIR_FREE(username);
 
751
    VIR_FREE(port);
 
752
    VIR_FREE(pkipath);
 
753
 
 
754
    return retcode;
 
755
 
 
756
 out_of_memory:
 
757
    virReportOOMError();
 
758
 
 
759
 failed:
 
760
    virNetClientProgramFree(priv->remoteProgram);
 
761
    virNetClientProgramFree(priv->qemuProgram);
 
762
    virNetClientClose(priv->client);
 
763
    virNetClientFree(priv->client);
 
764
    priv->client = NULL;
 
765
 
 
766
    VIR_FREE(priv->hostname);
 
767
    goto cleanup;
 
768
}
 
769
 
 
770
static struct private_data *
 
771
remoteAllocPrivateData(void)
 
772
{
 
773
    struct private_data *priv;
 
774
    if (VIR_ALLOC(priv) < 0) {
 
775
        virReportOOMError();
 
776
        return NULL;
 
777
    }
 
778
 
 
779
    if (virMutexInit(&priv->lock) < 0) {
 
780
        remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
781
                    _("cannot initialize mutex"));
 
782
        VIR_FREE(priv);
 
783
        return NULL;
 
784
    }
 
785
    remoteDriverLock(priv);
 
786
    priv->localUses = 1;
 
787
 
 
788
    return priv;
 
789
}
 
790
 
 
791
static int
 
792
remoteOpenSecondaryDriver(virConnectPtr conn,
 
793
                          virConnectAuthPtr auth,
 
794
                          unsigned int flags,
 
795
                          struct private_data **priv)
 
796
{
 
797
    int ret;
 
798
    int rflags = 0;
 
799
 
 
800
    if (!((*priv) = remoteAllocPrivateData()))
 
801
        return VIR_DRV_OPEN_ERROR;
 
802
 
 
803
    if (flags & VIR_CONNECT_RO)
 
804
        rflags |= VIR_DRV_OPEN_REMOTE_RO;
 
805
 
 
806
    ret = doRemoteOpen(conn, *priv, auth, rflags);
 
807
    if (ret != VIR_DRV_OPEN_SUCCESS) {
 
808
        remoteDriverUnlock(*priv);
 
809
        VIR_FREE(*priv);
 
810
    } else {
 
811
        (*priv)->localUses = 1;
 
812
        remoteDriverUnlock(*priv);
 
813
    }
 
814
 
 
815
    return ret;
 
816
}
 
817
 
 
818
static virDrvOpenStatus
 
819
remoteOpen (virConnectPtr conn,
 
820
            virConnectAuthPtr auth,
 
821
            unsigned int flags)
 
822
{
 
823
    struct private_data *priv;
 
824
    int ret, rflags = 0;
 
825
    const char *autostart = getenv("LIBVIRT_AUTOSTART");
 
826
 
 
827
    if (inside_daemon && (!conn->uri || (conn->uri && !conn->uri->server)))
 
828
        return VIR_DRV_OPEN_DECLINED;
 
829
 
 
830
    if (!(priv = remoteAllocPrivateData()))
 
831
        return VIR_DRV_OPEN_ERROR;
 
832
 
 
833
    if (flags & VIR_CONNECT_RO)
 
834
        rflags |= VIR_DRV_OPEN_REMOTE_RO;
 
835
 
 
836
    /*
 
837
     * If no servername is given, and no +XXX
 
838
     * transport is listed, or transport is unix,
 
839
     * and path is /session, and uid is unprivileged
 
840
     * then auto-spawn a daemon.
 
841
     */
 
842
    if (conn->uri &&
 
843
        !conn->uri->server &&
 
844
        conn->uri->path &&
 
845
        conn->uri->scheme &&
 
846
        ((strchr(conn->uri->scheme, '+') == 0)||
 
847
         (strstr(conn->uri->scheme, "+unix") != NULL)) &&
 
848
        (STREQ(conn->uri->path, "/session") ||
 
849
         STRPREFIX(conn->uri->scheme, "test+")) &&
 
850
        getuid() > 0) {
 
851
        VIR_DEBUG("Auto-spawn user daemon instance");
 
852
        rflags |= VIR_DRV_OPEN_REMOTE_USER;
 
853
        if (!autostart ||
 
854
            STRNEQ(autostart, "0"))
 
855
            rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
 
856
    }
 
857
 
 
858
    /*
 
859
     * If URI is NULL, then do a UNIX connection possibly auto-spawning
 
860
     * unprivileged server and probe remote server for URI. On Solaris,
 
861
     * this isn't supported, but we may be privileged enough to connect
 
862
     * to the UNIX socket anyway.
 
863
     */
 
864
    if (!conn->uri) {
 
865
        VIR_DEBUG("Auto-probe remote URI");
 
866
#ifndef __sun
 
867
        if (getuid() > 0) {
 
868
            VIR_DEBUG("Auto-spawn user daemon instance");
 
869
            rflags |= VIR_DRV_OPEN_REMOTE_USER;
 
870
            if (!autostart ||
 
871
                STRNEQ(autostart, "0"))
 
872
                rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
 
873
        }
 
874
#endif
 
875
    }
 
876
 
 
877
    ret = doRemoteOpen(conn, priv, auth, rflags);
 
878
    if (ret != VIR_DRV_OPEN_SUCCESS) {
 
879
        conn->privateData = NULL;
 
880
        remoteDriverUnlock(priv);
 
881
        VIR_FREE(priv);
 
882
    } else {
 
883
        conn->privateData = priv;
 
884
        remoteDriverUnlock(priv);
 
885
    }
 
886
    return ret;
 
887
}
 
888
 
 
889
 
 
890
/* In a string "driver+transport" return a pointer to "transport". */
 
891
static char *
 
892
get_transport_from_scheme (char *scheme)
 
893
{
 
894
    char *p = strchr (scheme, '+');
 
895
    return p ? p+1 : 0;
 
896
}
 
897
 
 
898
/*----------------------------------------------------------------------*/
 
899
 
 
900
 
 
901
static int
 
902
doRemoteClose (virConnectPtr conn, struct private_data *priv)
 
903
{
 
904
    int ret = 0;
 
905
 
 
906
    if (call (conn, priv, 0, REMOTE_PROC_CLOSE,
 
907
              (xdrproc_t) xdr_void, (char *) NULL,
 
908
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
909
        ret = -1;
 
910
 
 
911
    virNetTLSContextFree(priv->tls);
 
912
    priv->tls = NULL;
 
913
    virNetClientClose(priv->client);
 
914
    virNetClientFree(priv->client);
 
915
    priv->client = NULL;
 
916
    virNetClientProgramFree(priv->remoteProgram);
 
917
    virNetClientProgramFree(priv->qemuProgram);
 
918
    priv->remoteProgram = priv->qemuProgram = NULL;
 
919
 
 
920
    /* Free hostname copy */
 
921
    VIR_FREE(priv->hostname);
 
922
 
 
923
    /* See comment for remoteType. */
 
924
    VIR_FREE(priv->type);
 
925
 
 
926
    virDomainEventStateFree(priv->domainEventState);
 
927
    priv->domainEventState = NULL;
 
928
 
 
929
    return ret;
 
930
}
 
931
 
 
932
static int
 
933
remoteClose (virConnectPtr conn)
 
934
{
 
935
    int ret = 0;
 
936
    struct private_data *priv = conn->privateData;
 
937
 
 
938
    remoteDriverLock(priv);
 
939
    priv->localUses--;
 
940
    if (!priv->localUses) {
 
941
        ret = doRemoteClose(conn, priv);
 
942
        conn->privateData = NULL;
 
943
        remoteDriverUnlock(priv);
 
944
        virMutexDestroy(&priv->lock);
 
945
        VIR_FREE (priv);
 
946
    }
 
947
    if (priv)
 
948
        remoteDriverUnlock(priv);
 
949
 
 
950
    return ret;
 
951
}
 
952
 
 
953
 
 
954
/* Unfortunately this function is defined to return a static string.
 
955
 * Since the remote end always answers with the same type (for a
 
956
 * single connection anyway) we cache the type in the connection's
 
957
 * private data, and free it when we close the connection.
 
958
 *
 
959
 * See also:
 
960
 * http://www.redhat.com/archives/libvir-list/2007-February/msg00096.html
 
961
 */
 
962
static const char *
 
963
remoteType (virConnectPtr conn)
 
964
{
 
965
    char *rv = NULL;
 
966
    remote_get_type_ret ret;
 
967
    struct private_data *priv = conn->privateData;
 
968
 
 
969
    remoteDriverLock(priv);
 
970
 
 
971
    /* Cached? */
 
972
    if (priv->type) {
 
973
        rv = priv->type;
 
974
        goto done;
 
975
    }
 
976
 
 
977
    memset (&ret, 0, sizeof(ret));
 
978
    if (call (conn, priv, 0, REMOTE_PROC_GET_TYPE,
 
979
              (xdrproc_t) xdr_void, (char *) NULL,
 
980
              (xdrproc_t) xdr_remote_get_type_ret, (char *) &ret) == -1)
 
981
        goto done;
 
982
 
 
983
    /* Stash. */
 
984
    rv = priv->type = ret.type;
 
985
 
 
986
done:
 
987
    remoteDriverUnlock(priv);
 
988
    return rv;
 
989
}
 
990
 
 
991
static int remoteIsSecure(virConnectPtr conn)
 
992
{
 
993
    int rv = -1;
 
994
    struct private_data *priv = conn->privateData;
 
995
    remote_is_secure_ret ret;
 
996
    remoteDriverLock(priv);
 
997
 
 
998
    memset (&ret, 0, sizeof(ret));
 
999
    if (call (conn, priv, 0, REMOTE_PROC_IS_SECURE,
 
1000
              (xdrproc_t) xdr_void, (char *) NULL,
 
1001
              (xdrproc_t) xdr_remote_is_secure_ret, (char *) &ret) == -1)
 
1002
        goto done;
 
1003
 
 
1004
    /* We claim to be secure, if the remote driver
 
1005
     * transport itself is secure, and the remote
 
1006
     * HV connection is secure
 
1007
     *
 
1008
     * ie, we don't want to claim to be secure if the
 
1009
     * remote driver is used to connect to a XenD
 
1010
     * driver using unencrypted HTTP:/// access
 
1011
     */
 
1012
    rv = priv->is_secure && ret.secure ? 1 : 0;
 
1013
 
 
1014
done:
 
1015
    remoteDriverUnlock(priv);
 
1016
    return rv;
 
1017
}
 
1018
 
 
1019
static int remoteIsEncrypted(virConnectPtr conn)
 
1020
{
 
1021
    int rv = -1;
 
1022
    int encrypted = 0;
 
1023
    struct private_data *priv = conn->privateData;
 
1024
    remote_is_secure_ret ret;
 
1025
    remoteDriverLock(priv);
 
1026
 
 
1027
    memset (&ret, 0, sizeof(ret));
 
1028
    if (call (conn, priv, 0, REMOTE_PROC_IS_SECURE,
 
1029
              (xdrproc_t) xdr_void, (char *) NULL,
 
1030
              (xdrproc_t) xdr_remote_is_secure_ret, (char *) &ret) == -1)
 
1031
        goto done;
 
1032
 
 
1033
    if (virNetClientIsEncrypted(priv->client))
 
1034
        encrypted = 1;
 
1035
 
 
1036
    /* We claim to be encrypted, if the remote driver
 
1037
     * transport itself is encrypted, and the remote
 
1038
     * HV connection is secure.
 
1039
     *
 
1040
     * Yes, we really don't check the remote 'encrypted'
 
1041
     * option, since it will almost always be false,
 
1042
     * even if secure (eg UNIX sockets).
 
1043
     */
 
1044
    rv = encrypted && ret.secure ? 1 : 0;
 
1045
 
 
1046
done:
 
1047
    remoteDriverUnlock(priv);
 
1048
    return rv;
 
1049
}
 
1050
 
 
1051
static int
 
1052
remoteNodeGetCPUStats (virConnectPtr conn,
 
1053
                       int cpuNum,
 
1054
                       virNodeCPUStatsPtr params, int *nparams,
 
1055
                       unsigned int flags)
 
1056
{
 
1057
    int rv = -1;
 
1058
    remote_node_get_cpu_stats_args args;
 
1059
    remote_node_get_cpu_stats_ret ret;
 
1060
    int i = -1;
 
1061
    struct private_data *priv = conn->privateData;
 
1062
 
 
1063
    remoteDriverLock(priv);
 
1064
 
 
1065
    args.nparams = *nparams;
 
1066
    args.cpuNum = cpuNum;
 
1067
    args.flags = flags;
 
1068
 
 
1069
    memset (&ret, 0, sizeof(ret));
 
1070
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CPU_STATS,
 
1071
              (xdrproc_t) xdr_remote_node_get_cpu_stats_args,
 
1072
              (char *) &args,
 
1073
              (xdrproc_t) xdr_remote_node_get_cpu_stats_ret,
 
1074
              (char *) &ret) == -1)
 
1075
        goto done;
 
1076
 
 
1077
    /* Check the length of the returned list carefully. */
 
1078
    if (ret.params.params_len > REMOTE_NODE_CPU_STATS_MAX ||
 
1079
        ret.params.params_len > *nparams) {
 
1080
        remoteError(VIR_ERR_RPC, "%s",
 
1081
                    _("remoteNodeGetCPUStats: "
 
1082
                      "returned number of stats exceeds limit"));
 
1083
        goto cleanup;
 
1084
    }
 
1085
    /* Handle the case when the caller does not know the number of stats
 
1086
     * and is asking for the number of stats supported
 
1087
     */
 
1088
    if (*nparams == 0) {
 
1089
        *nparams = ret.nparams;
 
1090
        rv = 0;
 
1091
        goto cleanup;
 
1092
    }
 
1093
 
 
1094
    *nparams = ret.params.params_len;
 
1095
 
 
1096
    /* Deserialise the result. */
 
1097
    for (i = 0; i < *nparams; ++i) {
 
1098
        if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) {
 
1099
            remoteError(VIR_ERR_INTERNAL_ERROR,
 
1100
                        _("Stats %s too big for destination"),
 
1101
                        ret.params.params_val[i].field);
 
1102
            goto cleanup;
 
1103
        }
 
1104
        params[i].value = ret.params.params_val[i].value;
 
1105
    }
 
1106
 
 
1107
    rv = 0;
 
1108
 
 
1109
cleanup:
 
1110
    xdr_free ((xdrproc_t) xdr_remote_node_get_cpu_stats_ret,
 
1111
              (char *) &ret);
 
1112
done:
 
1113
    remoteDriverUnlock(priv);
 
1114
    return rv;
 
1115
}
 
1116
 
 
1117
static int
 
1118
remoteNodeGetMemoryStats (virConnectPtr conn,
 
1119
                          int cellNum,
 
1120
                          virNodeMemoryStatsPtr params, int *nparams,
 
1121
                          unsigned int flags)
 
1122
{
 
1123
    int rv = -1;
 
1124
    remote_node_get_memory_stats_args args;
 
1125
    remote_node_get_memory_stats_ret ret;
 
1126
    int i = -1;
 
1127
    struct private_data *priv = conn->privateData;
 
1128
 
 
1129
    remoteDriverLock(priv);
 
1130
 
 
1131
    args.nparams = *nparams;
 
1132
    args.cellNum = cellNum;
 
1133
    args.flags = flags;
 
1134
 
 
1135
    memset (&ret, 0, sizeof(ret));
 
1136
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_MEMORY_STATS,
 
1137
              (xdrproc_t) xdr_remote_node_get_memory_stats_args, (char *) &args,
 
1138
              (xdrproc_t) xdr_remote_node_get_memory_stats_ret, (char *) &ret) == -1)
 
1139
        goto done;
 
1140
 
 
1141
    /* Check the length of the returned list carefully. */
 
1142
    if (ret.params.params_len > REMOTE_NODE_MEMORY_STATS_MAX ||
 
1143
        ret.params.params_len > *nparams) {
 
1144
        remoteError(VIR_ERR_RPC, "%s",
 
1145
                    _("remoteNodeGetMemoryStats: "
 
1146
                      "returned number of stats exceeds limit"));
 
1147
        goto cleanup;
 
1148
    }
 
1149
    /* Handle the case when the caller does not know the number of stats
 
1150
     * and is asking for the number of stats supported
 
1151
     */
 
1152
    if (*nparams == 0) {
 
1153
        *nparams = ret.nparams;
 
1154
        rv = 0;
 
1155
        goto cleanup;
 
1156
    }
 
1157
 
 
1158
    *nparams = ret.params.params_len;
 
1159
 
 
1160
    /* Deserialise the result. */
 
1161
    for (i = 0; i < *nparams; ++i) {
 
1162
        if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) == NULL) {
 
1163
            remoteError(VIR_ERR_INTERNAL_ERROR,
 
1164
                        _("Stats %s too big for destination"),
 
1165
                        ret.params.params_val[i].field);
 
1166
            goto cleanup;
 
1167
        }
 
1168
        params[i].value = ret.params.params_val[i].value;
 
1169
    }
 
1170
 
 
1171
    rv = 0;
 
1172
 
 
1173
cleanup:
 
1174
    xdr_free ((xdrproc_t) xdr_remote_node_get_memory_stats_ret,
 
1175
              (char *) &ret);
 
1176
done:
 
1177
    remoteDriverUnlock(priv);
 
1178
    return rv;
 
1179
}
 
1180
 
 
1181
static int
 
1182
remoteNodeGetCellsFreeMemory(virConnectPtr conn,
 
1183
                            unsigned long long *freeMems,
 
1184
                            int startCell,
 
1185
                            int maxCells)
 
1186
{
 
1187
    int rv = -1;
 
1188
    remote_node_get_cells_free_memory_args args;
 
1189
    remote_node_get_cells_free_memory_ret ret;
 
1190
    int i;
 
1191
    struct private_data *priv = conn->privateData;
 
1192
 
 
1193
    remoteDriverLock(priv);
 
1194
 
 
1195
    if (maxCells > REMOTE_NODE_MAX_CELLS) {
 
1196
        remoteError(VIR_ERR_RPC,
 
1197
                    _("too many NUMA cells: %d > %d"),
 
1198
                    maxCells, REMOTE_NODE_MAX_CELLS);
 
1199
        goto done;
 
1200
    }
 
1201
 
 
1202
    args.startCell = startCell;
 
1203
    args.maxcells = maxCells;
 
1204
 
 
1205
    memset (&ret, 0, sizeof(ret));
 
1206
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY,
 
1207
              (xdrproc_t) xdr_remote_node_get_cells_free_memory_args, (char *)&args,
 
1208
              (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *)&ret) == -1)
 
1209
        goto done;
 
1210
 
 
1211
    for (i = 0 ; i < ret.cells.cells_len ; i++)
 
1212
        freeMems[i] = ret.cells.cells_val[i];
 
1213
 
 
1214
    xdr_free((xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *) &ret);
 
1215
 
 
1216
    rv = ret.cells.cells_len;
 
1217
 
 
1218
done:
 
1219
    remoteDriverUnlock(priv);
 
1220
    return rv;
 
1221
}
 
1222
 
 
1223
static int
 
1224
remoteListDomains (virConnectPtr conn, int *ids, int maxids)
 
1225
{
 
1226
    int rv = -1;
 
1227
    int i;
 
1228
    remote_list_domains_args args;
 
1229
    remote_list_domains_ret ret;
 
1230
    struct private_data *priv = conn->privateData;
 
1231
 
 
1232
    remoteDriverLock(priv);
 
1233
 
 
1234
    if (maxids > REMOTE_DOMAIN_ID_LIST_MAX) {
 
1235
        remoteError(VIR_ERR_RPC,
 
1236
                    _("too many remote domain IDs: %d > %d"),
 
1237
                    maxids, REMOTE_DOMAIN_ID_LIST_MAX);
 
1238
        goto done;
 
1239
    }
 
1240
    args.maxids = maxids;
 
1241
 
 
1242
    memset (&ret, 0, sizeof(ret));
 
1243
    if (call (conn, priv, 0, REMOTE_PROC_LIST_DOMAINS,
 
1244
              (xdrproc_t) xdr_remote_list_domains_args, (char *) &args,
 
1245
              (xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret) == -1)
 
1246
        goto done;
 
1247
 
 
1248
    if (ret.ids.ids_len > maxids) {
 
1249
        remoteError(VIR_ERR_RPC,
 
1250
                    _("too many remote domain IDs: %d > %d"),
 
1251
                    ret.ids.ids_len, maxids);
 
1252
        goto cleanup;
 
1253
    }
 
1254
 
 
1255
    for (i = 0; i < ret.ids.ids_len; ++i)
 
1256
        ids[i] = ret.ids.ids_val[i];
 
1257
 
 
1258
    rv = ret.ids.ids_len;
 
1259
 
 
1260
cleanup:
 
1261
    xdr_free ((xdrproc_t) xdr_remote_list_domains_ret, (char *) &ret);
 
1262
 
 
1263
done:
 
1264
    remoteDriverUnlock(priv);
 
1265
    return rv;
 
1266
}
 
1267
 
 
1268
static int
 
1269
remoteConnectListAllDomains(virConnectPtr conn,
 
1270
                            virDomainPtr **domains,
 
1271
                            unsigned int flags)
 
1272
{
 
1273
    int rv = -1;
 
1274
    int i;
 
1275
    virDomainPtr *doms = NULL;
 
1276
    remote_connect_list_all_domains_args args;
 
1277
    remote_connect_list_all_domains_ret ret;
 
1278
 
 
1279
    struct private_data *priv = conn->privateData;
 
1280
 
 
1281
    remoteDriverLock(priv);
 
1282
 
 
1283
    args.need_results = !!domains;
 
1284
    args.flags = flags;
 
1285
 
 
1286
    memset(&ret, 0, sizeof(ret));
 
1287
    if (call(conn,
 
1288
             priv,
 
1289
             0,
 
1290
             REMOTE_PROC_CONNECT_LIST_ALL_DOMAINS,
 
1291
             (xdrproc_t) xdr_remote_connect_list_all_domains_args,
 
1292
             (char *) &args,
 
1293
             (xdrproc_t) xdr_remote_connect_list_all_domains_ret,
 
1294
             (char *) &ret) == -1)
 
1295
        goto done;
 
1296
 
 
1297
    if (domains) {
 
1298
        if (VIR_ALLOC_N(doms, ret.domains.domains_len + 1) < 0) {
 
1299
            virReportOOMError();
 
1300
            goto cleanup;
 
1301
        }
 
1302
 
 
1303
        for (i = 0; i < ret.domains.domains_len; i++) {
 
1304
            doms[i] = get_nonnull_domain(conn, ret.domains.domains_val[i]);
 
1305
            if (!doms[i]) {
 
1306
                virReportOOMError();
 
1307
                goto cleanup;
 
1308
            }
 
1309
        }
 
1310
        *domains = doms;
 
1311
        doms = NULL;
 
1312
    }
 
1313
 
 
1314
    rv = ret.ret;
 
1315
 
 
1316
cleanup:
 
1317
    if (doms) {
 
1318
        for (i = 0; i < ret.domains.domains_len; i++)
 
1319
            if (doms[i])
 
1320
                virDomainFree(doms[i]);
 
1321
        VIR_FREE(doms);
 
1322
    }
 
1323
 
 
1324
    xdr_free((xdrproc_t) xdr_remote_connect_list_all_domains_ret, (char *) &ret);
 
1325
 
 
1326
done:
 
1327
    remoteDriverUnlock(priv);
 
1328
    return rv;
 
1329
}
 
1330
 
 
1331
/* Helper to free typed parameters. */
 
1332
static void
 
1333
remoteFreeTypedParameters(remote_typed_param *args_params_val,
 
1334
                          u_int args_params_len)
 
1335
{
 
1336
    u_int i;
 
1337
 
 
1338
    if (args_params_val == NULL)
 
1339
        return;
 
1340
 
 
1341
    for (i = 0; i < args_params_len; i++) {
 
1342
        VIR_FREE(args_params_val[i].field);
 
1343
        if (args_params_val[i].value.type == VIR_TYPED_PARAM_STRING)
 
1344
            VIR_FREE(args_params_val[i].value.remote_typed_param_value_u.s);
 
1345
    }
 
1346
 
 
1347
    VIR_FREE(args_params_val);
 
1348
}
 
1349
 
 
1350
/* Helper to serialize typed parameters. */
 
1351
static int
 
1352
remoteSerializeTypedParameters(virTypedParameterPtr params,
 
1353
                               int nparams,
 
1354
                               remote_typed_param **args_params_val,
 
1355
                               u_int *args_params_len)
 
1356
{
 
1357
    int i;
 
1358
    int rv = -1;
 
1359
    remote_typed_param *val;
 
1360
 
 
1361
    *args_params_len = nparams;
 
1362
    if (VIR_ALLOC_N(val, nparams) < 0) {
 
1363
        virReportOOMError();
 
1364
        goto cleanup;
 
1365
    }
 
1366
 
 
1367
    for (i = 0; i < nparams; ++i) {
 
1368
        /* call() will free this: */
 
1369
        val[i].field = strdup (params[i].field);
 
1370
        if (val[i].field == NULL) {
 
1371
            virReportOOMError();
 
1372
            goto cleanup;
 
1373
        }
 
1374
        val[i].value.type = params[i].type;
 
1375
        switch (params[i].type) {
 
1376
        case VIR_TYPED_PARAM_INT:
 
1377
            val[i].value.remote_typed_param_value_u.i = params[i].value.i;
 
1378
            break;
 
1379
        case VIR_TYPED_PARAM_UINT:
 
1380
            val[i].value.remote_typed_param_value_u.ui = params[i].value.ui;
 
1381
            break;
 
1382
        case VIR_TYPED_PARAM_LLONG:
 
1383
            val[i].value.remote_typed_param_value_u.l = params[i].value.l;
 
1384
            break;
 
1385
        case VIR_TYPED_PARAM_ULLONG:
 
1386
            val[i].value.remote_typed_param_value_u.ul = params[i].value.ul;
 
1387
            break;
 
1388
        case VIR_TYPED_PARAM_DOUBLE:
 
1389
            val[i].value.remote_typed_param_value_u.d = params[i].value.d;
 
1390
            break;
 
1391
        case VIR_TYPED_PARAM_BOOLEAN:
 
1392
            val[i].value.remote_typed_param_value_u.b = params[i].value.b;
 
1393
            break;
 
1394
        case VIR_TYPED_PARAM_STRING:
 
1395
            val[i].value.remote_typed_param_value_u.s = strdup(params[i].value.s);
 
1396
            if (val[i].value.remote_typed_param_value_u.s == NULL) {
 
1397
                virReportOOMError();
 
1398
                goto cleanup;
 
1399
            }
 
1400
            break;
 
1401
        default:
 
1402
            remoteError(VIR_ERR_RPC, _("unknown parameter type: %d"),
 
1403
                params[i].type);
 
1404
            goto cleanup;
 
1405
        }
 
1406
    }
 
1407
 
 
1408
    *args_params_val = val;
 
1409
    val = NULL;
 
1410
    rv = 0;
 
1411
 
 
1412
cleanup:
 
1413
    remoteFreeTypedParameters(val, nparams);
 
1414
    return rv;
 
1415
}
 
1416
 
 
1417
/* Helper to deserialize typed parameters. */
 
1418
static int
 
1419
remoteDeserializeTypedParameters(remote_typed_param *ret_params_val,
 
1420
                                 u_int ret_params_len,
 
1421
                                 int limit,
 
1422
                                 virTypedParameterPtr params,
 
1423
                                 int *nparams)
 
1424
{
 
1425
    int i = 0;
 
1426
    int rv = -1;
 
1427
 
 
1428
    /* Check the length of the returned list carefully. */
 
1429
    if (ret_params_len > limit || ret_params_len > *nparams) {
 
1430
        remoteError(VIR_ERR_RPC, "%s",
 
1431
                    _("returned number of parameters exceeds limit"));
 
1432
        goto cleanup;
 
1433
    }
 
1434
 
 
1435
    *nparams = ret_params_len;
 
1436
 
 
1437
    /* Deserialise the result. */
 
1438
    for (i = 0; i < ret_params_len; ++i) {
 
1439
        if (virStrcpyStatic(params[i].field,
 
1440
                            ret_params_val[i].field) == NULL) {
 
1441
            remoteError(VIR_ERR_INTERNAL_ERROR,
 
1442
                        _("Parameter %s too big for destination"),
 
1443
                        ret_params_val[i].field);
 
1444
            goto cleanup;
 
1445
        }
 
1446
        params[i].type = ret_params_val[i].value.type;
 
1447
        switch (params[i].type) {
 
1448
        case VIR_TYPED_PARAM_INT:
 
1449
            params[i].value.i =
 
1450
                ret_params_val[i].value.remote_typed_param_value_u.i;
 
1451
            break;
 
1452
        case VIR_TYPED_PARAM_UINT:
 
1453
            params[i].value.ui =
 
1454
                ret_params_val[i].value.remote_typed_param_value_u.ui;
 
1455
            break;
 
1456
        case VIR_TYPED_PARAM_LLONG:
 
1457
            params[i].value.l =
 
1458
                ret_params_val[i].value.remote_typed_param_value_u.l;
 
1459
            break;
 
1460
        case VIR_TYPED_PARAM_ULLONG:
 
1461
            params[i].value.ul =
 
1462
                ret_params_val[i].value.remote_typed_param_value_u.ul;
 
1463
            break;
 
1464
        case VIR_TYPED_PARAM_DOUBLE:
 
1465
            params[i].value.d =
 
1466
                ret_params_val[i].value.remote_typed_param_value_u.d;
 
1467
            break;
 
1468
        case VIR_TYPED_PARAM_BOOLEAN:
 
1469
            params[i].value.b =
 
1470
                ret_params_val[i].value.remote_typed_param_value_u.b;
 
1471
            break;
 
1472
        case VIR_TYPED_PARAM_STRING:
 
1473
            params[i].value.s =
 
1474
                strdup(ret_params_val[i].value.remote_typed_param_value_u.s);
 
1475
            if (params[i].value.s == NULL) {
 
1476
                virReportOOMError();
 
1477
                goto cleanup;
 
1478
            }
 
1479
            break;
 
1480
        default:
 
1481
            remoteError(VIR_ERR_RPC, _("unknown parameter type: %d"),
 
1482
                        params[i].type);
 
1483
            goto cleanup;
 
1484
        }
 
1485
    }
 
1486
 
 
1487
    rv = 0;
 
1488
 
 
1489
cleanup:
 
1490
    if (rv < 0)
 
1491
        virTypedParameterArrayClear(params, i);
 
1492
    return rv;
 
1493
}
 
1494
 
 
1495
static int
 
1496
remoteDeserializeDomainDiskErrors(remote_domain_disk_error *ret_errors_val,
 
1497
                                  u_int ret_errors_len,
 
1498
                                  int limit,
 
1499
                                  virDomainDiskErrorPtr errors,
 
1500
                                  int maxerrors)
 
1501
{
 
1502
    int i = 0;
 
1503
    int j;
 
1504
 
 
1505
    if (ret_errors_len > limit || ret_errors_len > maxerrors) {
 
1506
        remoteError(VIR_ERR_RPC, "%s",
 
1507
                    _("returned number of disk errors exceeds limit"));
 
1508
        goto error;
 
1509
    }
 
1510
 
 
1511
    for (i = 0; i < ret_errors_len; i++) {
 
1512
        if (!(errors[i].disk = strdup(ret_errors_val[i].disk))) {
 
1513
            virReportOOMError();
 
1514
            goto error;
 
1515
        }
 
1516
        errors[i].error = ret_errors_val[i].error;
 
1517
    }
 
1518
 
 
1519
    return 0;
 
1520
 
 
1521
error:
 
1522
    for (j = 0; j < i; j++)
 
1523
        VIR_FREE(errors[i].disk);
 
1524
 
 
1525
    return -1;
 
1526
}
 
1527
 
 
1528
static int
 
1529
remoteDomainBlockStatsFlags(virDomainPtr domain,
 
1530
                            const char *path,
 
1531
                            virTypedParameterPtr params,
 
1532
                            int *nparams,
 
1533
                            unsigned int flags)
 
1534
{
 
1535
    int rv = -1;
 
1536
    remote_domain_block_stats_flags_args args;
 
1537
    remote_domain_block_stats_flags_ret ret;
 
1538
    struct private_data *priv = domain->conn->privateData;
 
1539
 
 
1540
    remoteDriverLock(priv);
 
1541
 
 
1542
    make_nonnull_domain (&args.dom, domain);
 
1543
    args.nparams = *nparams;
 
1544
    args.path = (char *) path;
 
1545
    args.flags = flags;
 
1546
 
 
1547
    memset (&ret, 0, sizeof(ret));
 
1548
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS,
 
1549
              (xdrproc_t) xdr_remote_domain_block_stats_flags_args, (char *) &args,
 
1550
              (xdrproc_t) xdr_remote_domain_block_stats_flags_ret, (char *) &ret) == -1)
 
1551
        goto done;
 
1552
 
 
1553
    /* Check the length of the returned list carefully. */
 
1554
    if (ret.params.params_len > REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX ||
 
1555
        ret.params.params_len > *nparams) {
 
1556
        remoteError(VIR_ERR_RPC, "%s",
 
1557
                    _("remoteDomainBlockStatsFlags: "
 
1558
                      "returned number of stats exceeds limit"));
 
1559
        goto cleanup;
 
1560
    }
 
1561
 
 
1562
    /* Handle the case when the caller does not know the number of stats
 
1563
     * and is asking for the number of stats supported
 
1564
     */
 
1565
    if (*nparams == 0) {
 
1566
        *nparams = ret.nparams;
 
1567
        rv = 0;
 
1568
        goto cleanup;
 
1569
    }
 
1570
 
 
1571
    *nparams = ret.params.params_len;
 
1572
 
 
1573
    /* Deserialise the result. */
 
1574
    if (remoteDeserializeTypedParameters(ret.params.params_val,
 
1575
                                         ret.params.params_len,
 
1576
                                         REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
 
1577
                                         params,
 
1578
                                         nparams) < 0)
 
1579
        goto cleanup;
 
1580
 
 
1581
    rv = 0;
 
1582
 
 
1583
cleanup:
 
1584
    xdr_free ((xdrproc_t) xdr_remote_domain_block_stats_flags_ret,
 
1585
              (char *) &ret);
 
1586
done:
 
1587
    remoteDriverUnlock(priv);
 
1588
    return rv;
 
1589
}
 
1590
 
 
1591
static int
 
1592
remoteDomainGetMemoryParameters (virDomainPtr domain,
 
1593
                                 virTypedParameterPtr params, int *nparams,
 
1594
                                 unsigned int flags)
 
1595
{
 
1596
    int rv = -1;
 
1597
    remote_domain_get_memory_parameters_args args;
 
1598
    remote_domain_get_memory_parameters_ret ret;
 
1599
    struct private_data *priv = domain->conn->privateData;
 
1600
 
 
1601
    remoteDriverLock(priv);
 
1602
 
 
1603
    make_nonnull_domain (&args.dom, domain);
 
1604
    args.nparams = *nparams;
 
1605
    args.flags = flags;
 
1606
 
 
1607
    memset (&ret, 0, sizeof(ret));
 
1608
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS,
 
1609
              (xdrproc_t) xdr_remote_domain_get_memory_parameters_args, (char *) &args,
 
1610
              (xdrproc_t) xdr_remote_domain_get_memory_parameters_ret, (char *) &ret) == -1)
 
1611
        goto done;
 
1612
 
 
1613
    /* Handle the case when the caller does not know the number of parameters
 
1614
     * and is asking for the number of parameters supported
 
1615
     */
 
1616
    if (*nparams == 0) {
 
1617
        *nparams = ret.nparams;
 
1618
        rv = 0;
 
1619
        goto cleanup;
 
1620
    }
 
1621
 
 
1622
    if (remoteDeserializeTypedParameters(ret.params.params_val,
 
1623
                                         ret.params.params_len,
 
1624
                                         REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
 
1625
                                         params,
 
1626
                                         nparams) < 0)
 
1627
        goto cleanup;
 
1628
 
 
1629
    rv = 0;
 
1630
 
 
1631
cleanup:
 
1632
    xdr_free ((xdrproc_t) xdr_remote_domain_get_memory_parameters_ret,
 
1633
              (char *) &ret);
 
1634
done:
 
1635
    remoteDriverUnlock(priv);
 
1636
    return rv;
 
1637
}
 
1638
 
 
1639
static int
 
1640
remoteDomainGetNumaParameters (virDomainPtr domain,
 
1641
                               virTypedParameterPtr params, int *nparams,
 
1642
                               unsigned int flags)
 
1643
{
 
1644
    int rv = -1;
 
1645
    remote_domain_get_numa_parameters_args args;
 
1646
    remote_domain_get_numa_parameters_ret ret;
 
1647
    struct private_data *priv = domain->conn->privateData;
 
1648
 
 
1649
    remoteDriverLock(priv);
 
1650
 
 
1651
    make_nonnull_domain (&args.dom, domain);
 
1652
    args.nparams = *nparams;
 
1653
    args.flags = flags;
 
1654
 
 
1655
    memset (&ret, 0, sizeof(ret));
 
1656
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS,
 
1657
              (xdrproc_t) xdr_remote_domain_get_numa_parameters_args, (char *) &args,
 
1658
              (xdrproc_t) xdr_remote_domain_get_numa_parameters_ret, (char *) &ret) == -1)
 
1659
        goto done;
 
1660
 
 
1661
    /* Handle the case when the caller does not know the number of parameters
 
1662
     * and is asking for the number of parameters supported
 
1663
     */
 
1664
    if (*nparams == 0) {
 
1665
        *nparams = ret.nparams;
 
1666
        rv = 0;
 
1667
        goto cleanup;
 
1668
    }
 
1669
 
 
1670
    if (remoteDeserializeTypedParameters(ret.params.params_val,
 
1671
                                         ret.params.params_len,
 
1672
                                         REMOTE_DOMAIN_NUMA_PARAMETERS_MAX,
 
1673
                                         params,
 
1674
                                         nparams) < 0)
 
1675
        goto cleanup;
 
1676
 
 
1677
    rv = 0;
 
1678
 
 
1679
cleanup:
 
1680
    xdr_free ((xdrproc_t) xdr_remote_domain_get_numa_parameters_ret,
 
1681
              (char *) &ret);
 
1682
done:
 
1683
    remoteDriverUnlock(priv);
 
1684
    return rv;
 
1685
}
 
1686
 
 
1687
static int
 
1688
remoteDomainGetBlkioParameters (virDomainPtr domain,
 
1689
                                virTypedParameterPtr params, int *nparams,
 
1690
                                unsigned int flags)
 
1691
{
 
1692
    int rv = -1;
 
1693
    remote_domain_get_blkio_parameters_args args;
 
1694
    remote_domain_get_blkio_parameters_ret ret;
 
1695
    struct private_data *priv = domain->conn->privateData;
 
1696
 
 
1697
    remoteDriverLock(priv);
 
1698
 
 
1699
    make_nonnull_domain (&args.dom, domain);
 
1700
    args.nparams = *nparams;
 
1701
    args.flags = flags;
 
1702
 
 
1703
    memset (&ret, 0, sizeof(ret));
 
1704
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS,
 
1705
              (xdrproc_t) xdr_remote_domain_get_blkio_parameters_args, (char *) &args,
 
1706
              (xdrproc_t) xdr_remote_domain_get_blkio_parameters_ret, (char *) &ret) == -1)
 
1707
        goto done;
 
1708
 
 
1709
    /* Handle the case when the caller does not know the number of parameters
 
1710
     * and is asking for the number of parameters supported
 
1711
     */
 
1712
    if (*nparams == 0) {
 
1713
        *nparams = ret.nparams;
 
1714
        rv = 0;
 
1715
        goto cleanup;
 
1716
    }
 
1717
 
 
1718
    if (remoteDeserializeTypedParameters(ret.params.params_val,
 
1719
                                         ret.params.params_len,
 
1720
                                         REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX,
 
1721
                                         params,
 
1722
                                         nparams) < 0)
 
1723
        goto cleanup;
 
1724
 
 
1725
    rv = 0;
 
1726
 
 
1727
cleanup:
 
1728
    xdr_free ((xdrproc_t) xdr_remote_domain_get_blkio_parameters_ret,
 
1729
              (char *) &ret);
 
1730
done:
 
1731
    remoteDriverUnlock(priv);
 
1732
    return rv;
 
1733
}
 
1734
 
 
1735
static int
 
1736
remoteDomainGetVcpuPinInfo (virDomainPtr domain,
 
1737
                            int ncpumaps,
 
1738
                            unsigned char *cpumaps,
 
1739
                            int maplen,
 
1740
                            unsigned int flags)
 
1741
{
 
1742
    int rv = -1;
 
1743
    int i;
 
1744
    remote_domain_get_vcpu_pin_info_args args;
 
1745
    remote_domain_get_vcpu_pin_info_ret ret;
 
1746
    struct private_data *priv = domain->conn->privateData;
 
1747
 
 
1748
    remoteDriverLock(priv);
 
1749
 
 
1750
    if (ncpumaps > REMOTE_VCPUINFO_MAX) {
 
1751
        remoteError(VIR_ERR_RPC,
 
1752
                    _("vCPU count exceeds maximum: %d > %d"),
 
1753
                    ncpumaps, REMOTE_VCPUINFO_MAX);
 
1754
        goto done;
 
1755
    }
 
1756
 
 
1757
    if (INT_MULTIPLY_OVERFLOW(ncpumaps, maplen) ||
 
1758
        ncpumaps * maplen > REMOTE_CPUMAPS_MAX) {
 
1759
        remoteError(VIR_ERR_RPC,
 
1760
                    _("vCPU map buffer length exceeds maximum: %d > %d"),
 
1761
                    ncpumaps * maplen, REMOTE_CPUMAPS_MAX);
 
1762
        goto done;
 
1763
    }
 
1764
 
 
1765
    make_nonnull_domain (&args.dom, domain);
 
1766
    args.ncpumaps = ncpumaps;
 
1767
    args.maplen = maplen;
 
1768
    args.flags = flags;
 
1769
 
 
1770
    memset (&ret, 0, sizeof(ret));
 
1771
 
 
1772
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO,
 
1773
              (xdrproc_t) xdr_remote_domain_get_vcpu_pin_info_args,
 
1774
              (char *) &args,
 
1775
              (xdrproc_t) xdr_remote_domain_get_vcpu_pin_info_ret,
 
1776
              (char *) &ret) == -1)
 
1777
        goto done;
 
1778
 
 
1779
    if (ret.num > ncpumaps) {
 
1780
        remoteError(VIR_ERR_RPC,
 
1781
                    _("host reports too many vCPUs: %d > %d"),
 
1782
                    ret.num, ncpumaps);
 
1783
        goto cleanup;
 
1784
    }
 
1785
 
 
1786
    if (ret.cpumaps.cpumaps_len > ncpumaps * maplen) {
 
1787
        remoteError(VIR_ERR_RPC,
 
1788
                    _("host reports map buffer length exceeds maximum: %d > %d"),
 
1789
                    ret.cpumaps.cpumaps_len, ncpumaps * maplen);
 
1790
        goto cleanup;
 
1791
    }
 
1792
 
 
1793
    memset (cpumaps, 0, ncpumaps * maplen);
 
1794
 
 
1795
    for (i = 0; i < ret.cpumaps.cpumaps_len; ++i)
 
1796
        cpumaps[i] = ret.cpumaps.cpumaps_val[i];
 
1797
 
 
1798
    rv = ret.num;
 
1799
 
 
1800
cleanup:
 
1801
    xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpu_pin_info_ret, (char *) &ret);
 
1802
 
 
1803
done:
 
1804
    remoteDriverUnlock(priv);
 
1805
    return rv;
 
1806
}
 
1807
 
 
1808
static int
 
1809
remoteDomainGetVcpus (virDomainPtr domain,
 
1810
                      virVcpuInfoPtr info,
 
1811
                      int maxinfo,
 
1812
                      unsigned char *cpumaps,
 
1813
                      int maplen)
 
1814
{
 
1815
    int rv = -1;
 
1816
    int i;
 
1817
    remote_domain_get_vcpus_args args;
 
1818
    remote_domain_get_vcpus_ret ret;
 
1819
    struct private_data *priv = domain->conn->privateData;
 
1820
 
 
1821
    remoteDriverLock(priv);
 
1822
 
 
1823
    if (maxinfo > REMOTE_VCPUINFO_MAX) {
 
1824
        remoteError(VIR_ERR_RPC,
 
1825
                    _("vCPU count exceeds maximum: %d > %d"),
 
1826
                    maxinfo, REMOTE_VCPUINFO_MAX);
 
1827
        goto done;
 
1828
    }
 
1829
    if (INT_MULTIPLY_OVERFLOW(maxinfo, maplen) ||
 
1830
        maxinfo * maplen > REMOTE_CPUMAPS_MAX) {
 
1831
        remoteError(VIR_ERR_RPC,
 
1832
                    _("vCPU map buffer length exceeds maximum: %d > %d"),
 
1833
                    maxinfo * maplen, REMOTE_CPUMAPS_MAX);
 
1834
        goto done;
 
1835
    }
 
1836
 
 
1837
    make_nonnull_domain (&args.dom, domain);
 
1838
    args.maxinfo = maxinfo;
 
1839
    args.maplen = maplen;
 
1840
 
 
1841
    memset (&ret, 0, sizeof(ret));
 
1842
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS,
 
1843
              (xdrproc_t) xdr_remote_domain_get_vcpus_args, (char *) &args,
 
1844
              (xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret) == -1)
 
1845
        goto done;
 
1846
 
 
1847
    if (ret.info.info_len > maxinfo) {
 
1848
        remoteError(VIR_ERR_RPC,
 
1849
                    _("host reports too many vCPUs: %d > %d"),
 
1850
                    ret.info.info_len, maxinfo);
 
1851
        goto cleanup;
 
1852
    }
 
1853
    if (ret.cpumaps.cpumaps_len > maxinfo * maplen) {
 
1854
        remoteError(VIR_ERR_RPC,
 
1855
                    _("host reports map buffer length exceeds maximum: %d > %d"),
 
1856
                    ret.cpumaps.cpumaps_len, maxinfo * maplen);
 
1857
        goto cleanup;
 
1858
    }
 
1859
 
 
1860
    memset (info, 0, sizeof(virVcpuInfo) * maxinfo);
 
1861
    memset (cpumaps, 0, maxinfo * maplen);
 
1862
 
 
1863
    for (i = 0; i < ret.info.info_len; ++i) {
 
1864
        info[i].number = ret.info.info_val[i].number;
 
1865
        info[i].state = ret.info.info_val[i].state;
 
1866
        info[i].cpuTime = ret.info.info_val[i].cpu_time;
 
1867
        info[i].cpu = ret.info.info_val[i].cpu;
 
1868
    }
 
1869
 
 
1870
    for (i = 0; i < ret.cpumaps.cpumaps_len; ++i)
 
1871
        cpumaps[i] = ret.cpumaps.cpumaps_val[i];
 
1872
 
 
1873
    rv = ret.info.info_len;
 
1874
 
 
1875
cleanup:
 
1876
    xdr_free ((xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret);
 
1877
 
 
1878
done:
 
1879
    remoteDriverUnlock(priv);
 
1880
    return rv;
 
1881
}
 
1882
 
 
1883
static int
 
1884
remoteDomainGetSecurityLabel (virDomainPtr domain, virSecurityLabelPtr seclabel)
 
1885
{
 
1886
    remote_domain_get_security_label_args args;
 
1887
    remote_domain_get_security_label_ret ret;
 
1888
    struct private_data *priv = domain->conn->privateData;
 
1889
    int rv = -1;
 
1890
 
 
1891
    remoteDriverLock(priv);
 
1892
 
 
1893
    make_nonnull_domain (&args.dom, domain);
 
1894
    memset (&ret, 0, sizeof(ret));
 
1895
    memset (seclabel, 0, sizeof(*seclabel));
 
1896
 
 
1897
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL,
 
1898
              (xdrproc_t) xdr_remote_domain_get_security_label_args, (char *)&args,
 
1899
              (xdrproc_t) xdr_remote_domain_get_security_label_ret, (char *)&ret) == -1) {
 
1900
        goto done;
 
1901
    }
 
1902
 
 
1903
    if (ret.label.label_val != NULL) {
 
1904
        if (strlen (ret.label.label_val) >= sizeof(seclabel->label)) {
 
1905
            remoteError(VIR_ERR_RPC, _("security label exceeds maximum: %zu"),
 
1906
                        sizeof(seclabel->label) - 1);
 
1907
            goto cleanup;
 
1908
        }
 
1909
        strcpy (seclabel->label, ret.label.label_val);
 
1910
        seclabel->enforcing = ret.enforcing;
 
1911
    }
 
1912
 
 
1913
    rv = 0;
 
1914
 
 
1915
cleanup:
 
1916
    xdr_free((xdrproc_t) xdr_remote_domain_get_security_label_ret, (char *)&ret);
 
1917
 
 
1918
done:
 
1919
    remoteDriverUnlock(priv);
 
1920
    return rv;
 
1921
}
 
1922
 
 
1923
static int
 
1924
remoteDomainGetState(virDomainPtr domain,
 
1925
                     int *state,
 
1926
                     int *reason,
 
1927
                     unsigned int flags)
 
1928
{
 
1929
    int rv = -1;
 
1930
    remote_domain_get_state_args args;
 
1931
    remote_domain_get_state_ret ret;
 
1932
    struct private_data *priv = domain->conn->privateData;
 
1933
 
 
1934
    remoteDriverLock(priv);
 
1935
 
 
1936
    make_nonnull_domain(&args.dom, domain);
 
1937
    args.flags = flags;
 
1938
 
 
1939
    memset(&ret, 0, sizeof(ret));
 
1940
    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_STATE,
 
1941
             (xdrproc_t) xdr_remote_domain_get_state_args, (char *) &args,
 
1942
             (xdrproc_t) xdr_remote_domain_get_state_ret, (char *) &ret) == -1)
 
1943
        goto done;
 
1944
 
 
1945
    *state = ret.state;
 
1946
    if (reason)
 
1947
        *reason = ret.reason;
 
1948
 
 
1949
    rv = 0;
 
1950
 
 
1951
done:
 
1952
    remoteDriverUnlock(priv);
 
1953
    return rv;
 
1954
}
 
1955
 
 
1956
static int
 
1957
remoteNodeGetSecurityModel (virConnectPtr conn, virSecurityModelPtr secmodel)
 
1958
{
 
1959
    remote_node_get_security_model_ret ret;
 
1960
    struct private_data *priv = conn->privateData;
 
1961
    int rv = -1;
 
1962
 
 
1963
    remoteDriverLock(priv);
 
1964
 
 
1965
    memset (&ret, 0, sizeof(ret));
 
1966
    memset (secmodel, 0, sizeof(*secmodel));
 
1967
 
 
1968
    if (call (conn, priv, 0, REMOTE_PROC_NODE_GET_SECURITY_MODEL,
 
1969
              (xdrproc_t) xdr_void, NULL,
 
1970
              (xdrproc_t) xdr_remote_node_get_security_model_ret, (char *)&ret) == -1) {
 
1971
        goto done;
 
1972
    }
 
1973
 
 
1974
    if (ret.model.model_val != NULL) {
 
1975
        if (strlen (ret.model.model_val) >= sizeof(secmodel->model)) {
 
1976
            remoteError(VIR_ERR_RPC, _("security model exceeds maximum: %zu"),
 
1977
                        sizeof(secmodel->model) - 1);
 
1978
            goto cleanup;
 
1979
        }
 
1980
        strcpy (secmodel->model, ret.model.model_val);
 
1981
    }
 
1982
 
 
1983
    if (ret.doi.doi_val != NULL) {
 
1984
        if (strlen (ret.doi.doi_val) >= sizeof(secmodel->doi)) {
 
1985
            remoteError(VIR_ERR_RPC, _("security doi exceeds maximum: %zu"),
 
1986
                        sizeof(secmodel->doi) - 1);
 
1987
            goto cleanup;
 
1988
        }
 
1989
        strcpy (secmodel->doi, ret.doi.doi_val);
 
1990
    }
 
1991
 
 
1992
    rv = 0;
 
1993
 
 
1994
cleanup:
 
1995
    xdr_free((xdrproc_t) xdr_remote_node_get_security_model_ret, (char *)&ret);
 
1996
 
 
1997
done:
 
1998
    remoteDriverUnlock(priv);
 
1999
    return rv;
 
2000
}
 
2001
 
 
2002
static int
 
2003
remoteDomainMigratePrepare (virConnectPtr dconn,
 
2004
                            char **cookie, int *cookielen,
 
2005
                            const char *uri_in, char **uri_out,
 
2006
                            unsigned long flags, const char *dname,
 
2007
                            unsigned long resource)
 
2008
{
 
2009
    int rv = -1;
 
2010
    remote_domain_migrate_prepare_args args;
 
2011
    remote_domain_migrate_prepare_ret ret;
 
2012
    struct private_data *priv = dconn->privateData;
 
2013
 
 
2014
    remoteDriverLock(priv);
 
2015
 
 
2016
    args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
 
2017
    args.flags = flags;
 
2018
    args.dname = dname == NULL ? NULL : (char **) &dname;
 
2019
    args.resource = resource;
 
2020
 
 
2021
    memset (&ret, 0, sizeof(ret));
 
2022
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE,
 
2023
              (xdrproc_t) xdr_remote_domain_migrate_prepare_args, (char *) &args,
 
2024
              (xdrproc_t) xdr_remote_domain_migrate_prepare_ret, (char *) &ret) == -1)
 
2025
        goto done;
 
2026
 
 
2027
    if (ret.cookie.cookie_len > 0) {
 
2028
        *cookie = ret.cookie.cookie_val; /* Caller frees. */
 
2029
        *cookielen = ret.cookie.cookie_len;
 
2030
    }
 
2031
    if (ret.uri_out)
 
2032
        *uri_out = *ret.uri_out; /* Caller frees. */
 
2033
 
 
2034
    VIR_FREE(ret.uri_out);
 
2035
    rv = 0;
 
2036
 
 
2037
done:
 
2038
    remoteDriverUnlock(priv);
 
2039
    return rv;
 
2040
}
 
2041
 
 
2042
static int
 
2043
remoteDomainMigratePrepare2 (virConnectPtr dconn,
 
2044
                             char **cookie, int *cookielen,
 
2045
                             const char *uri_in, char **uri_out,
 
2046
                             unsigned long flags, const char *dname,
 
2047
                             unsigned long resource,
 
2048
                             const char *dom_xml)
 
2049
{
 
2050
    int rv = -1;
 
2051
    remote_domain_migrate_prepare2_args args;
 
2052
    remote_domain_migrate_prepare2_ret ret;
 
2053
    struct private_data *priv = dconn->privateData;
 
2054
 
 
2055
    remoteDriverLock(priv);
 
2056
 
 
2057
    args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
 
2058
    args.flags = flags;
 
2059
    args.dname = dname == NULL ? NULL : (char **) &dname;
 
2060
    args.resource = resource;
 
2061
    args.dom_xml = (char *) dom_xml;
 
2062
 
 
2063
    memset (&ret, 0, sizeof(ret));
 
2064
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2,
 
2065
              (xdrproc_t) xdr_remote_domain_migrate_prepare2_args, (char *) &args,
 
2066
              (xdrproc_t) xdr_remote_domain_migrate_prepare2_ret, (char *) &ret) == -1)
 
2067
        goto done;
 
2068
 
 
2069
    if (ret.cookie.cookie_len > 0) {
 
2070
        if (!cookie || !cookielen) {
 
2071
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
2072
                        _("caller ignores cookie or cookielen"));
 
2073
            goto error;
 
2074
        }
 
2075
        *cookie = ret.cookie.cookie_val; /* Caller frees. */
 
2076
        *cookielen = ret.cookie.cookie_len;
 
2077
    }
 
2078
    if (ret.uri_out) {
 
2079
        if (!uri_out) {
 
2080
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
2081
                        _("caller ignores uri_out"));
 
2082
            goto error;
 
2083
        }
 
2084
        *uri_out = *ret.uri_out; /* Caller frees. */
 
2085
    }
 
2086
 
 
2087
    rv = 0;
 
2088
 
 
2089
done:
 
2090
    VIR_FREE(ret.uri_out);
 
2091
    remoteDriverUnlock(priv);
 
2092
    return rv;
 
2093
error:
 
2094
    if (ret.cookie.cookie_len)
 
2095
        VIR_FREE(ret.cookie.cookie_val);
 
2096
    if (ret.uri_out)
 
2097
        VIR_FREE(*ret.uri_out);
 
2098
    goto done;
 
2099
}
 
2100
 
 
2101
static int
 
2102
remoteDomainCreate (virDomainPtr domain)
 
2103
{
 
2104
    int rv = -1;
 
2105
    remote_domain_create_args args;
 
2106
    remote_domain_lookup_by_uuid_args args2;
 
2107
    remote_domain_lookup_by_uuid_ret ret2;
 
2108
    struct private_data *priv = domain->conn->privateData;
 
2109
 
 
2110
    remoteDriverLock(priv);
 
2111
 
 
2112
    make_nonnull_domain (&args.dom, domain);
 
2113
 
 
2114
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE,
 
2115
              (xdrproc_t) xdr_remote_domain_create_args, (char *) &args,
 
2116
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
2117
        goto done;
 
2118
 
 
2119
    /* Need to do a lookup figure out ID of newly started guest, because
 
2120
     * bug in design of REMOTE_PROC_DOMAIN_CREATE means we aren't getting
 
2121
     * it returned.
 
2122
     */
 
2123
    memcpy (args2.uuid, domain->uuid, VIR_UUID_BUFLEN);
 
2124
    memset (&ret2, 0, sizeof(ret2));
 
2125
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID,
 
2126
              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, (char *) &args2,
 
2127
              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2) == -1)
 
2128
        goto done;
 
2129
 
 
2130
    domain->id = ret2.dom.id;
 
2131
    xdr_free ((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2);
 
2132
 
 
2133
    rv = 0;
 
2134
 
 
2135
done:
 
2136
    remoteDriverUnlock(priv);
 
2137
    return rv;
 
2138
}
 
2139
 
 
2140
static char *
 
2141
remoteDomainGetSchedulerType (virDomainPtr domain, int *nparams)
 
2142
{
 
2143
    char *rv = NULL;
 
2144
    remote_domain_get_scheduler_type_args args;
 
2145
    remote_domain_get_scheduler_type_ret ret;
 
2146
    struct private_data *priv = domain->conn->privateData;
 
2147
 
 
2148
    remoteDriverLock(priv);
 
2149
 
 
2150
    make_nonnull_domain (&args.dom, domain);
 
2151
 
 
2152
    memset (&ret, 0, sizeof(ret));
 
2153
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE,
 
2154
              (xdrproc_t) xdr_remote_domain_get_scheduler_type_args, (char *) &args,
 
2155
              (xdrproc_t) xdr_remote_domain_get_scheduler_type_ret, (char *) &ret) == -1)
 
2156
        goto done;
 
2157
 
 
2158
    if (nparams) *nparams = ret.nparams;
 
2159
 
 
2160
    /* Caller frees this. */
 
2161
    rv = ret.type;
 
2162
 
 
2163
done:
 
2164
    remoteDriverUnlock(priv);
 
2165
    return rv;
 
2166
}
 
2167
 
 
2168
static int
 
2169
remoteDomainMemoryStats (virDomainPtr domain,
 
2170
                         struct _virDomainMemoryStat *stats,
 
2171
                         unsigned int nr_stats,
 
2172
                         unsigned int flags)
 
2173
{
 
2174
    int rv = -1;
 
2175
    remote_domain_memory_stats_args args;
 
2176
    remote_domain_memory_stats_ret ret;
 
2177
    struct private_data *priv = domain->conn->privateData;
 
2178
    unsigned int i;
 
2179
 
 
2180
    remoteDriverLock(priv);
 
2181
 
 
2182
    make_nonnull_domain (&args.dom, domain);
 
2183
    if (nr_stats > REMOTE_DOMAIN_MEMORY_STATS_MAX) {
 
2184
        remoteError(VIR_ERR_RPC,
 
2185
                    _("too many memory stats requested: %d > %d"), nr_stats,
 
2186
                    REMOTE_DOMAIN_MEMORY_STATS_MAX);
 
2187
        goto done;
 
2188
    }
 
2189
    args.maxStats = nr_stats;
 
2190
    args.flags = flags;
 
2191
    memset (&ret, 0, sizeof(ret));
 
2192
 
 
2193
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MEMORY_STATS,
 
2194
              (xdrproc_t) xdr_remote_domain_memory_stats_args,
 
2195
                (char *) &args,
 
2196
              (xdrproc_t) xdr_remote_domain_memory_stats_ret,
 
2197
                (char *) &ret) == -1)
 
2198
        goto done;
 
2199
 
 
2200
    for (i = 0; i < ret.stats.stats_len; i++) {
 
2201
        stats[i].tag = ret.stats.stats_val[i].tag;
 
2202
        stats[i].val = ret.stats.stats_val[i].val;
 
2203
    }
 
2204
    rv = ret.stats.stats_len;
 
2205
    xdr_free((xdrproc_t) xdr_remote_domain_memory_stats_ret, (char *) &ret);
 
2206
 
 
2207
done:
 
2208
    remoteDriverUnlock(priv);
 
2209
    return rv;
 
2210
}
 
2211
 
 
2212
static int
 
2213
remoteDomainBlockPeek (virDomainPtr domain,
 
2214
                       const char *path,
 
2215
                       unsigned long long offset,
 
2216
                       size_t size,
 
2217
                       void *buffer,
 
2218
                       unsigned int flags)
 
2219
{
 
2220
    int rv = -1;
 
2221
    remote_domain_block_peek_args args;
 
2222
    remote_domain_block_peek_ret ret;
 
2223
    struct private_data *priv = domain->conn->privateData;
 
2224
 
 
2225
    remoteDriverLock(priv);
 
2226
 
 
2227
    if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
 
2228
        remoteError(VIR_ERR_RPC,
 
2229
                    _("block peek request too large for remote protocol, %zi > %d"),
 
2230
                    size, REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX);
 
2231
        goto done;
 
2232
    }
 
2233
 
 
2234
    make_nonnull_domain (&args.dom, domain);
 
2235
    args.path = (char *) path;
 
2236
    args.offset = offset;
 
2237
    args.size = size;
 
2238
    args.flags = flags;
 
2239
 
 
2240
    memset (&ret, 0, sizeof(ret));
 
2241
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_PEEK,
 
2242
              (xdrproc_t) xdr_remote_domain_block_peek_args,
 
2243
                (char *) &args,
 
2244
              (xdrproc_t) xdr_remote_domain_block_peek_ret,
 
2245
                (char *) &ret) == -1)
 
2246
        goto done;
 
2247
 
 
2248
    if (ret.buffer.buffer_len != size) {
 
2249
        remoteError(VIR_ERR_RPC, "%s",
 
2250
                    _("returned buffer is not same size as requested"));
 
2251
        goto cleanup;
 
2252
    }
 
2253
 
 
2254
    memcpy (buffer, ret.buffer.buffer_val, size);
 
2255
    rv = 0;
 
2256
 
 
2257
cleanup:
 
2258
    VIR_FREE(ret.buffer.buffer_val);
 
2259
 
 
2260
done:
 
2261
    remoteDriverUnlock(priv);
 
2262
    return rv;
 
2263
}
 
2264
 
 
2265
static int
 
2266
remoteDomainMemoryPeek (virDomainPtr domain,
 
2267
                        unsigned long long offset,
 
2268
                        size_t size,
 
2269
                        void *buffer,
 
2270
                        unsigned int flags)
 
2271
{
 
2272
    int rv = -1;
 
2273
    remote_domain_memory_peek_args args;
 
2274
    remote_domain_memory_peek_ret ret;
 
2275
    struct private_data *priv = domain->conn->privateData;
 
2276
 
 
2277
    remoteDriverLock(priv);
 
2278
 
 
2279
    if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
 
2280
        remoteError(VIR_ERR_RPC,
 
2281
                    _("memory peek request too large for remote protocol, %zi > %d"),
 
2282
                    size, REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX);
 
2283
        goto done;
 
2284
    }
 
2285
 
 
2286
    make_nonnull_domain (&args.dom, domain);
 
2287
    args.offset = offset;
 
2288
    args.size = size;
 
2289
    args.flags = flags;
 
2290
 
 
2291
    memset (&ret, 0, sizeof(ret));
 
2292
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MEMORY_PEEK,
 
2293
              (xdrproc_t) xdr_remote_domain_memory_peek_args,
 
2294
                (char *) &args,
 
2295
              (xdrproc_t) xdr_remote_domain_memory_peek_ret,
 
2296
                (char *) &ret) == -1)
 
2297
        goto done;
 
2298
 
 
2299
    if (ret.buffer.buffer_len != size) {
 
2300
        remoteError(VIR_ERR_RPC, "%s",
 
2301
                    _("returned buffer is not same size as requested"));
 
2302
        goto cleanup;
 
2303
    }
 
2304
 
 
2305
    memcpy (buffer, ret.buffer.buffer_val, size);
 
2306
    rv = 0;
 
2307
 
 
2308
cleanup:
 
2309
    VIR_FREE(ret.buffer.buffer_val);
 
2310
 
 
2311
done:
 
2312
    remoteDriverUnlock(priv);
 
2313
    return rv;
 
2314
}
 
2315
 
 
2316
static int remoteDomainGetBlockJobInfo(virDomainPtr domain,
 
2317
                                       const char *path,
 
2318
                                       virDomainBlockJobInfoPtr info,
 
2319
                                       unsigned int flags)
 
2320
{
 
2321
    int rv = -1;
 
2322
    remote_domain_get_block_job_info_args args;
 
2323
    remote_domain_get_block_job_info_ret ret;
 
2324
    struct private_data *priv = domain->conn->privateData;
 
2325
 
 
2326
    remoteDriverLock(priv);
 
2327
 
 
2328
    make_nonnull_domain(&args.dom, domain);
 
2329
    args.path = (char *)path;
 
2330
    args.flags = flags;
 
2331
 
 
2332
    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_JOB_INFO,
 
2333
             (xdrproc_t)xdr_remote_domain_get_block_job_info_args,
 
2334
               (char *)&args,
 
2335
             (xdrproc_t)xdr_remote_domain_get_block_job_info_ret,
 
2336
               (char *)&ret) == -1)
 
2337
        goto done;
 
2338
 
 
2339
    if (ret.found) {
 
2340
        info->type = ret.type;
 
2341
        info->bandwidth = ret.bandwidth;
 
2342
        info->cur = ret.cur;
 
2343
        info->end = ret.end;
 
2344
        rv = 1;
 
2345
    } else {
 
2346
        rv = 0;
 
2347
    }
 
2348
 
 
2349
done:
 
2350
    remoteDriverUnlock(priv);
 
2351
    return rv;
 
2352
}
 
2353
 
 
2354
static int remoteDomainGetBlockIoTune(virDomainPtr domain,
 
2355
                                      const char *disk,
 
2356
                                      virTypedParameterPtr params,
 
2357
                                      int *nparams,
 
2358
                                      unsigned int flags)
 
2359
{
 
2360
    int rv = -1;
 
2361
    remote_domain_get_block_io_tune_args args;
 
2362
    remote_domain_get_block_io_tune_ret ret;
 
2363
    struct private_data *priv = domain->conn->privateData;
 
2364
 
 
2365
    remoteDriverLock(priv);
 
2366
 
 
2367
    make_nonnull_domain(&args.dom, domain);
 
2368
    args.disk = disk ? (char **)&disk : NULL;
 
2369
    args.nparams = *nparams;
 
2370
    args.flags = flags;
 
2371
 
 
2372
    memset(&ret, 0, sizeof(ret));
 
2373
 
 
2374
 
 
2375
    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_IO_TUNE,
 
2376
             (xdrproc_t) xdr_remote_domain_get_block_io_tune_args,
 
2377
               (char *) &args,
 
2378
             (xdrproc_t) xdr_remote_domain_get_block_io_tune_ret,
 
2379
               (char *) &ret) == -1) {
 
2380
        goto done;
 
2381
    }
 
2382
 
 
2383
    /* Handle the case when the caller does not know the number of parameters
 
2384
     * and is asking for the number of parameters supported
 
2385
     */
 
2386
    if (*nparams == 0) {
 
2387
        *nparams = ret.nparams;
 
2388
        rv = 0;
 
2389
        goto cleanup;
 
2390
    }
 
2391
 
 
2392
    if (remoteDeserializeTypedParameters(ret.params.params_val,
 
2393
                                         ret.params.params_len,
 
2394
                                         REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
 
2395
                                         params,
 
2396
                                         nparams) < 0)
 
2397
        goto cleanup;
 
2398
 
 
2399
    rv = 0;
 
2400
 
 
2401
cleanup:
 
2402
    xdr_free ((xdrproc_t) xdr_remote_domain_get_block_io_tune_ret,
 
2403
              (char *) &ret);
 
2404
done:
 
2405
    remoteDriverUnlock(priv);
 
2406
    return rv;
 
2407
}
 
2408
 
 
2409
static int remoteDomainGetCPUStats(virDomainPtr domain,
 
2410
                                   virTypedParameterPtr params,
 
2411
                                   unsigned int nparams,
 
2412
                                   int start_cpu,
 
2413
                                   unsigned int ncpus,
 
2414
                                   unsigned int flags)
 
2415
{
 
2416
    struct private_data *priv = domain->conn->privateData;
 
2417
    remote_domain_get_cpu_stats_args args;
 
2418
    remote_domain_get_cpu_stats_ret ret;
 
2419
    int rv = -1;
 
2420
    int cpu;
 
2421
 
 
2422
    remoteDriverLock(priv);
 
2423
 
 
2424
    if (nparams > REMOTE_NODE_CPU_STATS_MAX) {
 
2425
        remoteError(VIR_ERR_RPC,
 
2426
                    _("nparams count exceeds maximum: %u > %u"),
 
2427
                    nparams, REMOTE_NODE_CPU_STATS_MAX);
 
2428
        goto done;
 
2429
    }
 
2430
    if (ncpus > REMOTE_DOMAIN_GET_CPU_STATS_NCPUS_MAX) {
 
2431
        remoteError(VIR_ERR_RPC,
 
2432
                    _("ncpus count exceeds maximum: %u > %u"),
 
2433
                    ncpus, REMOTE_DOMAIN_GET_CPU_STATS_NCPUS_MAX);
 
2434
        goto done;
 
2435
    }
 
2436
 
 
2437
    make_nonnull_domain(&args.dom, domain);
 
2438
    args.nparams = nparams;
 
2439
    args.start_cpu = start_cpu;
 
2440
    args.ncpus = ncpus;
 
2441
    args.flags = flags;
 
2442
 
 
2443
    memset(&ret, 0, sizeof(ret));
 
2444
 
 
2445
    if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_CPU_STATS,
 
2446
             (xdrproc_t) xdr_remote_domain_get_cpu_stats_args,
 
2447
             (char *) &args,
 
2448
             (xdrproc_t) xdr_remote_domain_get_cpu_stats_ret,
 
2449
             (char *) &ret) == -1)
 
2450
        goto done;
 
2451
 
 
2452
    /* Check the length of the returned list carefully. */
 
2453
    if (ret.params.params_len > nparams * ncpus ||
 
2454
        (ret.params.params_len &&
 
2455
         ((ret.params.params_len % ret.nparams) || ret.nparams > nparams))) {
 
2456
        remoteError(VIR_ERR_RPC, "%s",
 
2457
                    _("remoteDomainGetCPUStats: "
 
2458
                      "returned number of stats exceeds limit"));
 
2459
        memset(params, 0, sizeof(*params) * nparams * ncpus);
 
2460
        goto cleanup;
 
2461
    }
 
2462
 
 
2463
    /* Handle the case when the caller does not know the number of stats
 
2464
     * and is asking for the number of stats supported
 
2465
     */
 
2466
    if (nparams == 0) {
 
2467
        rv = ret.nparams;
 
2468
        goto cleanup;
 
2469
    }
 
2470
 
 
2471
    /* The remote side did not send back any zero entries, so we have
 
2472
     * to expand things back into a possibly sparse array, where the
 
2473
     * tail of the array may be omitted.
 
2474
     */
 
2475
    memset(params, 0, sizeof(*params) * nparams * ncpus);
 
2476
    ncpus = ret.params.params_len / ret.nparams;
 
2477
    for (cpu = 0; cpu < ncpus; cpu++) {
 
2478
        int tmp = nparams;
 
2479
        remote_typed_param *stride = &ret.params.params_val[cpu * ret.nparams];
 
2480
 
 
2481
        if (remoteDeserializeTypedParameters(stride, ret.nparams,
 
2482
                                             REMOTE_NODE_CPU_STATS_MAX,
 
2483
                                             &params[cpu * nparams],
 
2484
                                             &tmp) < 0)
 
2485
            goto cleanup;
 
2486
    }
 
2487
 
 
2488
    rv = ret.nparams;
 
2489
cleanup:
 
2490
    if (rv < 0)
 
2491
        virTypedParameterArrayClear(params, nparams * ncpus);
 
2492
 
 
2493
    xdr_free ((xdrproc_t) xdr_remote_domain_get_cpu_stats_ret,
 
2494
              (char *) &ret);
 
2495
done:
 
2496
    remoteDriverUnlock(priv);
 
2497
    return rv;
 
2498
}
 
2499
 
 
2500
 
 
2501
/*----------------------------------------------------------------------*/
 
2502
 
 
2503
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 
2504
remoteGenericOpen(virConnectPtr conn, virConnectAuthPtr auth,
 
2505
                  unsigned int flags, void **genericPrivateData)
 
2506
{
 
2507
    if (inside_daemon)
 
2508
        return VIR_DRV_OPEN_DECLINED;
 
2509
 
 
2510
    if (conn->driver &&
 
2511
        STREQ (conn->driver->name, "remote")) {
 
2512
        struct private_data *priv;
 
2513
 
 
2514
        /* If we're here, the remote driver is already
 
2515
         * in use due to a) a QEMU uri, or b) a remote
 
2516
         * URI. So we can re-use existing connection */
 
2517
        priv = conn->privateData;
 
2518
        remoteDriverLock(priv);
 
2519
        priv->localUses++;
 
2520
        *genericPrivateData = priv;
 
2521
        remoteDriverUnlock(priv);
 
2522
        return VIR_DRV_OPEN_SUCCESS;
 
2523
    } else if (conn->networkDriver &&
 
2524
               STREQ (conn->networkDriver->name, "remote")) {
 
2525
        struct private_data *priv = conn->networkPrivateData;
 
2526
        remoteDriverLock(priv);
 
2527
        *genericPrivateData = priv;
 
2528
        priv->localUses++;
 
2529
        remoteDriverUnlock(priv);
 
2530
        return VIR_DRV_OPEN_SUCCESS;
 
2531
    } else {
 
2532
        /* Using a non-remote driver, so we need to open a
 
2533
         * new connection for network APIs, forcing it to
 
2534
         * use the UNIX transport. This handles Xen driver
 
2535
         * which doesn't have its own impl of the network APIs. */
 
2536
        struct private_data *priv;
 
2537
        int ret = remoteOpenSecondaryDriver(conn, auth, flags, &priv);
 
2538
        *genericPrivateData = priv;
 
2539
        return ret;
 
2540
    }
 
2541
}
 
2542
 
 
2543
static int
 
2544
remoteGenericClose(virConnectPtr conn, void **genericPrivateData)
 
2545
{
 
2546
    int rv = 0;
 
2547
    struct private_data *priv = *genericPrivateData;
 
2548
 
 
2549
    remoteDriverLock(priv);
 
2550
    priv->localUses--;
 
2551
    if (!priv->localUses) {
 
2552
        rv = doRemoteClose(conn, priv);
 
2553
        *genericPrivateData = NULL;
 
2554
        remoteDriverUnlock(priv);
 
2555
        virMutexDestroy(&priv->lock);
 
2556
        VIR_FREE(priv);
 
2557
    }
 
2558
    if (priv)
 
2559
        remoteDriverUnlock(priv);
 
2560
    return rv;
 
2561
}
 
2562
 
 
2563
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 
2564
remoteNetworkOpen(virConnectPtr conn, virConnectAuthPtr auth,
 
2565
                  unsigned int flags)
 
2566
{
 
2567
    return remoteGenericOpen(conn, auth, flags, &conn->networkPrivateData);
 
2568
}
 
2569
 
 
2570
static int
 
2571
remoteNetworkClose(virConnectPtr conn)
 
2572
{
 
2573
    return remoteGenericClose(conn, &conn->networkPrivateData);
 
2574
}
 
2575
 
 
2576
/*----------------------------------------------------------------------*/
 
2577
 
 
2578
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 
2579
remoteInterfaceOpen(virConnectPtr conn, virConnectAuthPtr auth,
 
2580
                    unsigned int flags)
 
2581
{
 
2582
    return remoteGenericOpen(conn, auth, flags, &conn->interfacePrivateData);
 
2583
}
 
2584
 
 
2585
static int
 
2586
remoteInterfaceClose(virConnectPtr conn)
 
2587
{
 
2588
    return remoteGenericClose(conn, &conn->interfacePrivateData);
 
2589
}
 
2590
 
 
2591
/*----------------------------------------------------------------------*/
 
2592
 
 
2593
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 
2594
remoteStorageOpen(virConnectPtr conn, virConnectAuthPtr auth,
 
2595
                  unsigned int flags)
 
2596
{
 
2597
    return remoteGenericOpen(conn, auth, flags, &conn->storagePrivateData);
 
2598
}
 
2599
 
 
2600
static int
 
2601
remoteStorageClose(virConnectPtr conn)
 
2602
{
 
2603
    return remoteGenericClose(conn, &conn->storagePrivateData);
 
2604
}
 
2605
 
 
2606
static char *
 
2607
remoteFindStoragePoolSources (virConnectPtr conn,
 
2608
                              const char *type,
 
2609
                              const char *srcSpec,
 
2610
                              unsigned int flags)
 
2611
{
 
2612
    char *rv = NULL;
 
2613
    remote_find_storage_pool_sources_args args;
 
2614
    remote_find_storage_pool_sources_ret ret;
 
2615
    struct private_data *priv = conn->storagePrivateData;
 
2616
    const char *emptyString = "";
 
2617
 
 
2618
    remoteDriverLock(priv);
 
2619
 
 
2620
    args.type = (char*)type;
 
2621
    /*
 
2622
     * I'd think the following would work here:
 
2623
     *    args.srcSpec = (char**)&srcSpec;
 
2624
     * since srcSpec is a remote_string (not a remote_nonnull_string).
 
2625
     *
 
2626
     * But when srcSpec is NULL, this yields:
 
2627
     *    libvir: Remote error : marshaling args
 
2628
     *
 
2629
     * So for now I'm working around this by turning NULL srcSpecs
 
2630
     * into empty strings.
 
2631
     */
 
2632
    args.srcSpec = srcSpec ? (char **)&srcSpec : (char **)&emptyString;
 
2633
    args.flags = flags;
 
2634
 
 
2635
    memset (&ret, 0, sizeof(ret));
 
2636
    if (call (conn, priv, 0, REMOTE_PROC_FIND_STORAGE_POOL_SOURCES,
 
2637
              (xdrproc_t) xdr_remote_find_storage_pool_sources_args, (char *) &args,
 
2638
              (xdrproc_t) xdr_remote_find_storage_pool_sources_ret, (char *) &ret) == -1)
 
2639
        goto done;
 
2640
 
 
2641
    rv = ret.xml;
 
2642
    ret.xml = NULL; /* To stop xdr_free free'ing it */
 
2643
 
 
2644
    xdr_free ((xdrproc_t) xdr_remote_find_storage_pool_sources_ret, (char *) &ret);
 
2645
 
 
2646
done:
 
2647
    remoteDriverUnlock(priv);
 
2648
    return rv;
 
2649
}
 
2650
 
 
2651
/*----------------------------------------------------------------------*/
 
2652
 
 
2653
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 
2654
remoteDevMonOpen(virConnectPtr conn, virConnectAuthPtr auth,
 
2655
                 unsigned int flags)
 
2656
{
 
2657
    return remoteGenericOpen(conn, auth, flags, &conn->devMonPrivateData);
 
2658
}
 
2659
 
 
2660
static int
 
2661
remoteDevMonClose(virConnectPtr conn)
 
2662
{
 
2663
    return remoteGenericClose(conn, &conn->devMonPrivateData);
 
2664
}
 
2665
 
 
2666
static int
 
2667
remoteNodeDeviceDettach (virNodeDevicePtr dev)
 
2668
{
 
2669
    int rv = -1;
 
2670
    remote_node_device_dettach_args args;
 
2671
    /* This method is unusual in that it uses the HV driver, not the devMon driver
 
2672
     * hence its use of privateData, instead of devMonPrivateData */
 
2673
    struct private_data *priv = dev->conn->privateData;
 
2674
 
 
2675
    remoteDriverLock(priv);
 
2676
 
 
2677
    args.name = dev->name;
 
2678
 
 
2679
    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DETTACH,
 
2680
              (xdrproc_t) xdr_remote_node_device_dettach_args, (char *) &args,
 
2681
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
2682
        goto done;
 
2683
 
 
2684
    rv = 0;
 
2685
 
 
2686
done:
 
2687
    remoteDriverUnlock(priv);
 
2688
    return rv;
 
2689
}
 
2690
 
 
2691
static int
 
2692
remoteNodeDeviceReAttach (virNodeDevicePtr dev)
 
2693
{
 
2694
    int rv = -1;
 
2695
    remote_node_device_re_attach_args args;
 
2696
    /* This method is unusual in that it uses the HV driver, not the devMon driver
 
2697
     * hence its use of privateData, instead of devMonPrivateData */
 
2698
    struct private_data *priv = dev->conn->privateData;
 
2699
 
 
2700
    remoteDriverLock(priv);
 
2701
 
 
2702
    args.name = dev->name;
 
2703
 
 
2704
    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_RE_ATTACH,
 
2705
              (xdrproc_t) xdr_remote_node_device_re_attach_args, (char *) &args,
 
2706
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
2707
        goto done;
 
2708
 
 
2709
    rv = 0;
 
2710
 
 
2711
done:
 
2712
    remoteDriverUnlock(priv);
 
2713
    return rv;
 
2714
}
 
2715
 
 
2716
static int
 
2717
remoteNodeDeviceReset (virNodeDevicePtr dev)
 
2718
{
 
2719
    int rv = -1;
 
2720
    remote_node_device_reset_args args;
 
2721
    /* This method is unusual in that it uses the HV driver, not the devMon driver
 
2722
     * hence its use of privateData, instead of devMonPrivateData */
 
2723
    struct private_data *priv = dev->conn->privateData;
 
2724
 
 
2725
    remoteDriverLock(priv);
 
2726
 
 
2727
    args.name = dev->name;
 
2728
 
 
2729
    if (call (dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_RESET,
 
2730
              (xdrproc_t) xdr_remote_node_device_reset_args, (char *) &args,
 
2731
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
2732
        goto done;
 
2733
 
 
2734
    rv = 0;
 
2735
 
 
2736
done:
 
2737
    remoteDriverUnlock(priv);
 
2738
    return rv;
 
2739
}
 
2740
 
 
2741
/* ------------------------------------------------------------- */
 
2742
 
 
2743
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 
2744
remoteNWFilterOpen(virConnectPtr conn, virConnectAuthPtr auth,
 
2745
                   unsigned int flags)
 
2746
{
 
2747
    return remoteGenericOpen(conn, auth, flags, &conn->nwfilterPrivateData);
 
2748
}
 
2749
 
 
2750
static int
 
2751
remoteNWFilterClose(virConnectPtr conn)
 
2752
{
 
2753
    return remoteGenericClose(conn, &conn->nwfilterPrivateData);
 
2754
}
 
2755
 
 
2756
/*----------------------------------------------------------------------*/
 
2757
 
 
2758
static int
 
2759
remoteAuthenticate (virConnectPtr conn, struct private_data *priv,
 
2760
                    virConnectAuthPtr auth ATTRIBUTE_UNUSED,
 
2761
                    const char *authtype)
 
2762
{
 
2763
    struct remote_auth_list_ret ret;
 
2764
    int err, type = REMOTE_AUTH_NONE;
 
2765
 
 
2766
    memset(&ret, 0, sizeof(ret));
 
2767
    err = call (conn, priv, 0,
 
2768
                REMOTE_PROC_AUTH_LIST,
 
2769
                (xdrproc_t) xdr_void, (char *) NULL,
 
2770
                (xdrproc_t) xdr_remote_auth_list_ret, (char *) &ret);
 
2771
    if (err < 0) {
 
2772
        virErrorPtr verr = virGetLastError();
 
2773
        if (verr && verr->code == VIR_ERR_NO_SUPPORT) {
 
2774
            /* Missing RPC - old server - ignore */
 
2775
            virResetLastError();
 
2776
            return 0;
 
2777
        }
 
2778
        return -1;
 
2779
    }
 
2780
 
 
2781
    if (ret.types.types_len == 0)
 
2782
        return 0;
 
2783
 
 
2784
    if (authtype) {
 
2785
        int want, i;
 
2786
        if (STRCASEEQ(authtype, "sasl") ||
 
2787
            STRCASEEQLEN(authtype, "sasl.", 5)) {
 
2788
            want = REMOTE_AUTH_SASL;
 
2789
        } else if (STRCASEEQ(authtype, "polkit")) {
 
2790
            want = REMOTE_AUTH_POLKIT;
 
2791
        } else {
 
2792
            remoteError(VIR_ERR_AUTH_FAILED,
 
2793
                        _("unknown authentication type %s"), authtype);
 
2794
            return -1;
 
2795
        }
 
2796
        for (i = 0 ; i < ret.types.types_len ; i++) {
 
2797
            if (ret.types.types_val[i] == want)
 
2798
                type = want;
 
2799
        }
 
2800
        if (type == REMOTE_AUTH_NONE) {
 
2801
            remoteError(VIR_ERR_AUTH_FAILED,
 
2802
                        _("requested authentication type %s rejected"),
 
2803
                        authtype);
 
2804
            return -1;
 
2805
        }
 
2806
    } else {
 
2807
        type = ret.types.types_val[0];
 
2808
    }
 
2809
 
 
2810
    switch (type) {
 
2811
#if HAVE_SASL
 
2812
    case REMOTE_AUTH_SASL: {
 
2813
        const char *mech = NULL;
 
2814
        if (authtype &&
 
2815
            STRCASEEQLEN(authtype, "sasl.", 5))
 
2816
            mech = authtype + 5;
 
2817
 
 
2818
        if (remoteAuthSASL(conn, priv, auth, mech) < 0) {
 
2819
            VIR_FREE(ret.types.types_val);
 
2820
            return -1;
 
2821
        }
 
2822
        break;
 
2823
    }
 
2824
#endif
 
2825
 
 
2826
#if HAVE_POLKIT
 
2827
    case REMOTE_AUTH_POLKIT:
 
2828
        if (remoteAuthPolkit(conn, priv, auth) < 0) {
 
2829
            VIR_FREE(ret.types.types_val);
 
2830
            return -1;
 
2831
        }
 
2832
        break;
 
2833
#endif
 
2834
 
 
2835
    case REMOTE_AUTH_NONE:
 
2836
        /* Nothing todo, hurrah ! */
 
2837
        break;
 
2838
 
 
2839
    default:
 
2840
        remoteError(VIR_ERR_AUTH_FAILED,
 
2841
                    _("unsupported authentication type %d"),
 
2842
                    ret.types.types_val[0]);
 
2843
        VIR_FREE(ret.types.types_val);
 
2844
        return -1;
 
2845
    }
 
2846
 
 
2847
    VIR_FREE(ret.types.types_val);
 
2848
 
 
2849
    return 0;
 
2850
}
 
2851
 
 
2852
 
 
2853
 
 
2854
#if HAVE_SASL
 
2855
static int remoteAuthCredVir2SASL(int vircred)
 
2856
{
 
2857
    switch (vircred) {
 
2858
    case VIR_CRED_USERNAME:
 
2859
        return SASL_CB_USER;
 
2860
 
 
2861
    case VIR_CRED_AUTHNAME:
 
2862
        return SASL_CB_AUTHNAME;
 
2863
 
 
2864
    case VIR_CRED_LANGUAGE:
 
2865
        return SASL_CB_LANGUAGE;
 
2866
 
 
2867
    case VIR_CRED_CNONCE:
 
2868
        return SASL_CB_CNONCE;
 
2869
 
 
2870
    case VIR_CRED_PASSPHRASE:
 
2871
        return SASL_CB_PASS;
 
2872
 
 
2873
    case VIR_CRED_ECHOPROMPT:
 
2874
        return SASL_CB_ECHOPROMPT;
 
2875
 
 
2876
    case VIR_CRED_NOECHOPROMPT:
 
2877
        return SASL_CB_NOECHOPROMPT;
 
2878
 
 
2879
    case VIR_CRED_REALM:
 
2880
        return SASL_CB_GETREALM;
 
2881
    }
 
2882
 
 
2883
    return 0;
 
2884
}
 
2885
 
 
2886
static int remoteAuthCredSASL2Vir(int vircred)
 
2887
{
 
2888
    switch (vircred) {
 
2889
    case SASL_CB_USER:
 
2890
        return VIR_CRED_USERNAME;
 
2891
 
 
2892
    case SASL_CB_AUTHNAME:
 
2893
        return VIR_CRED_AUTHNAME;
 
2894
 
 
2895
    case SASL_CB_LANGUAGE:
 
2896
        return VIR_CRED_LANGUAGE;
 
2897
 
 
2898
    case SASL_CB_CNONCE:
 
2899
        return VIR_CRED_CNONCE;
 
2900
 
 
2901
    case SASL_CB_PASS:
 
2902
        return VIR_CRED_PASSPHRASE;
 
2903
 
 
2904
    case SASL_CB_ECHOPROMPT:
 
2905
        return VIR_CRED_ECHOPROMPT;
 
2906
 
 
2907
    case SASL_CB_NOECHOPROMPT:
 
2908
        return VIR_CRED_NOECHOPROMPT;
 
2909
 
 
2910
    case SASL_CB_GETREALM:
 
2911
        return VIR_CRED_REALM;
 
2912
    }
 
2913
 
 
2914
    return 0;
 
2915
}
 
2916
 
 
2917
/*
 
2918
 * @param credtype array of credential types client supports
 
2919
 * @param ncredtype size of credtype array
 
2920
 * @return the SASL callback structure, or NULL on error
 
2921
 *
 
2922
 * Build up the SASL callback structure. We register one callback for
 
2923
 * each credential type that the libvirt client indicated they support.
 
2924
 * We explicitly leav the callback function pointer at NULL though,
 
2925
 * because we don't actually want to get SASL callbacks triggered.
 
2926
 * Instead, we want the start/step functions to return SASL_INTERACT.
 
2927
 * This lets us give the libvirt client a list of all required
 
2928
 * credentials in one go, rather than triggering the callback one
 
2929
 * credential at a time,
 
2930
 */
 
2931
static sasl_callback_t *remoteAuthMakeCallbacks(int *credtype, int ncredtype)
 
2932
{
 
2933
    sasl_callback_t *cbs;
 
2934
    int i, n;
 
2935
    if (VIR_ALLOC_N(cbs, ncredtype+1) < 0) {
 
2936
        return NULL;
 
2937
    }
 
2938
 
 
2939
    for (i = 0, n = 0 ; i < ncredtype ; i++) {
 
2940
        int id = remoteAuthCredVir2SASL(credtype[i]);
 
2941
        if (id != 0)
 
2942
            cbs[n++].id = id;
 
2943
        /* Don't fill proc or context fields of sasl_callback_t
 
2944
         * because we want to use interactions instead */
 
2945
    }
 
2946
    cbs[n].id = 0;
 
2947
    return cbs;
 
2948
}
 
2949
 
 
2950
 
 
2951
/*
 
2952
 * @param interact SASL interactions required
 
2953
 * @param cred populated with libvirt credential metadata
 
2954
 * @return the size of the cred array returned
 
2955
 *
 
2956
 * Builds up an array of libvirt credential structs, populating
 
2957
 * with data from the SASL interaction struct. These two structs
 
2958
 * are basically a 1-to-1 copy of each other.
 
2959
 */
 
2960
static int remoteAuthMakeCredentials(sasl_interact_t *interact,
 
2961
                                     virConnectCredentialPtr *cred,
 
2962
                                     size_t *ncred)
 
2963
{
 
2964
    int ninteract;
 
2965
    if (!cred)
 
2966
        return -1;
 
2967
 
 
2968
    for (ninteract = 0, *ncred = 0 ; interact[ninteract].id != 0 ; ninteract++) {
 
2969
        if (interact[ninteract].result)
 
2970
            continue;
 
2971
        (*ncred)++;
 
2972
    }
 
2973
 
 
2974
    if (VIR_ALLOC_N(*cred, *ncred) < 0)
 
2975
        return -1;
 
2976
 
 
2977
    for (ninteract = 0, *ncred = 0 ; interact[ninteract].id != 0 ; ninteract++) {
 
2978
        if (interact[ninteract].result)
 
2979
            continue;
 
2980
 
 
2981
        (*cred)[*ncred].type = remoteAuthCredSASL2Vir(interact[ninteract].id);
 
2982
        if (!(*cred)[*ncred].type) {
 
2983
            *ncred = 0;
 
2984
            VIR_FREE(*cred);
 
2985
            return -1;
 
2986
        }
 
2987
        if (interact[*ncred].challenge)
 
2988
            (*cred)[*ncred].challenge = interact[ninteract].challenge;
 
2989
        (*cred)[*ncred].prompt = interact[ninteract].prompt;
 
2990
        if (interact[*ncred].defresult)
 
2991
            (*cred)[*ncred].defresult = interact[ninteract].defresult;
 
2992
        (*cred)[*ncred].result = NULL;
 
2993
 
 
2994
        (*ncred)++;
 
2995
    }
 
2996
 
 
2997
    return 0;
 
2998
}
 
2999
 
 
3000
 
 
3001
/*
 
3002
 * @param cred the populated libvirt credentials
 
3003
 * @param interact the SASL interactions to fill in results for
 
3004
 *
 
3005
 * Fills the SASL interactions with the result from the libvirt
 
3006
 * callbacks
 
3007
 */
 
3008
static void remoteAuthFillInteract(virConnectCredentialPtr cred,
 
3009
                                   sasl_interact_t *interact)
 
3010
{
 
3011
    int ninteract, ncred;
 
3012
    for (ninteract = 0, ncred = 0 ; interact[ninteract].id != 0 ; ninteract++) {
 
3013
        if (interact[ninteract].result)
 
3014
            continue;
 
3015
        interact[ninteract].result = cred[ncred].result;
 
3016
        interact[ninteract].len = cred[ncred].resultlen;
 
3017
        ncred++;
 
3018
    }
 
3019
}
 
3020
 
 
3021
struct remoteAuthInteractState {
 
3022
    sasl_interact_t *interact;
 
3023
    virConnectCredentialPtr cred;
 
3024
    size_t ncred;
 
3025
    virAuthConfigPtr config;
 
3026
};
 
3027
 
 
3028
 
 
3029
 
 
3030
static int remoteAuthFillFromConfig(virConnectPtr conn,
 
3031
                                    struct remoteAuthInteractState *state)
 
3032
{
 
3033
    int ret = -1;
 
3034
    int ninteract;
 
3035
    const char *credname;
 
3036
    char *path = NULL;
 
3037
 
 
3038
    VIR_DEBUG("Trying to fill auth parameters from config file");
 
3039
 
 
3040
    if (!state->config) {
 
3041
        if (virAuthGetConfigFilePath(conn, &path) < 0)
 
3042
            goto cleanup;
 
3043
        if (path == NULL) {
 
3044
            ret = 0;
 
3045
            goto cleanup;
 
3046
        }
 
3047
 
 
3048
        if (!(state->config = virAuthConfigNew(path)))
 
3049
            goto cleanup;
 
3050
    }
 
3051
 
 
3052
    for (ninteract = 0 ; state->interact[ninteract].id != 0 ; ninteract++) {
 
3053
        const char *value = NULL;
 
3054
 
 
3055
        switch (state->interact[ninteract].id) {
 
3056
        case SASL_CB_USER:
 
3057
            credname = "username";
 
3058
            break;
 
3059
        case SASL_CB_AUTHNAME:
 
3060
            credname = "authname";
 
3061
            break;
 
3062
        case SASL_CB_PASS:
 
3063
            credname = "password";
 
3064
            break;
 
3065
        case SASL_CB_GETREALM:
 
3066
            credname = "realm";
 
3067
            break;
 
3068
        default:
 
3069
            credname = NULL;
 
3070
            break;
 
3071
        }
 
3072
 
 
3073
        if (virAuthConfigLookup(state->config,
 
3074
                                "libvirt",
 
3075
                                conn->uri->server,
 
3076
                                credname,
 
3077
                                &value) < 0)
 
3078
            goto cleanup;
 
3079
 
 
3080
        if (value) {
 
3081
            state->interact[ninteract].result = value;
 
3082
            state->interact[ninteract].len = strlen(value);
 
3083
        }
 
3084
    }
 
3085
 
 
3086
    ret = 0;
 
3087
 
 
3088
cleanup:
 
3089
    VIR_FREE(path);
 
3090
    return ret;
 
3091
}
 
3092
 
 
3093
 
 
3094
static void remoteAuthInteractStateClear(struct remoteAuthInteractState *state,
 
3095
                                         bool final)
 
3096
{
 
3097
    size_t i;
 
3098
    if (!state)
 
3099
        return;
 
3100
 
 
3101
    for (i = 0 ; i < state->ncred ; i++)
 
3102
        VIR_FREE(state->cred[i].result);
 
3103
    VIR_FREE(state->cred);
 
3104
    state->ncred = 0;
 
3105
 
 
3106
    if (final)
 
3107
        virAuthConfigFree(state->config);
 
3108
}
 
3109
 
 
3110
 
 
3111
static int remoteAuthInteract(virConnectPtr conn,
 
3112
                              struct remoteAuthInteractState *state,
 
3113
                              virConnectAuthPtr auth)
 
3114
{
 
3115
    int ret = -1;
 
3116
 
 
3117
    VIR_DEBUG("Starting SASL interaction");
 
3118
    remoteAuthInteractStateClear(state, false);
 
3119
 
 
3120
    if (remoteAuthFillFromConfig(conn, state) < 0)
 
3121
        goto cleanup;
 
3122
 
 
3123
    if (remoteAuthMakeCredentials(state->interact, &state->cred, &state->ncred) < 0) {
 
3124
        remoteError(VIR_ERR_AUTH_FAILED, "%s",
 
3125
                    _("Failed to make auth credentials"));
 
3126
        goto cleanup;
 
3127
    }
 
3128
 
 
3129
    /* Run the authentication callback */
 
3130
    if (!auth || !auth->cb) {
 
3131
        remoteError(VIR_ERR_AUTH_FAILED, "%s",
 
3132
                    _("No authentication callback available"));
 
3133
        goto cleanup;
 
3134
    }
 
3135
 
 
3136
    if ((*(auth->cb))(state->cred, state->ncred, auth->cbdata) < 0) {
 
3137
        remoteError(VIR_ERR_AUTH_FAILED, "%s",
 
3138
                    _("Failed to collect auth credentials"));
 
3139
        goto cleanup;
 
3140
    }
 
3141
 
 
3142
    remoteAuthFillInteract(state->cred, state->interact);
 
3143
    /*
 
3144
     * 'interact' now has pointers to strings in 'state->cred'
 
3145
     * so we must not free state->cred until the *next*
 
3146
     * sasl_start/step function is complete. Hence we
 
3147
     * call remoteAuthInteractStateClear() at the *start*
 
3148
     * of this method, rather than the end.
 
3149
     */
 
3150
 
 
3151
    ret = 0;
 
3152
 
 
3153
cleanup:
 
3154
    return ret;
 
3155
}
 
3156
 
 
3157
 
 
3158
/* Perform the SASL authentication process
 
3159
 */
 
3160
static int
 
3161
remoteAuthSASL (virConnectPtr conn, struct private_data *priv,
 
3162
                virConnectAuthPtr auth, const char *wantmech)
 
3163
{
 
3164
    remote_auth_sasl_init_ret iret;
 
3165
    remote_auth_sasl_start_args sargs;
 
3166
    remote_auth_sasl_start_ret sret;
 
3167
    remote_auth_sasl_step_args pargs;
 
3168
    remote_auth_sasl_step_ret pret;
 
3169
    const char *clientout;
 
3170
    char *serverin = NULL;
 
3171
    size_t clientoutlen, serverinlen;
 
3172
    const char *mech;
 
3173
    int err, complete;
 
3174
    int ssf;
 
3175
    sasl_callback_t *saslcb = NULL;
 
3176
    int ret = -1;
 
3177
    const char *mechlist;
 
3178
    virNetSASLContextPtr saslCtxt;
 
3179
    virNetSASLSessionPtr sasl = NULL;
 
3180
    struct remoteAuthInteractState state;
 
3181
 
 
3182
    memset(&state, 0, sizeof(state));
 
3183
 
 
3184
    VIR_DEBUG("Client initialize SASL authentication");
 
3185
 
 
3186
    if (!(saslCtxt = virNetSASLContextNewClient()))
 
3187
        goto cleanup;
 
3188
 
 
3189
    if (auth) {
 
3190
        if ((saslcb = remoteAuthMakeCallbacks(auth->credtype, auth->ncredtype)) == NULL)
 
3191
            goto cleanup;
 
3192
    } else {
 
3193
        saslcb = NULL;
 
3194
    }
 
3195
 
 
3196
    /* Setup a handle for being a client */
 
3197
    if (!(sasl = virNetSASLSessionNewClient(saslCtxt,
 
3198
                                            "libvirt",
 
3199
                                            priv->hostname,
 
3200
                                            virNetClientLocalAddrString(priv->client),
 
3201
                                            virNetClientRemoteAddrString(priv->client),
 
3202
                                            saslcb)))
 
3203
        goto cleanup;
 
3204
 
 
3205
    /* Initialize some connection props we care about */
 
3206
    if (priv->tls) {
 
3207
        if ((ssf = virNetClientGetTLSKeySize(priv->client)) < 0)
 
3208
            goto cleanup;
 
3209
 
 
3210
        ssf *= 8; /* key size is bytes, sasl wants bits */
 
3211
 
 
3212
        VIR_DEBUG("Setting external SSF %d", ssf);
 
3213
        if (virNetSASLSessionExtKeySize(sasl, ssf) < 0)
 
3214
            goto cleanup;
 
3215
    }
 
3216
 
 
3217
    /* If we've got a secure channel (TLS or UNIX sock), we don't care about SSF */
 
3218
    /* If we're not secure, then forbid any anonymous or trivially crackable auth */
 
3219
    if (virNetSASLSessionSecProps(sasl,
 
3220
                                  priv->is_secure ? 0 : 56, /* Equiv to DES supported by all Kerberos */
 
3221
                                  priv->is_secure ? 0 : 100000, /* Very strong ! AES == 256 */
 
3222
                                  priv->is_secure ? true : false) < 0)
 
3223
        goto cleanup;
 
3224
 
 
3225
    /* First call is to inquire about supported mechanisms in the server */
 
3226
    memset (&iret, 0, sizeof(iret));
 
3227
    if (call (conn, priv, 0, REMOTE_PROC_AUTH_SASL_INIT,
 
3228
              (xdrproc_t) xdr_void, (char *)NULL,
 
3229
              (xdrproc_t) xdr_remote_auth_sasl_init_ret, (char *) &iret) != 0)
 
3230
        goto cleanup;
 
3231
 
 
3232
 
 
3233
    mechlist = iret.mechlist;
 
3234
    if (wantmech) {
 
3235
        if (strstr(mechlist, wantmech) == NULL) {
 
3236
            remoteError(VIR_ERR_AUTH_FAILED,
 
3237
                        _("SASL mechanism %s not supported by server"),
 
3238
                        wantmech);
 
3239
            VIR_FREE(iret.mechlist);
 
3240
            goto cleanup;
 
3241
        }
 
3242
        mechlist = wantmech;
 
3243
    }
 
3244
 restart:
 
3245
    /* Start the auth negotiation on the client end first */
 
3246
    VIR_DEBUG("Client start negotiation mechlist '%s'", mechlist);
 
3247
    if ((err = virNetSASLSessionClientStart(sasl,
 
3248
                                            mechlist,
 
3249
                                            &state.interact,
 
3250
                                            &clientout,
 
3251
                                            &clientoutlen,
 
3252
                                            &mech)) < 0)
 
3253
        goto cleanup;
 
3254
 
 
3255
    /* Need to gather some credentials from the client */
 
3256
    if (err == VIR_NET_SASL_INTERACT) {
 
3257
        if (remoteAuthInteract(conn, &state, auth) < 0) {
 
3258
            VIR_FREE(iret.mechlist);
 
3259
            goto cleanup;
 
3260
        }
 
3261
        goto restart;
 
3262
    }
 
3263
    VIR_FREE(iret.mechlist);
 
3264
 
 
3265
    if (clientoutlen > REMOTE_AUTH_SASL_DATA_MAX) {
 
3266
        remoteError(VIR_ERR_AUTH_FAILED,
 
3267
                    _("SASL negotiation data too long: %zu bytes"),
 
3268
                    clientoutlen);
 
3269
        goto cleanup;
 
3270
    }
 
3271
    /* NB, distinction of NULL vs "" is *critical* in SASL */
 
3272
    memset(&sargs, 0, sizeof(sargs));
 
3273
    sargs.nil = clientout ? 0 : 1;
 
3274
    sargs.data.data_val = (char*)clientout;
 
3275
    sargs.data.data_len = clientoutlen;
 
3276
    sargs.mech = (char*)mech;
 
3277
    VIR_DEBUG("Server start negotiation with mech %s. Data %zu bytes %p",
 
3278
              mech, clientoutlen, clientout);
 
3279
 
 
3280
    /* Now send the initial auth data to the server */
 
3281
    memset (&sret, 0, sizeof(sret));
 
3282
    if (call (conn, priv, 0, REMOTE_PROC_AUTH_SASL_START,
 
3283
              (xdrproc_t) xdr_remote_auth_sasl_start_args, (char *) &sargs,
 
3284
              (xdrproc_t) xdr_remote_auth_sasl_start_ret, (char *) &sret) != 0)
 
3285
        goto cleanup;
 
3286
 
 
3287
    complete = sret.complete;
 
3288
    /* NB, distinction of NULL vs "" is *critical* in SASL */
 
3289
    serverin = sret.nil ? NULL : sret.data.data_val;
 
3290
    serverinlen = sret.data.data_len;
 
3291
    VIR_DEBUG("Client step result complete: %d. Data %zu bytes %p",
 
3292
              complete, serverinlen, serverin);
 
3293
 
 
3294
    /* Loop-the-loop...
 
3295
     * Even if the server has completed, the client must *always* do at least one step
 
3296
     * in this loop to verify the server isn't lying about something. Mutual auth */
 
3297
    for (;;) {
 
3298
    restep:
 
3299
        if ((err = virNetSASLSessionClientStep(sasl,
 
3300
                                               serverin,
 
3301
                                               serverinlen,
 
3302
                                               &state.interact,
 
3303
                                               &clientout,
 
3304
                                               &clientoutlen)) < 0)
 
3305
            goto cleanup;
 
3306
 
 
3307
        /* Need to gather some credentials from the client */
 
3308
        if (err == VIR_NET_SASL_INTERACT) {
 
3309
            if (remoteAuthInteract(conn, &state, auth) < 0) {
 
3310
                VIR_FREE(iret.mechlist);
 
3311
                goto cleanup;
 
3312
            }
 
3313
            goto restep;
 
3314
        }
 
3315
 
 
3316
        VIR_FREE(serverin);
 
3317
        VIR_DEBUG("Client step result %d. Data %zu bytes %p",
 
3318
                  err, clientoutlen, clientout);
 
3319
 
 
3320
        /* Previous server call showed completion & we're now locally complete too */
 
3321
        if (complete && err == VIR_NET_SASL_COMPLETE)
 
3322
            break;
 
3323
 
 
3324
        /* Not done, prepare to talk with the server for another iteration */
 
3325
        /* NB, distinction of NULL vs "" is *critical* in SASL */
 
3326
        memset(&pargs, 0, sizeof(pargs));
 
3327
        pargs.nil = clientout ? 0 : 1;
 
3328
        pargs.data.data_val = (char*)clientout;
 
3329
        pargs.data.data_len = clientoutlen;
 
3330
        VIR_DEBUG("Server step with %zu bytes %p",
 
3331
                  clientoutlen, clientout);
 
3332
 
 
3333
        memset (&pret, 0, sizeof(pret));
 
3334
        if (call (conn, priv, 0, REMOTE_PROC_AUTH_SASL_STEP,
 
3335
                  (xdrproc_t) xdr_remote_auth_sasl_step_args, (char *) &pargs,
 
3336
                  (xdrproc_t) xdr_remote_auth_sasl_step_ret, (char *) &pret) != 0)
 
3337
            goto cleanup;
 
3338
 
 
3339
        complete = pret.complete;
 
3340
        /* NB, distinction of NULL vs "" is *critical* in SASL */
 
3341
        serverin = pret.nil ? NULL : pret.data.data_val;
 
3342
        serverinlen = pret.data.data_len;
 
3343
 
 
3344
        VIR_DEBUG("Client step result complete: %d. Data %zu bytes %p",
 
3345
                  complete, serverinlen, serverin);
 
3346
 
 
3347
        /* This server call shows complete, and earlier client step was OK */
 
3348
        if (complete && err == VIR_NET_SASL_COMPLETE) {
 
3349
            VIR_FREE(serverin);
 
3350
            break;
 
3351
        }
 
3352
    }
 
3353
 
 
3354
    /* Check for suitable SSF if not already secure (TLS or UNIX sock) */
 
3355
    if (!priv->is_secure) {
 
3356
        if ((ssf = virNetSASLSessionGetKeySize(sasl)) < 0)
 
3357
            goto cleanup;
 
3358
 
 
3359
        VIR_DEBUG("SASL SSF value %d", ssf);
 
3360
        if (ssf < 56) { /* 56 == DES level, good for Kerberos */
 
3361
            remoteError(VIR_ERR_AUTH_FAILED,
 
3362
                        _("negotiation SSF %d was not strong enough"), ssf);
 
3363
            goto cleanup;
 
3364
        }
 
3365
        priv->is_secure = 1;
 
3366
    }
 
3367
 
 
3368
    VIR_DEBUG("SASL authentication complete");
 
3369
    virNetClientSetSASLSession(priv->client, sasl);
 
3370
    ret = 0;
 
3371
 
 
3372
 cleanup:
 
3373
    VIR_FREE(serverin);
 
3374
 
 
3375
    remoteAuthInteractStateClear(&state, true);
 
3376
    VIR_FREE(saslcb);
 
3377
    virNetSASLSessionFree(sasl);
 
3378
    virNetSASLContextFree(saslCtxt);
 
3379
 
 
3380
    return ret;
 
3381
}
 
3382
#endif /* HAVE_SASL */
 
3383
 
 
3384
 
 
3385
#if HAVE_POLKIT
 
3386
# if HAVE_POLKIT1
 
3387
static int
 
3388
remoteAuthPolkit (virConnectPtr conn, struct private_data *priv,
 
3389
                  virConnectAuthPtr auth ATTRIBUTE_UNUSED)
 
3390
{
 
3391
    remote_auth_polkit_ret ret;
 
3392
    VIR_DEBUG("Client initialize PolicyKit-1 authentication");
 
3393
 
 
3394
    memset (&ret, 0, sizeof(ret));
 
3395
    if (call (conn, priv, 0, REMOTE_PROC_AUTH_POLKIT,
 
3396
              (xdrproc_t) xdr_void, (char *)NULL,
 
3397
              (xdrproc_t) xdr_remote_auth_polkit_ret, (char *) &ret) != 0) {
 
3398
        return -1; /* virError already set by call */
 
3399
    }
 
3400
 
 
3401
    VIR_DEBUG("PolicyKit-1 authentication complete");
 
3402
    return 0;
 
3403
}
 
3404
# elif HAVE_POLKIT0
 
3405
/* Perform the PolicyKit authentication process
 
3406
 */
 
3407
static int
 
3408
remoteAuthPolkit (virConnectPtr conn, struct private_data *priv,
 
3409
                  virConnectAuthPtr auth)
 
3410
{
 
3411
    remote_auth_polkit_ret ret;
 
3412
    int i, allowcb = 0;
 
3413
    virConnectCredential cred = {
 
3414
        VIR_CRED_EXTERNAL,
 
3415
        conn->flags & VIR_CONNECT_RO ? "org.libvirt.unix.monitor" : "org.libvirt.unix.manage",
 
3416
        "PolicyKit",
 
3417
        NULL,
 
3418
        NULL,
 
3419
        0,
 
3420
    };
 
3421
    VIR_DEBUG("Client initialize PolicyKit-0 authentication");
 
3422
 
 
3423
    /* Check auth first and if it succeeds we are done. */
 
3424
    memset (&ret, 0, sizeof(ret));
 
3425
    if (call (conn, priv, 0, REMOTE_PROC_AUTH_POLKIT,
 
3426
              (xdrproc_t) xdr_void, (char *)NULL,
 
3427
              (xdrproc_t) xdr_remote_auth_polkit_ret, (char *) &ret) == 0)
 
3428
        goto out;
 
3429
 
 
3430
    /* Auth failed.  Ask client to obtain it and check again. */
 
3431
    if (auth && auth->cb) {
 
3432
        /* Check if the necessary credential type for PolicyKit is supported */
 
3433
        for (i = 0 ; i < auth->ncredtype ; i++) {
 
3434
            if (auth->credtype[i] == VIR_CRED_EXTERNAL)
 
3435
                allowcb = 1;
 
3436
        }
 
3437
 
 
3438
        if (allowcb) {
 
3439
            VIR_DEBUG("Client run callback for PolicyKit authentication");
 
3440
            /* Run the authentication callback */
 
3441
            if ((*(auth->cb))(&cred, 1, auth->cbdata) < 0) {
 
3442
                remoteError(VIR_ERR_AUTH_FAILED, "%s",
 
3443
                            _("Failed to collect auth credentials"));
 
3444
                return -1;
 
3445
            }
 
3446
        } else {
 
3447
            VIR_DEBUG("Client auth callback does not support PolicyKit");
 
3448
            return -1;
 
3449
        }
 
3450
    } else {
 
3451
        VIR_DEBUG("No auth callback provided");
 
3452
        return -1;
 
3453
    }
 
3454
 
 
3455
    memset (&ret, 0, sizeof(ret));
 
3456
    if (call (conn, priv, 0, REMOTE_PROC_AUTH_POLKIT,
 
3457
              (xdrproc_t) xdr_void, (char *)NULL,
 
3458
              (xdrproc_t) xdr_remote_auth_polkit_ret, (char *) &ret) != 0) {
 
3459
        return -1; /* virError already set by call */
 
3460
    }
 
3461
 
 
3462
out:
 
3463
    VIR_DEBUG("PolicyKit-0 authentication complete");
 
3464
    return 0;
 
3465
}
 
3466
# endif /* HAVE_POLKIT0 */
 
3467
#endif /* HAVE_POLKIT */
 
3468
/*----------------------------------------------------------------------*/
 
3469
 
 
3470
static int remoteDomainEventRegister(virConnectPtr conn,
 
3471
                                     virConnectDomainEventCallback callback,
 
3472
                                     void *opaque,
 
3473
                                     virFreeCallback freecb)
 
3474
{
 
3475
    int rv = -1;
 
3476
    struct private_data *priv = conn->privateData;
 
3477
    int count;
 
3478
 
 
3479
    remoteDriverLock(priv);
 
3480
 
 
3481
    if ((count = virDomainEventStateRegister(conn, priv->domainEventState,
 
3482
                                             callback, opaque, freecb)) < 0) {
 
3483
         remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
 
3484
         goto done;
 
3485
    }
 
3486
 
 
3487
    if (count == 1) {
 
3488
        /* Tell the server when we are the first callback deregistering */
 
3489
        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER,
 
3490
                (xdrproc_t) xdr_void, (char *) NULL,
 
3491
                (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
3492
            goto done;
 
3493
    }
 
3494
 
 
3495
    rv = 0;
 
3496
 
 
3497
done:
 
3498
    remoteDriverUnlock(priv);
 
3499
    return rv;
 
3500
}
 
3501
 
 
3502
static int remoteDomainEventDeregister(virConnectPtr conn,
 
3503
                                       virConnectDomainEventCallback callback)
 
3504
{
 
3505
    struct private_data *priv = conn->privateData;
 
3506
    int rv = -1;
 
3507
    int count;
 
3508
 
 
3509
    remoteDriverLock(priv);
 
3510
 
 
3511
    if ((count = virDomainEventStateDeregister(conn,
 
3512
                                               priv->domainEventState,
 
3513
                                               callback)) < 0)
 
3514
        goto done;
 
3515
 
 
3516
    if (count == 0) {
 
3517
        /* Tell the server when we are the last callback deregistering */
 
3518
        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER,
 
3519
                  (xdrproc_t) xdr_void, (char *) NULL,
 
3520
                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
3521
            goto done;
 
3522
    }
 
3523
 
 
3524
    rv = 0;
 
3525
 
 
3526
done:
 
3527
    remoteDriverUnlock(priv);
 
3528
    return rv;
 
3529
}
 
3530
 
 
3531
 
 
3532
static void
 
3533
remoteDomainBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3534
                                virNetClientPtr client ATTRIBUTE_UNUSED,
 
3535
                                void *evdata, void *opaque)
 
3536
{
 
3537
    virConnectPtr conn = opaque;
 
3538
    struct private_data *priv = conn->privateData;
 
3539
    remote_domain_event_lifecycle_msg *msg = evdata;
 
3540
    virDomainPtr dom;
 
3541
    virDomainEventPtr event = NULL;
 
3542
 
 
3543
    dom = get_nonnull_domain(conn, msg->dom);
 
3544
    if (!dom)
 
3545
        return;
 
3546
 
 
3547
    event = virDomainEventNewFromDom(dom, msg->event, msg->detail);
 
3548
    virDomainFree(dom);
 
3549
 
 
3550
    remoteDomainEventQueue(priv, event);
 
3551
}
 
3552
 
 
3553
 
 
3554
static void
 
3555
remoteDomainBuildEventReboot(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3556
                             virNetClientPtr client ATTRIBUTE_UNUSED,
 
3557
                             void *evdata, void *opaque)
 
3558
{
 
3559
    virConnectPtr conn = opaque;
 
3560
    struct private_data *priv = conn->privateData;
 
3561
    remote_domain_event_reboot_msg *msg = evdata;
 
3562
    virDomainPtr dom;
 
3563
    virDomainEventPtr event = NULL;
 
3564
 
 
3565
    dom = get_nonnull_domain(conn, msg->dom);
 
3566
    if (!dom)
 
3567
        return;
 
3568
 
 
3569
    event = virDomainEventRebootNewFromDom(dom);
 
3570
    virDomainFree(dom);
 
3571
 
 
3572
    remoteDomainEventQueue(priv, event);
 
3573
}
 
3574
 
 
3575
 
 
3576
static void
 
3577
remoteDomainBuildEventRTCChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3578
                                virNetClientPtr client ATTRIBUTE_UNUSED,
 
3579
                                void *evdata, void *opaque)
 
3580
{
 
3581
    virConnectPtr conn = opaque;
 
3582
    struct private_data *priv = conn->privateData;
 
3583
    remote_domain_event_rtc_change_msg *msg = evdata;
 
3584
    virDomainPtr dom;
 
3585
    virDomainEventPtr event = NULL;
 
3586
 
 
3587
    dom = get_nonnull_domain(conn, msg->dom);
 
3588
    if (!dom)
 
3589
        return;
 
3590
 
 
3591
    event = virDomainEventRTCChangeNewFromDom(dom, msg->offset);
 
3592
    virDomainFree(dom);
 
3593
 
 
3594
    remoteDomainEventQueue(priv, event);
 
3595
}
 
3596
 
 
3597
 
 
3598
static void
 
3599
remoteDomainBuildEventWatchdog(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3600
                               virNetClientPtr client ATTRIBUTE_UNUSED,
 
3601
                               void *evdata, void *opaque)
 
3602
{
 
3603
    virConnectPtr conn = opaque;
 
3604
    struct private_data *priv = conn->privateData;
 
3605
    remote_domain_event_watchdog_msg *msg = evdata;
 
3606
    virDomainPtr dom;
 
3607
    virDomainEventPtr event = NULL;
 
3608
 
 
3609
    dom = get_nonnull_domain(conn, msg->dom);
 
3610
    if (!dom)
 
3611
        return;
 
3612
 
 
3613
    event = virDomainEventWatchdogNewFromDom(dom, msg->action);
 
3614
    virDomainFree(dom);
 
3615
 
 
3616
    remoteDomainEventQueue(priv, event);
 
3617
}
 
3618
 
 
3619
 
 
3620
static void
 
3621
remoteDomainBuildEventIOError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3622
                              virNetClientPtr client ATTRIBUTE_UNUSED,
 
3623
                              void *evdata, void *opaque)
 
3624
{
 
3625
    virConnectPtr conn = opaque;
 
3626
    struct private_data *priv = conn->privateData;
 
3627
    remote_domain_event_io_error_msg *msg = evdata;
 
3628
    virDomainPtr dom;
 
3629
    virDomainEventPtr event = NULL;
 
3630
 
 
3631
    dom = get_nonnull_domain(conn, msg->dom);
 
3632
    if (!dom)
 
3633
        return;
 
3634
 
 
3635
    event = virDomainEventIOErrorNewFromDom(dom,
 
3636
                                            msg->srcPath,
 
3637
                                            msg->devAlias,
 
3638
                                            msg->action);
 
3639
    virDomainFree(dom);
 
3640
 
 
3641
    remoteDomainEventQueue(priv, event);
 
3642
}
 
3643
 
 
3644
 
 
3645
static void
 
3646
remoteDomainBuildEventIOErrorReason(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3647
                                    virNetClientPtr client ATTRIBUTE_UNUSED,
 
3648
                                    void *evdata, void *opaque)
 
3649
{
 
3650
    virConnectPtr conn = opaque;
 
3651
    struct private_data *priv = conn->privateData;
 
3652
    remote_domain_event_io_error_reason_msg *msg = evdata;
 
3653
    virDomainPtr dom;
 
3654
    virDomainEventPtr event = NULL;
 
3655
 
 
3656
    dom = get_nonnull_domain(conn,msg->dom);
 
3657
    if (!dom)
 
3658
        return;
 
3659
 
 
3660
    event = virDomainEventIOErrorReasonNewFromDom(dom,
 
3661
                                                  msg->srcPath,
 
3662
                                                  msg->devAlias,
 
3663
                                                  msg->action,
 
3664
                                                  msg->reason);
 
3665
 
 
3666
    virDomainFree(dom);
 
3667
 
 
3668
    remoteDomainEventQueue(priv, event);
 
3669
}
 
3670
 
 
3671
static void
 
3672
remoteDomainBuildEventBlockJob(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3673
                               virNetClientPtr client ATTRIBUTE_UNUSED,
 
3674
                               void *evdata, void *opaque)
 
3675
{
 
3676
    virConnectPtr conn = opaque;
 
3677
    struct private_data *priv = conn->privateData;
 
3678
    remote_domain_event_block_job_msg *msg = evdata;
 
3679
    virDomainPtr dom;
 
3680
    virDomainEventPtr event = NULL;
 
3681
 
 
3682
    dom = get_nonnull_domain(conn, msg->dom);
 
3683
    if (!dom)
 
3684
        return;
 
3685
 
 
3686
    event = virDomainEventBlockJobNewFromDom(dom, msg->path, msg->type,
 
3687
                                             msg->status);
 
3688
 
 
3689
    virDomainFree(dom);
 
3690
 
 
3691
    remoteDomainEventQueue(priv, event);
 
3692
}
 
3693
 
 
3694
static void
 
3695
remoteDomainBuildEventGraphics(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3696
                               virNetClientPtr client ATTRIBUTE_UNUSED,
 
3697
                               void *evdata, void *opaque)
 
3698
{
 
3699
    virConnectPtr conn = opaque;
 
3700
    struct private_data *priv = conn->privateData;
 
3701
    remote_domain_event_graphics_msg *msg = evdata;
 
3702
    virDomainPtr dom;
 
3703
    virDomainEventPtr event = NULL;
 
3704
    virDomainEventGraphicsAddressPtr localAddr = NULL;
 
3705
    virDomainEventGraphicsAddressPtr remoteAddr = NULL;
 
3706
    virDomainEventGraphicsSubjectPtr subject = NULL;
 
3707
    int i;
 
3708
 
 
3709
    dom = get_nonnull_domain(conn, msg->dom);
 
3710
    if (!dom)
 
3711
        return;
 
3712
 
 
3713
    if (VIR_ALLOC(localAddr) < 0)
 
3714
        goto no_memory;
 
3715
    localAddr->family = msg->local.family;
 
3716
    if (!(localAddr->service = strdup(msg->local.service)) ||
 
3717
        !(localAddr->node = strdup(msg->local.node)))
 
3718
        goto no_memory;
 
3719
 
 
3720
    if (VIR_ALLOC(remoteAddr) < 0)
 
3721
        goto no_memory;
 
3722
    remoteAddr->family = msg->remote.family;
 
3723
    if (!(remoteAddr->service = strdup(msg->remote.service)) ||
 
3724
        !(remoteAddr->node = strdup(msg->remote.node)))
 
3725
        goto no_memory;
 
3726
 
 
3727
    if (VIR_ALLOC(subject) < 0)
 
3728
        goto no_memory;
 
3729
    if (VIR_ALLOC_N(subject->identities, msg->subject.subject_len) < 0)
 
3730
        goto no_memory;
 
3731
    subject->nidentity = msg->subject.subject_len;
 
3732
    for (i = 0 ; i < subject->nidentity ; i++) {
 
3733
        if (!(subject->identities[i].type = strdup(msg->subject.subject_val[i].type)) ||
 
3734
            !(subject->identities[i].name = strdup(msg->subject.subject_val[i].name)))
 
3735
            goto no_memory;
 
3736
    }
 
3737
 
 
3738
    event = virDomainEventGraphicsNewFromDom(dom,
 
3739
                                             msg->phase,
 
3740
                                             localAddr,
 
3741
                                             remoteAddr,
 
3742
                                             msg->authScheme,
 
3743
                                             subject);
 
3744
 
 
3745
    virDomainFree(dom);
 
3746
 
 
3747
    remoteDomainEventQueue(priv, event);
 
3748
    return;
 
3749
 
 
3750
no_memory:
 
3751
    if (localAddr) {
 
3752
        VIR_FREE(localAddr->service);
 
3753
        VIR_FREE(localAddr->node);
 
3754
        VIR_FREE(localAddr);
 
3755
    }
 
3756
    if (remoteAddr) {
 
3757
        VIR_FREE(remoteAddr->service);
 
3758
        VIR_FREE(remoteAddr->node);
 
3759
        VIR_FREE(remoteAddr);
 
3760
    }
 
3761
    if (subject) {
 
3762
        for (i = 0 ; i < subject->nidentity ; i++) {
 
3763
            VIR_FREE(subject->identities[i].type);
 
3764
            VIR_FREE(subject->identities[i].name);
 
3765
        }
 
3766
        VIR_FREE(subject->identities);
 
3767
        VIR_FREE(subject);
 
3768
    }
 
3769
    virDomainFree(dom);
 
3770
    return;
 
3771
}
 
3772
 
 
3773
 
 
3774
static void
 
3775
remoteDomainBuildEventControlError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3776
                                   virNetClientPtr client ATTRIBUTE_UNUSED,
 
3777
                                   void *evdata, void *opaque)
 
3778
{
 
3779
    virConnectPtr conn = opaque;
 
3780
    struct private_data *priv = conn->privateData;
 
3781
    remote_domain_event_control_error_msg *msg = evdata;
 
3782
    virDomainPtr dom;
 
3783
    virDomainEventPtr event = NULL;
 
3784
 
 
3785
    dom = get_nonnull_domain(conn, msg->dom);
 
3786
    if (!dom)
 
3787
        return;
 
3788
 
 
3789
    event = virDomainEventControlErrorNewFromDom(dom);
 
3790
 
 
3791
    virDomainFree(dom);
 
3792
 
 
3793
    remoteDomainEventQueue(priv, event);
 
3794
}
 
3795
 
 
3796
 
 
3797
static void
 
3798
remoteDomainBuildEventDiskChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3799
                                 virNetClientPtr client ATTRIBUTE_UNUSED,
 
3800
                                 void *evdata, void *opaque)
 
3801
{
 
3802
    virConnectPtr conn = opaque;
 
3803
    struct private_data *priv = conn->privateData;
 
3804
    remote_domain_event_disk_change_msg *msg = evdata;
 
3805
    virDomainPtr dom;
 
3806
    virDomainEventPtr event = NULL;
 
3807
 
 
3808
    dom = get_nonnull_domain(conn, msg->dom);
 
3809
    if (!dom)
 
3810
        return;
 
3811
 
 
3812
    event = virDomainEventDiskChangeNewFromDom(dom,
 
3813
                                               msg->oldSrcPath ? *msg->oldSrcPath : NULL,
 
3814
                                               msg->newSrcPath ? *msg->newSrcPath : NULL,
 
3815
                                               msg->devAlias,
 
3816
                                               msg->reason);
 
3817
 
 
3818
    virDomainFree(dom);
 
3819
 
 
3820
    remoteDomainEventQueue(priv, event);
 
3821
}
 
3822
 
 
3823
 
 
3824
static void
 
3825
remoteDomainBuildEventTrayChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3826
                                 virNetClientPtr client ATTRIBUTE_UNUSED,
 
3827
                                 void *evdata, void *opaque)
 
3828
{
 
3829
    virConnectPtr conn = opaque;
 
3830
    struct private_data *priv = conn->privateData;
 
3831
    remote_domain_event_tray_change_msg *msg = evdata;
 
3832
    virDomainPtr dom;
 
3833
    virDomainEventPtr event = NULL;
 
3834
 
 
3835
    dom = get_nonnull_domain(conn, msg->dom);
 
3836
    if (!dom)
 
3837
        return;
 
3838
 
 
3839
    event = virDomainEventTrayChangeNewFromDom(dom,
 
3840
                                               msg->devAlias,
 
3841
                                               msg->reason);
 
3842
 
 
3843
    virDomainFree(dom);
 
3844
 
 
3845
    remoteDomainEventQueue(priv, event);
 
3846
}
 
3847
 
 
3848
static void
 
3849
remoteDomainBuildEventPMWakeup(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3850
                               virNetClientPtr client ATTRIBUTE_UNUSED,
 
3851
                               void *evdata, void *opaque)
 
3852
{
 
3853
    virConnectPtr conn = opaque;
 
3854
    struct private_data *priv = conn->privateData;
 
3855
    remote_domain_event_pmwakeup_msg *msg = evdata;
 
3856
    virDomainPtr dom;
 
3857
    virDomainEventPtr event = NULL;
 
3858
 
 
3859
    dom = get_nonnull_domain(conn, msg->dom);
 
3860
    if (!dom)
 
3861
        return;
 
3862
 
 
3863
    event = virDomainEventPMWakeupNewFromDom(dom);
 
3864
 
 
3865
    virDomainFree(dom);
 
3866
 
 
3867
    remoteDomainEventQueue(priv, event);
 
3868
}
 
3869
 
 
3870
static void
 
3871
remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
 
3872
                                virNetClientPtr client ATTRIBUTE_UNUSED,
 
3873
                                void *evdata, void *opaque)
 
3874
{
 
3875
    virConnectPtr conn = opaque;
 
3876
    struct private_data *priv = conn->privateData;
 
3877
    remote_domain_event_pmsuspend_msg *msg = evdata;
 
3878
    virDomainPtr dom;
 
3879
    virDomainEventPtr event = NULL;
 
3880
 
 
3881
    dom = get_nonnull_domain(conn, msg->dom);
 
3882
    if (!dom)
 
3883
        return;
 
3884
 
 
3885
    event = virDomainEventPMSuspendNewFromDom(dom);
 
3886
 
 
3887
    virDomainFree(dom);
 
3888
 
 
3889
    remoteDomainEventQueue(priv, event);
 
3890
}
 
3891
 
 
3892
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
 
3893
remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
 
3894
                 unsigned int flags)
 
3895
{
 
3896
    return remoteGenericOpen(conn, auth, flags, &conn->secretPrivateData);
 
3897
}
 
3898
 
 
3899
static int
 
3900
remoteSecretClose (virConnectPtr conn)
 
3901
{
 
3902
    return remoteGenericClose(conn, &conn->secretPrivateData);
 
3903
}
 
3904
 
 
3905
static unsigned char *
 
3906
remoteSecretGetValue (virSecretPtr secret, size_t *value_size,
 
3907
                      unsigned int flags, unsigned int internalFlags)
 
3908
{
 
3909
    unsigned char *rv = NULL;
 
3910
    remote_secret_get_value_args args;
 
3911
    remote_secret_get_value_ret ret;
 
3912
    struct private_data *priv = secret->conn->secretPrivateData;
 
3913
 
 
3914
    remoteDriverLock (priv);
 
3915
 
 
3916
    /* internalFlags intentionally do not go over the wire */
 
3917
    if (internalFlags) {
 
3918
        remoteError(VIR_ERR_INTERNAL_ERROR, "%s", _("no internalFlags support"));
 
3919
        goto done;
 
3920
    }
 
3921
 
 
3922
    make_nonnull_secret (&args.secret, secret);
 
3923
    args.flags = flags;
 
3924
 
 
3925
    memset (&ret, 0, sizeof(ret));
 
3926
    if (call (secret->conn, priv, 0, REMOTE_PROC_SECRET_GET_VALUE,
 
3927
              (xdrproc_t) xdr_remote_secret_get_value_args, (char *) &args,
 
3928
              (xdrproc_t) xdr_remote_secret_get_value_ret, (char *) &ret) == -1)
 
3929
        goto done;
 
3930
 
 
3931
    *value_size = ret.value.value_len;
 
3932
    rv = (unsigned char *) ret.value.value_val; /* Caller frees. */
 
3933
 
 
3934
done:
 
3935
    remoteDriverUnlock (priv);
 
3936
    return rv;
 
3937
}
 
3938
 
 
3939
 
 
3940
static int
 
3941
remoteStreamSend(virStreamPtr st,
 
3942
                 const char *data,
 
3943
                 size_t nbytes)
 
3944
{
 
3945
    VIR_DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
 
3946
    struct private_data *priv = st->conn->privateData;
 
3947
    virNetClientStreamPtr privst = st->privateData;
 
3948
    int rv = -1;
 
3949
 
 
3950
    remoteDriverLock(priv);
 
3951
 
 
3952
    if (virNetClientStreamRaiseError(privst))
 
3953
        goto cleanup;
 
3954
 
 
3955
    rv = virNetClientStreamSendPacket(privst,
 
3956
                                      priv->client,
 
3957
                                      VIR_NET_CONTINUE,
 
3958
                                      data,
 
3959
                                      nbytes);
 
3960
 
 
3961
cleanup:
 
3962
    remoteDriverUnlock(priv);
 
3963
 
 
3964
    return rv;
 
3965
}
 
3966
 
 
3967
 
 
3968
static int
 
3969
remoteStreamRecv(virStreamPtr st,
 
3970
                 char *data,
 
3971
                 size_t nbytes)
 
3972
{
 
3973
    VIR_DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
 
3974
    struct private_data *priv = st->conn->privateData;
 
3975
    virNetClientStreamPtr privst = st->privateData;
 
3976
    int rv = -1;
 
3977
 
 
3978
    remoteDriverLock(priv);
 
3979
 
 
3980
    if (virNetClientStreamRaiseError(privst))
 
3981
        goto cleanup;
 
3982
 
 
3983
    rv = virNetClientStreamRecvPacket(privst,
 
3984
                                      priv->client,
 
3985
                                      data,
 
3986
                                      nbytes,
 
3987
                                      (st->flags & VIR_STREAM_NONBLOCK));
 
3988
 
 
3989
    VIR_DEBUG("Done %d", rv);
 
3990
 
 
3991
cleanup:
 
3992
    remoteDriverUnlock(priv);
 
3993
 
 
3994
    return rv;
 
3995
}
 
3996
 
 
3997
struct remoteStreamCallbackData {
 
3998
    virStreamPtr st;
 
3999
    virStreamEventCallback cb;
 
4000
    void *opaque;
 
4001
    virFreeCallback ff;
 
4002
};
 
4003
 
 
4004
static void remoteStreamEventCallback(virNetClientStreamPtr stream ATTRIBUTE_UNUSED,
 
4005
                                      int events,
 
4006
                                      void *opaque)
 
4007
{
 
4008
    struct remoteStreamCallbackData *cbdata = opaque;
 
4009
 
 
4010
    (cbdata->cb)(cbdata->st, events, cbdata->opaque);
 
4011
}
 
4012
 
 
4013
 
 
4014
static void remoteStreamCallbackFree(void *opaque)
 
4015
{
 
4016
    struct remoteStreamCallbackData *cbdata = opaque;
 
4017
 
 
4018
    if (!cbdata->cb && cbdata->ff)
 
4019
        (cbdata->ff)(cbdata->opaque);
 
4020
 
 
4021
    virStreamFree(cbdata->st);
 
4022
    VIR_FREE(opaque);
 
4023
}
 
4024
 
 
4025
 
 
4026
static int
 
4027
remoteStreamEventAddCallback(virStreamPtr st,
 
4028
                             int events,
 
4029
                             virStreamEventCallback cb,
 
4030
                             void *opaque,
 
4031
                             virFreeCallback ff)
 
4032
{
 
4033
    struct private_data *priv = st->conn->privateData;
 
4034
    virNetClientStreamPtr privst = st->privateData;
 
4035
    int ret = -1;
 
4036
    struct remoteStreamCallbackData *cbdata;
 
4037
 
 
4038
    if (VIR_ALLOC(cbdata) < 0) {
 
4039
        virReportOOMError();
 
4040
        return -1;
 
4041
    }
 
4042
    cbdata->cb = cb;
 
4043
    cbdata->opaque = opaque;
 
4044
    cbdata->ff = ff;
 
4045
    cbdata->st = st;
 
4046
    virStreamRef(st);
 
4047
 
 
4048
    remoteDriverLock(priv);
 
4049
 
 
4050
    if ((ret = virNetClientStreamEventAddCallback(privst,
 
4051
                                                  events,
 
4052
                                                  remoteStreamEventCallback,
 
4053
                                                  cbdata,
 
4054
                                                  remoteStreamCallbackFree)) < 0) {
 
4055
        VIR_FREE(cbdata);
 
4056
        goto cleanup;
 
4057
    }
 
4058
 
 
4059
cleanup:
 
4060
    remoteDriverUnlock(priv);
 
4061
    return ret;
 
4062
}
 
4063
 
 
4064
 
 
4065
static int
 
4066
remoteStreamEventUpdateCallback(virStreamPtr st,
 
4067
                                int events)
 
4068
{
 
4069
    struct private_data *priv = st->conn->privateData;
 
4070
    virNetClientStreamPtr privst = st->privateData;
 
4071
    int ret = -1;
 
4072
 
 
4073
    remoteDriverLock(priv);
 
4074
 
 
4075
    ret = virNetClientStreamEventUpdateCallback(privst, events);
 
4076
 
 
4077
    remoteDriverUnlock(priv);
 
4078
    return ret;
 
4079
}
 
4080
 
 
4081
 
 
4082
static int
 
4083
remoteStreamEventRemoveCallback(virStreamPtr st)
 
4084
{
 
4085
    struct private_data *priv = st->conn->privateData;
 
4086
    virNetClientStreamPtr privst = st->privateData;
 
4087
    int ret = -1;
 
4088
 
 
4089
    remoteDriverLock(priv);
 
4090
 
 
4091
    ret = virNetClientStreamEventRemoveCallback(privst);
 
4092
 
 
4093
    remoteDriverUnlock(priv);
 
4094
    return ret;
 
4095
}
 
4096
 
 
4097
 
 
4098
static int
 
4099
remoteStreamFinish(virStreamPtr st)
 
4100
{
 
4101
    struct private_data *priv = st->conn->privateData;
 
4102
    virNetClientStreamPtr privst = st->privateData;
 
4103
    int ret = -1;
 
4104
 
 
4105
    remoteDriverLock(priv);
 
4106
 
 
4107
    if (virNetClientStreamRaiseError(privst))
 
4108
        goto cleanup;
 
4109
 
 
4110
    ret = virNetClientStreamSendPacket(privst,
 
4111
                                       priv->client,
 
4112
                                       VIR_NET_OK,
 
4113
                                       NULL,
 
4114
                                       0);
 
4115
 
 
4116
cleanup:
 
4117
    virNetClientRemoveStream(priv->client, privst);
 
4118
    virNetClientStreamFree(privst);
 
4119
    st->privateData = NULL;
 
4120
    st->driver = NULL;
 
4121
 
 
4122
    remoteDriverUnlock(priv);
 
4123
    return ret;
 
4124
}
 
4125
 
 
4126
 
 
4127
static int
 
4128
remoteStreamAbort(virStreamPtr st)
 
4129
{
 
4130
    struct private_data *priv = st->conn->privateData;
 
4131
    virNetClientStreamPtr privst = st->privateData;
 
4132
    int ret = -1;
 
4133
 
 
4134
    remoteDriverLock(priv);
 
4135
 
 
4136
    if (virNetClientStreamRaiseError(privst))
 
4137
        goto cleanup;
 
4138
 
 
4139
    ret = virNetClientStreamSendPacket(privst,
 
4140
                                       priv->client,
 
4141
                                       VIR_NET_ERROR,
 
4142
                                       NULL,
 
4143
                                       0);
 
4144
 
 
4145
cleanup:
 
4146
    virNetClientRemoveStream(priv->client, privst);
 
4147
    virNetClientStreamFree(privst);
 
4148
    st->privateData = NULL;
 
4149
    st->driver = NULL;
 
4150
 
 
4151
    remoteDriverUnlock(priv);
 
4152
    return ret;
 
4153
}
 
4154
 
 
4155
 
 
4156
static virStreamDriver remoteStreamDrv = {
 
4157
    .streamRecv = remoteStreamRecv,
 
4158
    .streamSend = remoteStreamSend,
 
4159
    .streamFinish = remoteStreamFinish,
 
4160
    .streamAbort = remoteStreamAbort,
 
4161
    .streamAddCallback = remoteStreamEventAddCallback,
 
4162
    .streamUpdateCallback = remoteStreamEventUpdateCallback,
 
4163
    .streamRemoveCallback = remoteStreamEventRemoveCallback,
 
4164
};
 
4165
 
 
4166
 
 
4167
static int remoteDomainEventRegisterAny(virConnectPtr conn,
 
4168
                                        virDomainPtr dom,
 
4169
                                        int eventID,
 
4170
                                        virConnectDomainEventGenericCallback callback,
 
4171
                                        void *opaque,
 
4172
                                        virFreeCallback freecb)
 
4173
{
 
4174
    int rv = -1;
 
4175
    struct private_data *priv = conn->privateData;
 
4176
    remote_domain_events_register_any_args args;
 
4177
    int callbackID;
 
4178
    int count;
 
4179
 
 
4180
    remoteDriverLock(priv);
 
4181
 
 
4182
    if ((count = virDomainEventStateRegisterID(conn,
 
4183
                                               priv->domainEventState,
 
4184
                                               dom, eventID,
 
4185
                                               callback, opaque, freecb,
 
4186
                                               &callbackID)) < 0) {
 
4187
        remoteError(VIR_ERR_RPC, "%s", _("adding cb to list"));
 
4188
        goto done;
 
4189
    }
 
4190
 
 
4191
    /* If this is the first callback for this eventID, we need to enable
 
4192
     * events on the server */
 
4193
    if (count == 1) {
 
4194
        args.eventID = eventID;
 
4195
 
 
4196
        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_REGISTER_ANY,
 
4197
                  (xdrproc_t) xdr_remote_domain_events_register_any_args, (char *) &args,
 
4198
                  (xdrproc_t) xdr_void, (char *)NULL) == -1) {
 
4199
            virDomainEventStateDeregisterID(conn,
 
4200
                                            priv->domainEventState,
 
4201
                                            callbackID);
 
4202
            goto done;
 
4203
        }
 
4204
    }
 
4205
 
 
4206
    rv = callbackID;
 
4207
 
 
4208
done:
 
4209
    remoteDriverUnlock(priv);
 
4210
    return rv;
 
4211
}
 
4212
 
 
4213
 
 
4214
static int remoteDomainEventDeregisterAny(virConnectPtr conn,
 
4215
                                          int callbackID)
 
4216
{
 
4217
    struct private_data *priv = conn->privateData;
 
4218
    int rv = -1;
 
4219
    remote_domain_events_deregister_any_args args;
 
4220
    int eventID;
 
4221
    int count;
 
4222
 
 
4223
    remoteDriverLock(priv);
 
4224
 
 
4225
    if ((eventID = virDomainEventStateEventID(conn,
 
4226
                                              priv->domainEventState,
 
4227
                                              callbackID)) < 0) {
 
4228
        remoteError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
 
4229
        goto done;
 
4230
    }
 
4231
 
 
4232
    if ((count = virDomainEventStateDeregisterID(conn,
 
4233
                                                 priv->domainEventState,
 
4234
                                                 callbackID)) < 0) {
 
4235
        remoteError(VIR_ERR_RPC, _("unable to find callback ID %d"), callbackID);
 
4236
        goto done;
 
4237
    }
 
4238
 
 
4239
    /* If that was the last callback for this eventID, we need to disable
 
4240
     * events on the server */
 
4241
    if (count == 0) {
 
4242
        args.eventID = callbackID;
 
4243
 
 
4244
        if (call (conn, priv, 0, REMOTE_PROC_DOMAIN_EVENTS_DEREGISTER_ANY,
 
4245
                  (xdrproc_t) xdr_remote_domain_events_deregister_any_args, (char *) &args,
 
4246
                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
4247
            goto done;
 
4248
    }
 
4249
 
 
4250
    rv = 0;
 
4251
 
 
4252
done:
 
4253
    remoteDriverUnlock(priv);
 
4254
    return rv;
 
4255
}
 
4256
 
 
4257
 
 
4258
/*----------------------------------------------------------------------*/
 
4259
 
 
4260
static int
 
4261
remoteQemuDomainMonitorCommand (virDomainPtr domain, const char *cmd,
 
4262
                                char **result, unsigned int flags)
 
4263
{
 
4264
    int rv = -1;
 
4265
    qemu_monitor_command_args args;
 
4266
    qemu_monitor_command_ret ret;
 
4267
    struct private_data *priv = domain->conn->privateData;
 
4268
 
 
4269
    remoteDriverLock(priv);
 
4270
 
 
4271
    make_nonnull_domain(&args.dom, domain);
 
4272
    args.cmd = (char *)cmd;
 
4273
    args.flags = flags;
 
4274
 
 
4275
    memset (&ret, 0, sizeof(ret));
 
4276
    if (call (domain->conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_MONITOR_COMMAND,
 
4277
              (xdrproc_t) xdr_qemu_monitor_command_args, (char *) &args,
 
4278
              (xdrproc_t) xdr_qemu_monitor_command_ret, (char *) &ret) == -1)
 
4279
        goto done;
 
4280
 
 
4281
    *result = strdup(ret.result);
 
4282
    if (*result == NULL) {
 
4283
        virReportOOMError();
 
4284
        goto cleanup;
 
4285
    }
 
4286
 
 
4287
    rv = 0;
 
4288
 
 
4289
cleanup:
 
4290
    xdr_free ((xdrproc_t) xdr_qemu_monitor_command_ret, (char *) &ret);
 
4291
 
 
4292
done:
 
4293
    remoteDriverUnlock(priv);
 
4294
    return rv;
 
4295
}
 
4296
 
 
4297
 
 
4298
static char *
 
4299
remoteDomainMigrateBegin3(virDomainPtr domain,
 
4300
                          const char *xmlin,
 
4301
                          char **cookieout,
 
4302
                          int *cookieoutlen,
 
4303
                          unsigned long flags,
 
4304
                          const char *dname,
 
4305
                          unsigned long resource)
 
4306
{
 
4307
    char *rv = NULL;
 
4308
    remote_domain_migrate_begin3_args args;
 
4309
    remote_domain_migrate_begin3_ret ret;
 
4310
    struct private_data *priv = domain->conn->privateData;
 
4311
 
 
4312
    remoteDriverLock(priv);
 
4313
 
 
4314
    memset(&args, 0, sizeof(args));
 
4315
    memset(&ret, 0, sizeof(ret));
 
4316
 
 
4317
    make_nonnull_domain (&args.dom, domain);
 
4318
    args.xmlin = xmlin == NULL ? NULL : (char **) &xmlin;
 
4319
    args.flags = flags;
 
4320
    args.dname = dname == NULL ? NULL : (char **) &dname;
 
4321
    args.resource = resource;
 
4322
 
 
4323
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3,
 
4324
              (xdrproc_t) xdr_remote_domain_migrate_begin3_args, (char *) &args,
 
4325
              (xdrproc_t) xdr_remote_domain_migrate_begin3_ret, (char *) &ret) == -1)
 
4326
        goto done;
 
4327
 
 
4328
    if (ret.cookie_out.cookie_out_len > 0) {
 
4329
        if (!cookieout || !cookieoutlen) {
 
4330
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
4331
                        _("caller ignores cookieout or cookieoutlen"));
 
4332
            goto error;
 
4333
        }
 
4334
        *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
 
4335
        *cookieoutlen = ret.cookie_out.cookie_out_len;
 
4336
    }
 
4337
 
 
4338
    rv = ret.xml; /* caller frees */
 
4339
 
 
4340
done:
 
4341
    remoteDriverUnlock(priv);
 
4342
    return rv;
 
4343
 
 
4344
error:
 
4345
    VIR_FREE(ret.cookie_out.cookie_out_val);
 
4346
    goto done;
 
4347
}
 
4348
 
 
4349
 
 
4350
static int
 
4351
remoteDomainMigratePrepare3(virConnectPtr dconn,
 
4352
                            const char *cookiein,
 
4353
                            int cookieinlen,
 
4354
                            char **cookieout,
 
4355
                            int *cookieoutlen,
 
4356
                            const char *uri_in,
 
4357
                            char **uri_out,
 
4358
                            unsigned long flags,
 
4359
                            const char *dname,
 
4360
                            unsigned long resource,
 
4361
                            const char *dom_xml)
 
4362
{
 
4363
    int rv = -1;
 
4364
    remote_domain_migrate_prepare3_args args;
 
4365
    remote_domain_migrate_prepare3_ret ret;
 
4366
    struct private_data *priv = dconn->privateData;
 
4367
 
 
4368
    remoteDriverLock(priv);
 
4369
 
 
4370
    memset(&args, 0, sizeof(args));
 
4371
    memset(&ret, 0, sizeof(ret));
 
4372
 
 
4373
    args.cookie_in.cookie_in_val = (char *)cookiein;
 
4374
    args.cookie_in.cookie_in_len = cookieinlen;
 
4375
    args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
 
4376
    args.flags = flags;
 
4377
    args.dname = dname == NULL ? NULL : (char **) &dname;
 
4378
    args.resource = resource;
 
4379
    args.dom_xml = (char *) dom_xml;
 
4380
 
 
4381
    memset (&ret, 0, sizeof(ret));
 
4382
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3,
 
4383
              (xdrproc_t) xdr_remote_domain_migrate_prepare3_args, (char *) &args,
 
4384
              (xdrproc_t) xdr_remote_domain_migrate_prepare3_ret, (char *) &ret) == -1)
 
4385
        goto done;
 
4386
 
 
4387
    if (ret.cookie_out.cookie_out_len > 0) {
 
4388
        if (!cookieout || !cookieoutlen) {
 
4389
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
4390
                        _("caller ignores cookieout or cookieoutlen"));
 
4391
            goto error;
 
4392
        }
 
4393
        *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
 
4394
        *cookieoutlen = ret.cookie_out.cookie_out_len;
 
4395
    }
 
4396
    if (ret.uri_out) {
 
4397
        if (!uri_out) {
 
4398
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
4399
                        _("caller ignores uri_out"));
 
4400
            goto error;
 
4401
        }
 
4402
        *uri_out = *ret.uri_out; /* Caller frees. */
 
4403
    }
 
4404
 
 
4405
    rv = 0;
 
4406
 
 
4407
done:
 
4408
    VIR_FREE(ret.uri_out);
 
4409
    remoteDriverUnlock(priv);
 
4410
    return rv;
 
4411
error:
 
4412
    VIR_FREE(ret.cookie_out.cookie_out_val);
 
4413
    if (ret.uri_out)
 
4414
        VIR_FREE(*ret.uri_out);
 
4415
    goto done;
 
4416
}
 
4417
 
 
4418
 
 
4419
static int
 
4420
remoteDomainMigratePrepareTunnel3(virConnectPtr dconn,
 
4421
                                  virStreamPtr st,
 
4422
                                  const char *cookiein,
 
4423
                                  int cookieinlen,
 
4424
                                  char **cookieout,
 
4425
                                  int *cookieoutlen,
 
4426
                                  unsigned long flags,
 
4427
                                  const char *dname,
 
4428
                                  unsigned long resource,
 
4429
                                  const char *dom_xml)
 
4430
{
 
4431
    struct private_data *priv = dconn->privateData;
 
4432
    int rv = -1;
 
4433
    remote_domain_migrate_prepare_tunnel3_args args;
 
4434
    remote_domain_migrate_prepare_tunnel3_ret ret;
 
4435
    virNetClientStreamPtr netst;
 
4436
 
 
4437
    remoteDriverLock(priv);
 
4438
 
 
4439
    memset(&args, 0, sizeof(args));
 
4440
    memset(&ret, 0, sizeof(ret));
 
4441
 
 
4442
    if (!(netst = virNetClientStreamNew(priv->remoteProgram,
 
4443
                                        REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3,
 
4444
                                        priv->counter)))
 
4445
        goto done;
 
4446
 
 
4447
    if (virNetClientAddStream(priv->client, netst) < 0) {
 
4448
        virNetClientStreamFree(netst);
 
4449
        goto done;
 
4450
    }
 
4451
 
 
4452
    st->driver = &remoteStreamDrv;
 
4453
    st->privateData = netst;
 
4454
 
 
4455
    args.cookie_in.cookie_in_val = (char *)cookiein;
 
4456
    args.cookie_in.cookie_in_len = cookieinlen;
 
4457
    args.flags = flags;
 
4458
    args.dname = dname == NULL ? NULL : (char **) &dname;
 
4459
    args.resource = resource;
 
4460
    args.dom_xml = (char *) dom_xml;
 
4461
 
 
4462
    if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3,
 
4463
             (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_args, (char *) &args,
 
4464
             (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_ret, (char *) &ret) == -1) {
 
4465
        virNetClientRemoveStream(priv->client, netst);
 
4466
        virNetClientStreamFree(netst);
 
4467
        goto done;
 
4468
    }
 
4469
 
 
4470
    if (ret.cookie_out.cookie_out_len > 0) {
 
4471
        if (!cookieout || !cookieoutlen) {
 
4472
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
4473
                        _("caller ignores cookieout or cookieoutlen"));
 
4474
            goto error;
 
4475
        }
 
4476
        *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
 
4477
        *cookieoutlen = ret.cookie_out.cookie_out_len;
 
4478
    }
 
4479
 
 
4480
    rv = 0;
 
4481
 
 
4482
done:
 
4483
    remoteDriverUnlock(priv);
 
4484
    return rv;
 
4485
 
 
4486
error:
 
4487
    VIR_FREE(ret.cookie_out.cookie_out_val);
 
4488
    goto done;
 
4489
}
 
4490
 
 
4491
 
 
4492
static int
 
4493
remoteDomainMigratePerform3(virDomainPtr dom,
 
4494
                            const char *xmlin,
 
4495
                            const char *cookiein,
 
4496
                            int cookieinlen,
 
4497
                            char **cookieout,
 
4498
                            int *cookieoutlen,
 
4499
                            const char *dconnuri,
 
4500
                            const char *uri,
 
4501
                            unsigned long flags,
 
4502
                            const char *dname,
 
4503
                            unsigned long resource)
 
4504
{
 
4505
    int rv = -1;
 
4506
    remote_domain_migrate_perform3_args args;
 
4507
    remote_domain_migrate_perform3_ret ret;
 
4508
    struct private_data *priv = dom->conn->privateData;
 
4509
 
 
4510
    remoteDriverLock(priv);
 
4511
 
 
4512
    memset(&args, 0, sizeof(args));
 
4513
    memset(&ret, 0, sizeof(ret));
 
4514
 
 
4515
    make_nonnull_domain(&args.dom, dom);
 
4516
 
 
4517
    args.xmlin = xmlin == NULL ? NULL : (char **) &xmlin;
 
4518
    args.cookie_in.cookie_in_val = (char *)cookiein;
 
4519
    args.cookie_in.cookie_in_len = cookieinlen;
 
4520
    args.flags = flags;
 
4521
    args.dname = dname == NULL ? NULL : (char **) &dname;
 
4522
    args.uri = uri == NULL ? NULL : (char **) &uri;
 
4523
    args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri;
 
4524
    args.resource = resource;
 
4525
 
 
4526
    if (call (dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3,
 
4527
              (xdrproc_t) xdr_remote_domain_migrate_perform3_args, (char *) &args,
 
4528
              (xdrproc_t) xdr_remote_domain_migrate_perform3_ret, (char *) &ret) == -1)
 
4529
        goto done;
 
4530
 
 
4531
    if (ret.cookie_out.cookie_out_len > 0) {
 
4532
        if (!cookieout || !cookieoutlen) {
 
4533
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
4534
                        _("caller ignores cookieout or cookieoutlen"));
 
4535
            goto error;
 
4536
        }
 
4537
        *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
 
4538
        *cookieoutlen = ret.cookie_out.cookie_out_len;
 
4539
    }
 
4540
 
 
4541
    rv = 0;
 
4542
 
 
4543
done:
 
4544
    remoteDriverUnlock(priv);
 
4545
    return rv;
 
4546
 
 
4547
error:
 
4548
    VIR_FREE(ret.cookie_out.cookie_out_val);
 
4549
    goto done;
 
4550
}
 
4551
 
 
4552
 
 
4553
static virDomainPtr
 
4554
remoteDomainMigrateFinish3(virConnectPtr dconn,
 
4555
                           const char *dname,
 
4556
                           const char *cookiein,
 
4557
                           int cookieinlen,
 
4558
                           char **cookieout,
 
4559
                           int *cookieoutlen,
 
4560
                           const char *dconnuri,
 
4561
                           const char *uri,
 
4562
                           unsigned long flags,
 
4563
                           int cancelled)
 
4564
{
 
4565
    remote_domain_migrate_finish3_args args;
 
4566
    remote_domain_migrate_finish3_ret ret;
 
4567
    struct private_data *priv = dconn->privateData;
 
4568
    virDomainPtr rv = NULL;
 
4569
 
 
4570
    remoteDriverLock(priv);
 
4571
 
 
4572
    memset(&args, 0, sizeof(args));
 
4573
    memset(&ret, 0, sizeof(ret));
 
4574
 
 
4575
    args.cookie_in.cookie_in_val = (char *)cookiein;
 
4576
    args.cookie_in.cookie_in_len = cookieinlen;
 
4577
    args.dname = (char *) dname;
 
4578
    args.uri = uri == NULL ? NULL : (char **) &uri;
 
4579
    args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri;
 
4580
    args.flags = flags;
 
4581
    args.cancelled = cancelled;
 
4582
 
 
4583
    if (call (dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH3,
 
4584
              (xdrproc_t) xdr_remote_domain_migrate_finish3_args, (char *) &args,
 
4585
              (xdrproc_t) xdr_remote_domain_migrate_finish3_ret, (char *) &ret) == -1)
 
4586
        goto done;
 
4587
 
 
4588
    rv = get_nonnull_domain(dconn, ret.dom);
 
4589
 
 
4590
    if (ret.cookie_out.cookie_out_len > 0) {
 
4591
        if (!cookieout || !cookieoutlen) {
 
4592
            remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
4593
                        _("caller ignores cookieout or cookieoutlen"));
 
4594
            goto error;
 
4595
        }
 
4596
        *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
 
4597
        *cookieoutlen = ret.cookie_out.cookie_out_len;
 
4598
        ret.cookie_out.cookie_out_val = NULL;
 
4599
        ret.cookie_out.cookie_out_len = 0;
 
4600
    }
 
4601
 
 
4602
    xdr_free ((xdrproc_t) &xdr_remote_domain_migrate_finish3_ret, (char *) &ret);
 
4603
 
 
4604
done:
 
4605
    remoteDriverUnlock(priv);
 
4606
    return rv;
 
4607
 
 
4608
error:
 
4609
    VIR_FREE(ret.cookie_out.cookie_out_val);
 
4610
    goto done;
 
4611
}
 
4612
 
 
4613
 
 
4614
static int
 
4615
remoteDomainMigrateConfirm3(virDomainPtr domain,
 
4616
                            const char *cookiein,
 
4617
                            int cookieinlen,
 
4618
                            unsigned long flags,
 
4619
                            int cancelled)
 
4620
{
 
4621
    int rv = -1;
 
4622
    remote_domain_migrate_confirm3_args args;
 
4623
    struct private_data *priv = domain->conn->privateData;
 
4624
 
 
4625
    remoteDriverLock(priv);
 
4626
 
 
4627
    memset(&args, 0, sizeof(args));
 
4628
 
 
4629
    make_nonnull_domain (&args.dom, domain);
 
4630
    args.cookie_in.cookie_in_len = cookieinlen;
 
4631
    args.cookie_in.cookie_in_val = (char *) cookiein;
 
4632
    args.flags = flags;
 
4633
    args.cancelled = cancelled;
 
4634
 
 
4635
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3,
 
4636
              (xdrproc_t) xdr_remote_domain_migrate_confirm3_args, (char *) &args,
 
4637
              (xdrproc_t) xdr_void, (char *) NULL) == -1)
 
4638
        goto done;
 
4639
 
 
4640
    rv = 0;
 
4641
 
 
4642
done:
 
4643
    remoteDriverUnlock(priv);
 
4644
    return rv;
 
4645
}
 
4646
 
 
4647
 
 
4648
static int
 
4649
remoteDomainOpenGraphics(virDomainPtr dom,
 
4650
                         unsigned int idx,
 
4651
                         int fd,
 
4652
                         unsigned int flags)
 
4653
{
 
4654
    int rv = -1;
 
4655
    remote_domain_open_graphics_args args;
 
4656
    struct private_data *priv = dom->conn->privateData;
 
4657
 
 
4658
    remoteDriverLock(priv);
 
4659
 
 
4660
    make_nonnull_domain (&args.dom, dom);
 
4661
    args.idx = idx;
 
4662
    args.flags = flags;
 
4663
 
 
4664
    if (callWithFD(dom->conn, priv, 0, fd, REMOTE_PROC_DOMAIN_OPEN_GRAPHICS,
 
4665
                   (xdrproc_t) xdr_remote_domain_open_graphics_args, (char *) &args,
 
4666
                   (xdrproc_t) xdr_void, NULL) == -1)
 
4667
        goto done;
 
4668
 
 
4669
    rv = 0;
 
4670
 
 
4671
done:
 
4672
    remoteDriverUnlock(priv);
 
4673
 
 
4674
    return rv;
 
4675
}
 
4676
 
 
4677
 
 
4678
static int
 
4679
remoteSetKeepAlive(virConnectPtr conn, int interval, unsigned int count)
 
4680
{
 
4681
    struct private_data *priv = conn->privateData;
 
4682
    int ret = -1;
 
4683
 
 
4684
    remoteDriverLock(priv);
 
4685
    if (!virNetClientKeepAliveIsSupported(priv->client)) {
 
4686
        remoteError(VIR_ERR_INTERNAL_ERROR, "%s",
 
4687
                    _("the caller doesn't support keepalive protocol;"
 
4688
                      " perhaps it's missing event loop implementation"));
 
4689
        goto cleanup;
 
4690
    }
 
4691
 
 
4692
    if (!priv->serverKeepAlive) {
 
4693
        ret = 1;
 
4694
        goto cleanup;
 
4695
    }
 
4696
 
 
4697
    if (interval > 0) {
 
4698
        ret = virNetClientKeepAliveStart(priv->client, interval, count);
 
4699
    } else {
 
4700
        virNetClientKeepAliveStop(priv->client);
 
4701
        ret = 0;
 
4702
    }
 
4703
 
 
4704
cleanup:
 
4705
    remoteDriverUnlock(priv);
 
4706
    return ret;
 
4707
}
 
4708
 
 
4709
 
 
4710
static int
 
4711
remoteIsAlive(virConnectPtr conn)
 
4712
{
 
4713
    struct private_data *priv = conn->privateData;
 
4714
    bool ret;
 
4715
 
 
4716
    remoteDriverLock(priv);
 
4717
    ret = virNetClientIsOpen(priv->client);
 
4718
    remoteDriverUnlock(priv);
 
4719
 
 
4720
    if (ret)
 
4721
        return 1;
 
4722
    else
 
4723
        return 0;
 
4724
}
 
4725
 
 
4726
 
 
4727
static int
 
4728
remoteDomainGetDiskErrors(virDomainPtr dom,
 
4729
                          virDomainDiskErrorPtr errors,
 
4730
                          unsigned int maxerrors,
 
4731
                          unsigned int flags)
 
4732
{
 
4733
    int rv = -1;
 
4734
    struct private_data *priv = dom->conn->privateData;
 
4735
    remote_domain_get_disk_errors_args args;
 
4736
    remote_domain_get_disk_errors_ret ret;
 
4737
 
 
4738
    remoteDriverLock(priv);
 
4739
 
 
4740
    make_nonnull_domain(&args.dom, dom);
 
4741
    args.maxerrors = maxerrors;
 
4742
    args.flags = flags;
 
4743
 
 
4744
    memset(&ret, 0, sizeof(ret));
 
4745
 
 
4746
    if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_DISK_ERRORS,
 
4747
             (xdrproc_t) xdr_remote_domain_get_disk_errors_args,
 
4748
             (char *) &args,
 
4749
             (xdrproc_t) xdr_remote_domain_get_disk_errors_ret,
 
4750
             (char *) &ret) == -1)
 
4751
        goto done;
 
4752
 
 
4753
    if (remoteDeserializeDomainDiskErrors(ret.errors.errors_val,
 
4754
                                          ret.errors.errors_len,
 
4755
                                          REMOTE_DOMAIN_DISK_ERRORS_MAX,
 
4756
                                          errors,
 
4757
                                          maxerrors) < 0)
 
4758
        goto cleanup;
 
4759
 
 
4760
    rv = ret.nerrors;
 
4761
 
 
4762
cleanup:
 
4763
    xdr_free((xdrproc_t) xdr_remote_domain_get_disk_errors_ret, (char *) &ret);
 
4764
 
 
4765
done:
 
4766
    remoteDriverUnlock(priv);
 
4767
    return rv;
 
4768
}
 
4769
 
 
4770
#include "remote_client_bodies.h"
 
4771
#include "qemu_client_bodies.h"
 
4772
 
 
4773
/*
 
4774
 * Serial a set of arguments into a method call message,
 
4775
 * send that to the server and wait for reply
 
4776
 */
 
4777
static int
 
4778
callWithFD(virConnectPtr conn ATTRIBUTE_UNUSED,
 
4779
           struct private_data *priv,
 
4780
           unsigned int flags,
 
4781
           int fd,
 
4782
           int proc_nr,
 
4783
           xdrproc_t args_filter, char *args,
 
4784
           xdrproc_t ret_filter, char *ret)
 
4785
{
 
4786
    int rv;
 
4787
    virNetClientProgramPtr prog = flags & REMOTE_CALL_QEMU ? priv->qemuProgram : priv->remoteProgram;
 
4788
    int counter = priv->counter++;
 
4789
    virNetClientPtr client = priv->client;
 
4790
    int fds[] = { fd };
 
4791
    size_t nfds = fd == -1 ? 0 : 1;
 
4792
    priv->localUses++;
 
4793
 
 
4794
    /* Unlock, so that if we get any async events/stream data
 
4795
     * while processing the RPC, we don't deadlock when our
 
4796
     * callbacks for those are invoked
 
4797
     */
 
4798
    remoteDriverUnlock(priv);
 
4799
    rv = virNetClientProgramCall(prog,
 
4800
                                 client,
 
4801
                                 counter,
 
4802
                                 proc_nr,
 
4803
                                 nfds, nfds ? fds : NULL, NULL, NULL,
 
4804
                                 args_filter, args,
 
4805
                                 ret_filter, ret);
 
4806
    remoteDriverLock(priv);
 
4807
    priv->localUses--;
 
4808
 
 
4809
    return rv;
 
4810
}
 
4811
 
 
4812
static int
 
4813
call (virConnectPtr conn,
 
4814
      struct private_data *priv,
 
4815
      unsigned int flags,
 
4816
      int proc_nr,
 
4817
      xdrproc_t args_filter, char *args,
 
4818
      xdrproc_t ret_filter, char *ret)
 
4819
{
 
4820
    return callWithFD(conn, priv, flags, -1, proc_nr,
 
4821
                      args_filter, args,
 
4822
                      ret_filter, ret);
 
4823
}
 
4824
 
 
4825
 
 
4826
static int
 
4827
remoteDomainGetInterfaceParameters (virDomainPtr domain,
 
4828
                                    const char *device,
 
4829
                                    virTypedParameterPtr params, int *nparams,
 
4830
                                    unsigned int flags)
 
4831
{
 
4832
    int rv = -1;
 
4833
    remote_domain_get_interface_parameters_args args;
 
4834
    remote_domain_get_interface_parameters_ret ret;
 
4835
    struct private_data *priv = domain->conn->privateData;
 
4836
 
 
4837
    remoteDriverLock(priv);
 
4838
 
 
4839
    make_nonnull_domain (&args.dom, domain);
 
4840
    args.device = (char *)device;
 
4841
    args.nparams = *nparams;
 
4842
    args.flags = flags;
 
4843
 
 
4844
    memset (&ret, 0, sizeof(ret));
 
4845
    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS,
 
4846
              (xdrproc_t) xdr_remote_domain_get_interface_parameters_args, (char *) &args,
 
4847
              (xdrproc_t) xdr_remote_domain_get_interface_parameters_ret, (char *) &ret) == -1)
 
4848
        goto done;
 
4849
 
 
4850
    /* Handle the case when the caller does not know the number of parameters
 
4851
     * and is asking for the number of parameters supported
 
4852
     */
 
4853
    if (*nparams == 0) {
 
4854
        *nparams = ret.nparams;
 
4855
        rv = 0;
 
4856
        goto cleanup;
 
4857
    }
 
4858
 
 
4859
    if (remoteDeserializeTypedParameters(ret.params.params_val,
 
4860
                                         ret.params.params_len,
 
4861
                                         REMOTE_DOMAIN_INTERFACE_PARAMETERS_MAX,
 
4862
                                         params,
 
4863
                                         nparams) < 0)
 
4864
        goto cleanup;
 
4865
 
 
4866
    rv = 0;
 
4867
 
 
4868
cleanup:
 
4869
    xdr_free ((xdrproc_t) xdr_remote_domain_get_interface_parameters_ret,
 
4870
              (char *) &ret);
 
4871
done:
 
4872
    remoteDriverUnlock(priv);
 
4873
    return rv;
 
4874
}
 
4875
 
 
4876
static int
 
4877
remoteDomainListAllSnapshots(virDomainPtr dom,
 
4878
                             virDomainSnapshotPtr **snapshots,
 
4879
                             unsigned int flags)
 
4880
{
 
4881
    int rv = -1;
 
4882
    int i;
 
4883
    virDomainSnapshotPtr *snaps = NULL;
 
4884
    remote_domain_list_all_snapshots_args args;
 
4885
    remote_domain_list_all_snapshots_ret ret;
 
4886
 
 
4887
    struct private_data *priv = dom->conn->privateData;
 
4888
 
 
4889
    remoteDriverLock(priv);
 
4890
 
 
4891
    args.need_results = !!snapshots;
 
4892
    args.flags = flags;
 
4893
 
 
4894
    memset(&ret, 0, sizeof(ret));
 
4895
    if (call (dom->conn,
 
4896
              priv,
 
4897
              0,
 
4898
              REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS,
 
4899
              (xdrproc_t) xdr_remote_domain_list_all_snapshots_args,
 
4900
              (char *) &args,
 
4901
              (xdrproc_t) xdr_remote_domain_list_all_snapshots_ret,
 
4902
              (char *) &ret) == -1)
 
4903
        goto done;
 
4904
 
 
4905
    if (snapshots) {
 
4906
        if (VIR_ALLOC_N(snaps, ret.snapshots.snapshots_len + 1) < 0) {
 
4907
            virReportOOMError();
 
4908
            goto cleanup;
 
4909
        }
 
4910
        for (i = 0; i < ret.snapshots.snapshots_len; i++) {
 
4911
            snaps[i] = get_nonnull_domain_snapshot(dom, ret.snapshots.snapshots_val[i]);
 
4912
            if (!snaps[i]) {
 
4913
                virReportOOMError();
 
4914
                goto cleanup;
 
4915
            }
 
4916
        }
 
4917
        *snapshots = snaps;
 
4918
        snaps = NULL;
 
4919
    }
 
4920
 
 
4921
    rv = ret.ret;
 
4922
 
 
4923
cleanup:
 
4924
    if (snaps) {
 
4925
        for (i = 0; i < ret.snapshots.snapshots_len; i++)
 
4926
            if (snaps[i])
 
4927
                virDomainSnapshotFree(snaps[i]);
 
4928
        VIR_FREE(snaps);
 
4929
    }
 
4930
 
 
4931
    xdr_free((xdrproc_t) xdr_remote_domain_list_all_snapshots_ret, (char *) &ret);
 
4932
 
 
4933
done:
 
4934
    remoteDriverUnlock(priv);
 
4935
    return rv;
 
4936
}
 
4937
 
 
4938
static int
 
4939
remoteDomainSnapshotListAllChildren(virDomainSnapshotPtr parent,
 
4940
                                    virDomainSnapshotPtr **snapshots,
 
4941
                                    unsigned int flags)
 
4942
{
 
4943
    int rv = -1;
 
4944
    int i;
 
4945
    virDomainSnapshotPtr *snaps = NULL;
 
4946
    remote_domain_snapshot_list_all_children_args args;
 
4947
    remote_domain_snapshot_list_all_children_ret ret;
 
4948
 
 
4949
    struct private_data *priv = parent->domain->conn->privateData;
 
4950
 
 
4951
    remoteDriverLock(priv);
 
4952
 
 
4953
    args.need_results = !!snapshots;
 
4954
    args.flags = flags;
 
4955
 
 
4956
    memset(&ret, 0, sizeof(ret));
 
4957
    if (call (parent->domain->conn,
 
4958
              priv,
 
4959
              0,
 
4960
              REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN,
 
4961
              (xdrproc_t) xdr_remote_domain_snapshot_list_all_children_args,
 
4962
              (char *) &args,
 
4963
              (xdrproc_t) xdr_remote_domain_snapshot_list_all_children_ret,
 
4964
              (char *) &ret) == -1)
 
4965
        goto done;
 
4966
 
 
4967
    if (snapshots) {
 
4968
        if (VIR_ALLOC_N(snaps, ret.snapshots.snapshots_len + 1) < 0) {
 
4969
            virReportOOMError();
 
4970
            goto cleanup;
 
4971
        }
 
4972
        for (i = 0; i < ret.snapshots.snapshots_len; i++) {
 
4973
            snaps[i] = get_nonnull_domain_snapshot(parent->domain, ret.snapshots.snapshots_val[i]);
 
4974
            if (!snaps[i]) {
 
4975
                virReportOOMError();
 
4976
                goto cleanup;
 
4977
            }
 
4978
        }
 
4979
        *snapshots = snaps;
 
4980
        snaps = NULL;
 
4981
    }
 
4982
 
 
4983
    rv = ret.ret;
 
4984
 
 
4985
cleanup:
 
4986
    if (snaps) {
 
4987
        for (i = 0; i < ret.snapshots.snapshots_len; i++)
 
4988
            if (snaps[i])
 
4989
                virDomainSnapshotFree(snaps[i]);
 
4990
        VIR_FREE(snaps);
 
4991
    }
 
4992
 
 
4993
    xdr_free((xdrproc_t) xdr_remote_domain_snapshot_list_all_children_ret, (char *) &ret);
 
4994
 
 
4995
done:
 
4996
    remoteDriverUnlock(priv);
 
4997
    return rv;
 
4998
}
 
4999
 
 
5000
static void
 
5001
remoteDomainEventQueue(struct private_data *priv, virDomainEventPtr event)
 
5002
{
 
5003
    virDomainEventStateQueue(priv->domainEventState, event);
 
5004
}
 
5005
 
 
5006
/* get_nonnull_domain and get_nonnull_network turn an on-wire
 
5007
 * (name, uuid) pair into virDomainPtr or virNetworkPtr object.
 
5008
 * These can return NULL if underlying memory allocations fail,
 
5009
 * but if they do then virterror_internal.has been set.
 
5010
 */
 
5011
static virDomainPtr
 
5012
get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain)
 
5013
{
 
5014
    virDomainPtr dom;
 
5015
    dom = virGetDomain (conn, domain.name, BAD_CAST domain.uuid);
 
5016
    if (dom) dom->id = domain.id;
 
5017
    return dom;
 
5018
}
 
5019
 
 
5020
static virNetworkPtr
 
5021
get_nonnull_network (virConnectPtr conn, remote_nonnull_network network)
 
5022
{
 
5023
    return virGetNetwork (conn, network.name, BAD_CAST network.uuid);
 
5024
}
 
5025
 
 
5026
static virInterfacePtr
 
5027
get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface iface)
 
5028
{
 
5029
    return virGetInterface (conn, iface.name, iface.mac);
 
5030
}
 
5031
 
 
5032
static virStoragePoolPtr
 
5033
get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool)
 
5034
{
 
5035
    return virGetStoragePool (conn, pool.name, BAD_CAST pool.uuid);
 
5036
}
 
5037
 
 
5038
static virStorageVolPtr
 
5039
get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol)
 
5040
{
 
5041
    return virGetStorageVol (conn, vol.pool, vol.name, vol.key);
 
5042
}
 
5043
 
 
5044
static virNodeDevicePtr
 
5045
get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev)
 
5046
{
 
5047
    return virGetNodeDevice(conn, dev.name);
 
5048
}
 
5049
 
 
5050
static virSecretPtr
 
5051
get_nonnull_secret (virConnectPtr conn, remote_nonnull_secret secret)
 
5052
{
 
5053
    return virGetSecret(conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
 
5054
}
 
5055
 
 
5056
static virNWFilterPtr
 
5057
get_nonnull_nwfilter (virConnectPtr conn, remote_nonnull_nwfilter nwfilter)
 
5058
{
 
5059
    return virGetNWFilter (conn, nwfilter.name, BAD_CAST nwfilter.uuid);
 
5060
}
 
5061
 
 
5062
static virDomainSnapshotPtr
 
5063
get_nonnull_domain_snapshot (virDomainPtr domain, remote_nonnull_domain_snapshot snapshot)
 
5064
{
 
5065
    return virGetDomainSnapshot(domain, snapshot.name);
 
5066
}
 
5067
 
 
5068
 
 
5069
/* Make remote_nonnull_domain and remote_nonnull_network. */
 
5070
static void
 
5071
make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
 
5072
{
 
5073
    dom_dst->id = dom_src->id;
 
5074
    dom_dst->name = dom_src->name;
 
5075
    memcpy (dom_dst->uuid, dom_src->uuid, VIR_UUID_BUFLEN);
 
5076
}
 
5077
 
 
5078
static void
 
5079
make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src)
 
5080
{
 
5081
    net_dst->name = net_src->name;
 
5082
    memcpy (net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN);
 
5083
}
 
5084
 
 
5085
static void
 
5086
make_nonnull_interface (remote_nonnull_interface *interface_dst,
 
5087
                        virInterfacePtr interface_src)
 
5088
{
 
5089
    interface_dst->name = interface_src->name;
 
5090
    interface_dst->mac = interface_src->mac;
 
5091
}
 
5092
 
 
5093
static void
 
5094
make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
 
5095
{
 
5096
    pool_dst->name = pool_src->name;
 
5097
    memcpy (pool_dst->uuid, pool_src->uuid, VIR_UUID_BUFLEN);
 
5098
}
 
5099
 
 
5100
static void
 
5101
make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src)
 
5102
{
 
5103
    vol_dst->pool = vol_src->pool;
 
5104
    vol_dst->name = vol_src->name;
 
5105
    vol_dst->key = vol_src->key;
 
5106
}
 
5107
 
 
5108
static void
 
5109
make_nonnull_secret (remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
 
5110
{
 
5111
    memcpy (secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
 
5112
    secret_dst->usageType = secret_src->usageType;
 
5113
    secret_dst->usageID = secret_src->usageID;
 
5114
}
 
5115
 
 
5116
static void
 
5117
make_nonnull_nwfilter (remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src)
 
5118
{
 
5119
    nwfilter_dst->name = nwfilter_src->name;
 
5120
    memcpy (nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
 
5121
}
 
5122
 
 
5123
static void
 
5124
make_nonnull_domain_snapshot (remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src)
 
5125
{
 
5126
    snapshot_dst->name = snapshot_src->name;
 
5127
    make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain);
 
5128
}
 
5129
 
 
5130
/*----------------------------------------------------------------------*/
 
5131
 
 
5132
unsigned long remoteVersion(void)
 
5133
{
 
5134
    return REMOTE_PROTOCOL_VERSION;
 
5135
}
 
5136
 
 
5137
static virDriver remote_driver = {
 
5138
    .no = VIR_DRV_REMOTE,
 
5139
    .name = "remote",
 
5140
    .open = remoteOpen, /* 0.3.0 */
 
5141
    .close = remoteClose, /* 0.3.0 */
 
5142
    .supports_feature = remoteSupportsFeature, /* 0.3.0 */
 
5143
    .type = remoteType, /* 0.3.0 */
 
5144
    .version = remoteGetVersion, /* 0.3.0 */
 
5145
    .libvirtVersion = remoteGetLibVersion, /* 0.7.3 */
 
5146
    .getHostname = remoteGetHostname, /* 0.3.0 */
 
5147
    .getSysinfo = remoteGetSysinfo, /* 0.8.8 */
 
5148
    .getMaxVcpus = remoteGetMaxVcpus, /* 0.3.0 */
 
5149
    .nodeGetInfo = remoteNodeGetInfo, /* 0.3.0 */
 
5150
    .getCapabilities = remoteGetCapabilities, /* 0.3.0 */
 
5151
    .listDomains = remoteListDomains, /* 0.3.0 */
 
5152
    .numOfDomains = remoteNumOfDomains, /* 0.3.0 */
 
5153
    .listAllDomains = remoteConnectListAllDomains, /* 0.9.13 */
 
5154
    .domainCreateXML = remoteDomainCreateXML, /* 0.3.0 */
 
5155
    .domainLookupByID = remoteDomainLookupByID, /* 0.3.0 */
 
5156
    .domainLookupByUUID = remoteDomainLookupByUUID, /* 0.3.0 */
 
5157
    .domainLookupByName = remoteDomainLookupByName, /* 0.3.0 */
 
5158
    .domainSuspend = remoteDomainSuspend, /* 0.3.0 */
 
5159
    .domainResume = remoteDomainResume, /* 0.3.0 */
 
5160
    .domainPMSuspendForDuration = remoteDomainPMSuspendForDuration, /* 0.9.10 */
 
5161
    .domainPMWakeup = remoteDomainPMWakeup, /* 0.9.11 */
 
5162
    .domainShutdown = remoteDomainShutdown, /* 0.3.0 */
 
5163
    .domainShutdownFlags = remoteDomainShutdownFlags, /* 0.9.10 */
 
5164
    .domainReboot = remoteDomainReboot, /* 0.3.0 */
 
5165
    .domainReset = remoteDomainReset, /* 0.9.7 */
 
5166
    .domainDestroy = remoteDomainDestroy, /* 0.3.0 */
 
5167
    .domainDestroyFlags = remoteDomainDestroyFlags, /* 0.9.4 */
 
5168
    .domainGetOSType = remoteDomainGetOSType, /* 0.3.0 */
 
5169
    .domainGetMaxMemory = remoteDomainGetMaxMemory, /* 0.3.0 */
 
5170
    .domainSetMaxMemory = remoteDomainSetMaxMemory, /* 0.3.0 */
 
5171
    .domainSetMemory = remoteDomainSetMemory, /* 0.3.0 */
 
5172
    .domainSetMemoryFlags = remoteDomainSetMemoryFlags, /* 0.9.0 */
 
5173
    .domainSetMemoryParameters = remoteDomainSetMemoryParameters, /* 0.8.5 */
 
5174
    .domainGetMemoryParameters = remoteDomainGetMemoryParameters, /* 0.8.5 */
 
5175
    .domainSetBlkioParameters = remoteDomainSetBlkioParameters, /* 0.9.0 */
 
5176
    .domainGetBlkioParameters = remoteDomainGetBlkioParameters, /* 0.9.0 */
 
5177
    .domainGetInfo = remoteDomainGetInfo, /* 0.3.0 */
 
5178
    .domainGetState = remoteDomainGetState, /* 0.9.2 */
 
5179
    .domainGetControlInfo = remoteDomainGetControlInfo, /* 0.9.3 */
 
5180
    .domainSave = remoteDomainSave, /* 0.3.0 */
 
5181
    .domainSaveFlags = remoteDomainSaveFlags, /* 0.9.4 */
 
5182
    .domainRestore = remoteDomainRestore, /* 0.3.0 */
 
5183
    .domainRestoreFlags = remoteDomainRestoreFlags, /* 0.9.4 */
 
5184
    .domainSaveImageGetXMLDesc = remoteDomainSaveImageGetXMLDesc, /* 0.9.4 */
 
5185
    .domainSaveImageDefineXML = remoteDomainSaveImageDefineXML, /* 0.9.4 */
 
5186
    .domainCoreDump = remoteDomainCoreDump, /* 0.3.0 */
 
5187
    .domainScreenshot = remoteDomainScreenshot, /* 0.9.2 */
 
5188
    .domainSetVcpus = remoteDomainSetVcpus, /* 0.3.0 */
 
5189
    .domainSetVcpusFlags = remoteDomainSetVcpusFlags, /* 0.8.5 */
 
5190
    .domainGetVcpusFlags = remoteDomainGetVcpusFlags, /* 0.8.5 */
 
5191
    .domainPinVcpu = remoteDomainPinVcpu, /* 0.3.0 */
 
5192
    .domainPinVcpuFlags = remoteDomainPinVcpuFlags, /* 0.9.3 */
 
5193
    .domainGetVcpuPinInfo = remoteDomainGetVcpuPinInfo, /* 0.9.3 */
 
5194
    .domainGetVcpus = remoteDomainGetVcpus, /* 0.3.0 */
 
5195
    .domainGetMaxVcpus = remoteDomainGetMaxVcpus, /* 0.3.0 */
 
5196
    .domainGetSecurityLabel = remoteDomainGetSecurityLabel, /* 0.6.1 */
 
5197
    .nodeGetSecurityModel = remoteNodeGetSecurityModel, /* 0.6.1 */
 
5198
    .domainGetXMLDesc = remoteDomainGetXMLDesc, /* 0.3.0 */
 
5199
    .domainXMLFromNative = remoteDomainXMLFromNative, /* 0.6.4 */
 
5200
    .domainXMLToNative = remoteDomainXMLToNative, /* 0.6.4 */
 
5201
    .listDefinedDomains = remoteListDefinedDomains, /* 0.3.0 */
 
5202
    .numOfDefinedDomains = remoteNumOfDefinedDomains, /* 0.3.0 */
 
5203
    .domainCreate = remoteDomainCreate, /* 0.3.0 */
 
5204
    .domainCreateWithFlags = remoteDomainCreateWithFlags, /* 0.8.2 */
 
5205
    .domainDefineXML = remoteDomainDefineXML, /* 0.3.0 */
 
5206
    .domainUndefine = remoteDomainUndefine, /* 0.3.0 */
 
5207
    .domainUndefineFlags = remoteDomainUndefineFlags, /* 0.9.4 */
 
5208
    .domainAttachDevice = remoteDomainAttachDevice, /* 0.3.0 */
 
5209
    .domainAttachDeviceFlags = remoteDomainAttachDeviceFlags, /* 0.7.7 */
 
5210
    .domainDetachDevice = remoteDomainDetachDevice, /* 0.3.0 */
 
5211
    .domainDetachDeviceFlags = remoteDomainDetachDeviceFlags, /* 0.7.7 */
 
5212
    .domainUpdateDeviceFlags = remoteDomainUpdateDeviceFlags, /* 0.8.0 */
 
5213
    .domainGetAutostart = remoteDomainGetAutostart, /* 0.3.0 */
 
5214
    .domainSetAutostart = remoteDomainSetAutostart, /* 0.3.0 */
 
5215
    .domainGetSchedulerType = remoteDomainGetSchedulerType, /* 0.3.0 */
 
5216
    .domainGetSchedulerParameters = remoteDomainGetSchedulerParameters, /* 0.3.0 */
 
5217
    .domainGetSchedulerParametersFlags = remoteDomainGetSchedulerParametersFlags, /* 0.9.2 */
 
5218
    .domainSetSchedulerParameters = remoteDomainSetSchedulerParameters, /* 0.3.0 */
 
5219
    .domainSetSchedulerParametersFlags = remoteDomainSetSchedulerParametersFlags, /* 0.9.2 */
 
5220
    .domainMigratePrepare = remoteDomainMigratePrepare, /* 0.3.2 */
 
5221
    .domainMigratePerform = remoteDomainMigratePerform, /* 0.3.2 */
 
5222
    .domainMigrateFinish = remoteDomainMigrateFinish, /* 0.3.2 */
 
5223
    .domainBlockResize = remoteDomainBlockResize, /* 0.9.8 */
 
5224
    .domainBlockStats = remoteDomainBlockStats, /* 0.3.2 */
 
5225
    .domainBlockStatsFlags = remoteDomainBlockStatsFlags, /* 0.9.5 */
 
5226
    .domainInterfaceStats = remoteDomainInterfaceStats, /* 0.3.2 */
 
5227
    .domainSetInterfaceParameters = remoteDomainSetInterfaceParameters, /* 0.9.9 */
 
5228
    .domainGetInterfaceParameters = remoteDomainGetInterfaceParameters, /* 0.9.9 */
 
5229
    .domainMemoryStats = remoteDomainMemoryStats, /* 0.7.5 */
 
5230
    .domainBlockPeek = remoteDomainBlockPeek, /* 0.4.2 */
 
5231
    .domainMemoryPeek = remoteDomainMemoryPeek, /* 0.4.2 */
 
5232
    .domainGetBlockInfo = remoteDomainGetBlockInfo, /* 0.8.1 */
 
5233
    .nodeGetCPUStats = remoteNodeGetCPUStats, /* 0.9.3 */
 
5234
    .nodeGetMemoryStats = remoteNodeGetMemoryStats, /* 0.9.3 */
 
5235
    .nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory, /* 0.3.3 */
 
5236
    .nodeGetFreeMemory = remoteNodeGetFreeMemory, /* 0.3.3 */
 
5237
    .domainEventRegister = remoteDomainEventRegister, /* 0.5.0 */
 
5238
    .domainEventDeregister = remoteDomainEventDeregister, /* 0.5.0 */
 
5239
    .domainMigratePrepare2 = remoteDomainMigratePrepare2, /* 0.5.0 */
 
5240
    .domainMigrateFinish2 = remoteDomainMigrateFinish2, /* 0.5.0 */
 
5241
    .nodeDeviceDettach = remoteNodeDeviceDettach, /* 0.6.1 */
 
5242
    .nodeDeviceReAttach = remoteNodeDeviceReAttach, /* 0.6.1 */
 
5243
    .nodeDeviceReset = remoteNodeDeviceReset, /* 0.6.1 */
 
5244
    .domainMigratePrepareTunnel = remoteDomainMigratePrepareTunnel, /* 0.7.2 */
 
5245
    .isEncrypted = remoteIsEncrypted, /* 0.7.3 */
 
5246
    .isSecure = remoteIsSecure, /* 0.7.3 */
 
5247
    .domainIsActive = remoteDomainIsActive, /* 0.7.3 */
 
5248
    .domainIsPersistent = remoteDomainIsPersistent, /* 0.7.3 */
 
5249
    .domainIsUpdated = remoteDomainIsUpdated, /* 0.8.6 */
 
5250
    .cpuCompare = remoteCPUCompare, /* 0.7.5 */
 
5251
    .cpuBaseline = remoteCPUBaseline, /* 0.7.7 */
 
5252
    .domainGetJobInfo = remoteDomainGetJobInfo, /* 0.7.7 */
 
5253
    .domainAbortJob = remoteDomainAbortJob, /* 0.7.7 */
 
5254
    .domainMigrateSetMaxDowntime = remoteDomainMigrateSetMaxDowntime, /* 0.8.0 */
 
5255
    .domainMigrateSetMaxSpeed = remoteDomainMigrateSetMaxSpeed, /* 0.9.0 */
 
5256
    .domainMigrateGetMaxSpeed = remoteDomainMigrateGetMaxSpeed, /* 0.9.5 */
 
5257
    .domainEventRegisterAny = remoteDomainEventRegisterAny, /* 0.8.0 */
 
5258
    .domainEventDeregisterAny = remoteDomainEventDeregisterAny, /* 0.8.0 */
 
5259
    .domainManagedSave = remoteDomainManagedSave, /* 0.8.0 */
 
5260
    .domainHasManagedSaveImage = remoteDomainHasManagedSaveImage, /* 0.8.0 */
 
5261
    .domainManagedSaveRemove = remoteDomainManagedSaveRemove, /* 0.8.0 */
 
5262
    .domainSnapshotCreateXML = remoteDomainSnapshotCreateXML, /* 0.8.0 */
 
5263
    .domainSnapshotGetXMLDesc = remoteDomainSnapshotGetXMLDesc, /* 0.8.0 */
 
5264
    .domainSnapshotNum = remoteDomainSnapshotNum, /* 0.8.0 */
 
5265
    .domainSnapshotListNames = remoteDomainSnapshotListNames, /* 0.8.0 */
 
5266
    .domainListAllSnapshots = remoteDomainListAllSnapshots, /* 0.9.13 */
 
5267
    .domainSnapshotNumChildren = remoteDomainSnapshotNumChildren, /* 0.9.7 */
 
5268
    .domainSnapshotListAllChildren = remoteDomainSnapshotListAllChildren, /* 0.9.13 */
 
5269
    .domainSnapshotListChildrenNames = remoteDomainSnapshotListChildrenNames, /* 0.9.7 */
 
5270
    .domainSnapshotLookupByName = remoteDomainSnapshotLookupByName, /* 0.8.0 */
 
5271
    .domainHasCurrentSnapshot = remoteDomainHasCurrentSnapshot, /* 0.8.0 */
 
5272
    .domainSnapshotGetParent = remoteDomainSnapshotGetParent, /* 0.9.7 */
 
5273
    .domainSnapshotCurrent = remoteDomainSnapshotCurrent, /* 0.8.0 */
 
5274
    .domainRevertToSnapshot = remoteDomainRevertToSnapshot, /* 0.8.0 */
 
5275
    .domainSnapshotIsCurrent = remoteDomainSnapshotIsCurrent, /* 0.9.13 */
 
5276
    .domainSnapshotHasMetadata = remoteDomainSnapshotHasMetadata, /* 0.9.13 */
 
5277
    .domainSnapshotDelete = remoteDomainSnapshotDelete, /* 0.8.0 */
 
5278
    .qemuDomainMonitorCommand = remoteQemuDomainMonitorCommand, /* 0.8.3 */
 
5279
    .qemuDomainAttach = qemuDomainAttach, /* 0.9.4 */
 
5280
    .domainOpenConsole = remoteDomainOpenConsole, /* 0.8.6 */
 
5281
    .domainOpenGraphics = remoteDomainOpenGraphics, /* 0.9.7 */
 
5282
    .domainInjectNMI = remoteDomainInjectNMI, /* 0.9.2 */
 
5283
    .domainMigrateBegin3 = remoteDomainMigrateBegin3, /* 0.9.2 */
 
5284
    .domainMigratePrepare3 = remoteDomainMigratePrepare3, /* 0.9.2 */
 
5285
    .domainMigratePrepareTunnel3 = remoteDomainMigratePrepareTunnel3, /* 0.9.2 */
 
5286
    .domainMigratePerform3 = remoteDomainMigratePerform3, /* 0.9.2 */
 
5287
    .domainMigrateFinish3 = remoteDomainMigrateFinish3, /* 0.9.2 */
 
5288
    .domainMigrateConfirm3 = remoteDomainMigrateConfirm3, /* 0.9.2 */
 
5289
    .domainSendKey = remoteDomainSendKey, /* 0.9.3 */
 
5290
    .domainBlockJobAbort = remoteDomainBlockJobAbort, /* 0.9.4 */
 
5291
    .domainGetBlockJobInfo = remoteDomainGetBlockJobInfo, /* 0.9.4 */
 
5292
    .domainBlockJobSetSpeed = remoteDomainBlockJobSetSpeed, /* 0.9.4 */
 
5293
    .domainBlockPull = remoteDomainBlockPull, /* 0.9.4 */
 
5294
    .domainBlockRebase = remoteDomainBlockRebase, /* 0.9.10 */
 
5295
    .setKeepAlive = remoteSetKeepAlive, /* 0.9.8 */
 
5296
    .isAlive = remoteIsAlive, /* 0.9.8 */
 
5297
    .nodeSuspendForDuration = remoteNodeSuspendForDuration, /* 0.9.8 */
 
5298
    .domainSetBlockIoTune = remoteDomainSetBlockIoTune, /* 0.9.8 */
 
5299
    .domainGetBlockIoTune = remoteDomainGetBlockIoTune, /* 0.9.8 */
 
5300
    .domainSetNumaParameters = remoteDomainSetNumaParameters, /* 0.9.9 */
 
5301
    .domainGetNumaParameters = remoteDomainGetNumaParameters, /* 0.9.9 */
 
5302
    .domainGetCPUStats = remoteDomainGetCPUStats, /* 0.9.10 */
 
5303
    .domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */
 
5304
    .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */
 
5305
    .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */
 
5306
};
 
5307
 
 
5308
static virNetworkDriver network_driver = {
 
5309
    .name = "remote",
 
5310
    .open = remoteNetworkOpen, /* 0.3.0 */
 
5311
    .close = remoteNetworkClose, /* 0.3.0 */
 
5312
    .numOfNetworks = remoteNumOfNetworks, /* 0.3.0 */
 
5313
    .listNetworks = remoteListNetworks, /* 0.3.0 */
 
5314
    .numOfDefinedNetworks = remoteNumOfDefinedNetworks, /* 0.3.0 */
 
5315
    .listDefinedNetworks = remoteListDefinedNetworks, /* 0.3.0 */
 
5316
    .networkLookupByUUID = remoteNetworkLookupByUUID, /* 0.3.0 */
 
5317
    .networkLookupByName = remoteNetworkLookupByName, /* 0.3.0 */
 
5318
    .networkCreateXML = remoteNetworkCreateXML, /* 0.3.0 */
 
5319
    .networkDefineXML = remoteNetworkDefineXML, /* 0.3.0 */
 
5320
    .networkUndefine = remoteNetworkUndefine, /* 0.3.0 */
 
5321
    .networkCreate = remoteNetworkCreate, /* 0.3.0 */
 
5322
    .networkDestroy = remoteNetworkDestroy, /* 0.3.0 */
 
5323
    .networkGetXMLDesc = remoteNetworkGetXMLDesc, /* 0.3.0 */
 
5324
    .networkGetBridgeName = remoteNetworkGetBridgeName, /* 0.3.0 */
 
5325
    .networkGetAutostart = remoteNetworkGetAutostart, /* 0.3.0 */
 
5326
    .networkSetAutostart = remoteNetworkSetAutostart, /* 0.3.0 */
 
5327
    .networkIsActive = remoteNetworkIsActive, /* 0.7.3 */
 
5328
    .networkIsPersistent = remoteNetworkIsPersistent, /* 0.7.3 */
 
5329
};
 
5330
 
 
5331
static virInterfaceDriver interface_driver = {
 
5332
    .name = "remote",
 
5333
    .open = remoteInterfaceOpen, /* 0.7.2 */
 
5334
    .close = remoteInterfaceClose, /* 0.7.2 */
 
5335
    .numOfInterfaces = remoteNumOfInterfaces, /* 0.7.2 */
 
5336
    .listInterfaces = remoteListInterfaces, /* 0.7.2 */
 
5337
    .numOfDefinedInterfaces = remoteNumOfDefinedInterfaces, /* 0.7.2 */
 
5338
    .listDefinedInterfaces = remoteListDefinedInterfaces, /* 0.7.2 */
 
5339
    .interfaceLookupByName = remoteInterfaceLookupByName, /* 0.7.2 */
 
5340
    .interfaceLookupByMACString = remoteInterfaceLookupByMACString, /* 0.7.2 */
 
5341
    .interfaceGetXMLDesc = remoteInterfaceGetXMLDesc, /* 0.7.2 */
 
5342
    .interfaceDefineXML = remoteInterfaceDefineXML, /* 0.7.2 */
 
5343
    .interfaceUndefine = remoteInterfaceUndefine, /* 0.7.2 */
 
5344
    .interfaceCreate = remoteInterfaceCreate, /* 0.7.2 */
 
5345
    .interfaceDestroy = remoteInterfaceDestroy, /* 0.7.2 */
 
5346
    .interfaceIsActive = remoteInterfaceIsActive, /* 0.7.3 */
 
5347
    .interfaceChangeBegin = remoteInterfaceChangeBegin, /* 0.9.2 */
 
5348
    .interfaceChangeCommit = remoteInterfaceChangeCommit, /* 0.9.2 */
 
5349
    .interfaceChangeRollback = remoteInterfaceChangeRollback, /* 0.9.2 */
 
5350
};
 
5351
 
 
5352
static virStorageDriver storage_driver = {
 
5353
    .name = "remote",
 
5354
    .open = remoteStorageOpen, /* 0.4.1 */
 
5355
    .close = remoteStorageClose, /* 0.4.1 */
 
5356
    .numOfPools = remoteNumOfStoragePools, /* 0.4.1 */
 
5357
    .listPools = remoteListStoragePools, /* 0.4.1 */
 
5358
    .numOfDefinedPools = remoteNumOfDefinedStoragePools, /* 0.4.1 */
 
5359
    .listDefinedPools = remoteListDefinedStoragePools, /* 0.4.1 */
 
5360
    .findPoolSources = remoteFindStoragePoolSources, /* 0.4.5 */
 
5361
    .poolLookupByName = remoteStoragePoolLookupByName, /* 0.4.1 */
 
5362
    .poolLookupByUUID = remoteStoragePoolLookupByUUID, /* 0.4.1 */
 
5363
    .poolLookupByVolume = remoteStoragePoolLookupByVolume, /* 0.4.1 */
 
5364
    .poolCreateXML = remoteStoragePoolCreateXML, /* 0.4.1 */
 
5365
    .poolDefineXML = remoteStoragePoolDefineXML, /* 0.4.1 */
 
5366
    .poolBuild = remoteStoragePoolBuild, /* 0.4.1 */
 
5367
    .poolUndefine = remoteStoragePoolUndefine, /* 0.4.1 */
 
5368
    .poolCreate = remoteStoragePoolCreate, /* 0.4.1 */
 
5369
    .poolDestroy = remoteStoragePoolDestroy, /* 0.4.1 */
 
5370
    .poolDelete = remoteStoragePoolDelete, /* 0.4.1 */
 
5371
    .poolRefresh = remoteStoragePoolRefresh, /* 0.4.1 */
 
5372
    .poolGetInfo = remoteStoragePoolGetInfo, /* 0.4.1 */
 
5373
    .poolGetXMLDesc = remoteStoragePoolGetXMLDesc, /* 0.4.1 */
 
5374
    .poolGetAutostart = remoteStoragePoolGetAutostart, /* 0.4.1 */
 
5375
    .poolSetAutostart = remoteStoragePoolSetAutostart, /* 0.4.1 */
 
5376
    .poolNumOfVolumes = remoteStoragePoolNumOfVolumes, /* 0.4.1 */
 
5377
    .poolListVolumes = remoteStoragePoolListVolumes, /* 0.4.1 */
 
5378
 
 
5379
    .volLookupByName = remoteStorageVolLookupByName, /* 0.4.1 */
 
5380
    .volLookupByKey = remoteStorageVolLookupByKey, /* 0.4.1 */
 
5381
    .volLookupByPath = remoteStorageVolLookupByPath, /* 0.4.1 */
 
5382
    .volCreateXML = remoteStorageVolCreateXML, /* 0.4.1 */
 
5383
    .volCreateXMLFrom = remoteStorageVolCreateXMLFrom, /* 0.6.4 */
 
5384
    .volDownload = remoteStorageVolDownload, /* 0.9.0 */
 
5385
    .volUpload = remoteStorageVolUpload, /* 0.9.0 */
 
5386
    .volDelete = remoteStorageVolDelete, /* 0.4.1 */
 
5387
    .volWipe = remoteStorageVolWipe, /* 0.8.0 */
 
5388
    .volWipePattern = remoteStorageVolWipePattern, /* 0.9.10 */
 
5389
    .volGetInfo = remoteStorageVolGetInfo, /* 0.4.1 */
 
5390
    .volGetXMLDesc = remoteStorageVolGetXMLDesc, /* 0.4.1 */
 
5391
    .volGetPath = remoteStorageVolGetPath, /* 0.4.1 */
 
5392
    .volResize = remoteStorageVolResize, /* 0.9.10 */
 
5393
    .poolIsActive = remoteStoragePoolIsActive, /* 0.7.3 */
 
5394
    .poolIsPersistent = remoteStoragePoolIsPersistent, /* 0.7.3 */
 
5395
};
 
5396
 
 
5397
static virSecretDriver secret_driver = {
 
5398
    .name = "remote",
 
5399
    .open = remoteSecretOpen, /* 0.7.1 */
 
5400
    .close = remoteSecretClose, /* 0.7.1 */
 
5401
    .numOfSecrets = remoteNumOfSecrets, /* 0.7.1 */
 
5402
    .listSecrets = remoteListSecrets, /* 0.7.1 */
 
5403
    .lookupByUUID = remoteSecretLookupByUUID, /* 0.7.1 */
 
5404
    .lookupByUsage = remoteSecretLookupByUsage, /* 0.7.1 */
 
5405
    .defineXML = remoteSecretDefineXML, /* 0.7.1 */
 
5406
    .getXMLDesc = remoteSecretGetXMLDesc, /* 0.7.1 */
 
5407
    .setValue = remoteSecretSetValue, /* 0.7.1 */
 
5408
    .getValue = remoteSecretGetValue, /* 0.7.1 */
 
5409
    .undefine = remoteSecretUndefine /* 0.7.1 */
 
5410
};
 
5411
 
 
5412
static virDeviceMonitor dev_monitor = {
 
5413
    .name = "remote",
 
5414
    .open = remoteDevMonOpen, /* 0.5.0 */
 
5415
    .close = remoteDevMonClose, /* 0.5.0 */
 
5416
    .numOfDevices = remoteNodeNumOfDevices, /* 0.5.0 */
 
5417
    .listDevices = remoteNodeListDevices, /* 0.5.0 */
 
5418
    .deviceLookupByName = remoteNodeDeviceLookupByName, /* 0.5.0 */
 
5419
    .deviceGetXMLDesc = remoteNodeDeviceGetXMLDesc, /* 0.5.0 */
 
5420
    .deviceGetParent = remoteNodeDeviceGetParent, /* 0.5.0 */
 
5421
    .deviceNumOfCaps = remoteNodeDeviceNumOfCaps, /* 0.5.0 */
 
5422
    .deviceListCaps = remoteNodeDeviceListCaps, /* 0.5.0 */
 
5423
    .deviceCreateXML = remoteNodeDeviceCreateXML, /* 0.6.3 */
 
5424
    .deviceDestroy = remoteNodeDeviceDestroy /* 0.6.3 */
 
5425
};
 
5426
 
 
5427
static virNWFilterDriver nwfilter_driver = {
 
5428
    .name = "remote",
 
5429
    .open = remoteNWFilterOpen, /* 0.8.0 */
 
5430
    .close = remoteNWFilterClose, /* 0.8.0 */
 
5431
    .nwfilterLookupByUUID = remoteNWFilterLookupByUUID, /* 0.8.0 */
 
5432
    .nwfilterLookupByName = remoteNWFilterLookupByName, /* 0.8.0 */
 
5433
    .getXMLDesc           = remoteNWFilterGetXMLDesc, /* 0.8.0 */
 
5434
    .defineXML            = remoteNWFilterDefineXML, /* 0.8.0 */
 
5435
    .undefine             = remoteNWFilterUndefine, /* 0.8.0 */
 
5436
    .numOfNWFilters       = remoteNumOfNWFilters, /* 0.8.0 */
 
5437
    .listNWFilters        = remoteListNWFilters, /* 0.8.0 */
 
5438
};
 
5439
 
 
5440
 
 
5441
#ifdef WITH_LIBVIRTD
 
5442
static virStateDriver state_driver = {
 
5443
    .name = "Remote",
 
5444
    .initialize = remoteStartup,
 
5445
};
 
5446
#endif
 
5447
 
 
5448
 
 
5449
/** remoteRegister:
 
5450
 *
 
5451
 * Register driver with libvirt driver system.
 
5452
 *
 
5453
 * Returns -1 on error.
 
5454
 */
 
5455
int
 
5456
remoteRegister (void)
 
5457
{
 
5458
    remoteDriver = &remote_driver;
 
5459
 
 
5460
    if (virRegisterDriver (&remote_driver) == -1) return -1;
 
5461
    if (virRegisterNetworkDriver (&network_driver) == -1) return -1;
 
5462
    if (virRegisterInterfaceDriver (&interface_driver) == -1) return -1;
 
5463
    if (virRegisterStorageDriver (&storage_driver) == -1) return -1;
 
5464
    if (virRegisterDeviceMonitor (&dev_monitor) == -1) return -1;
 
5465
    if (virRegisterSecretDriver (&secret_driver) == -1) return -1;
 
5466
    if (virRegisterNWFilterDriver(&nwfilter_driver) == -1) return -1;
 
5467
#ifdef WITH_LIBVIRTD
 
5468
    if (virRegisterStateDriver (&state_driver) == -1) return -1;
 
5469
#endif
 
5470
 
 
5471
    return 0;
 
5472
}