1 /*
2  * remote_driver.c: driver to provide access to libvirtd running
3  *   on a remote machine
4  *
5  * Copyright (C) 2007-2015 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, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 
24 #include <unistd.h>
25 
26 #include "virnetclient.h"
27 #include "virnetclientprogram.h"
28 #include "virnetclientstream.h"
29 #include "virerror.h"
30 #include "virlog.h"
31 #include "datatypes.h"
32 #include "domain_event.h"
33 #include "network_event.h"
34 #include "storage_event.h"
35 #include "node_device_event.h"
36 #include "secret_event.h"
37 #include "driver.h"
38 #include "virbuffer.h"
39 #include "remote_driver.h"
40 #include "remote_protocol.h"
41 #include "remote_sockets.h"
42 #include "lxc_protocol.h"
43 #include "qemu_protocol.h"
44 #include "viralloc.h"
45 #include "virfile.h"
46 #include "vircommand.h"
47 #include "virtypedparam.h"
48 #include "viruri.h"
49 #include "virauth.h"
50 #include "virauthconfig.h"
51 #include "virstring.h"
52 #include "virutil.h"
53 
54 #define VIR_FROM_THIS VIR_FROM_REMOTE
55 
56 VIR_LOG_INIT("remote.remote_driver");
57 
58 
59 #if SIZEOF_LONG < 8
60 # define HYPER_TO_TYPE(_type, _to, _from) \
61     do { \
62         if ((_from) != (_type)(_from)) { \
63             virReportError(VIR_ERR_INTERNAL_ERROR, \
64                            _("conversion from hyper to %s overflowed"), #_type); \
65             goto done; \
66         } \
67         (_to) = (_from); \
68     } while (0)
69 
70 # define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
71 # define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
72 #else
73 # define HYPER_TO_LONG(_to, _from) (_to) = (_from)
74 # define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
75 #endif
76 
77 static bool inside_daemon;
78 
79 struct private_data {
80     virMutex lock;
81 
82     virNetClient *client;
83     virNetClientProgram *remoteProgram;
84     virNetClientProgram *qemuProgram;
85     virNetClientProgram *lxcProgram;
86 
87     int counter; /* Serial number for RPC */
88 
89     virNetTLSContext *tls;
90 
91     int is_secure;              /* Secure if TLS or SASL or UNIX sockets */
92     char *type;                 /* Cached return from remoteType. */
93     int localUses;              /* Ref count for private data */
94     char *hostname;             /* Original hostname */
95     bool serverKeepAlive;       /* Does server support keepalive protocol? */
96     bool serverEventFilter;     /* Does server support modern event filtering */
97     bool serverCloseCallback;   /* Does server support driver close callback */
98 
99     virObjectEventState *eventState;
100     virConnectCloseCallbackData *closeCallback;
101 };
102 
103 enum {
104     REMOTE_CALL_QEMU              = (1 << 0),
105     REMOTE_CALL_LXC               = (1 << 1),
106 };
107 
108 
remoteDriverLock(struct private_data * driver)109 static void remoteDriverLock(struct private_data *driver)
110 {
111     virMutexLock(&driver->lock);
112 }
113 
remoteDriverUnlock(struct private_data * driver)114 static void remoteDriverUnlock(struct private_data *driver)
115 {
116     virMutexUnlock(&driver->lock);
117 }
118 
119 static int call(virConnectPtr conn, struct private_data *priv,
120                 unsigned int flags, int proc_nr,
121                 xdrproc_t args_filter, char *args,
122                 xdrproc_t ret_filter, char *ret);
123 static int callFull(virConnectPtr conn, struct private_data *priv,
124                     unsigned int flags,
125                     int *fdin, size_t fdinlen,
126                     int **fdout, size_t *fdoutlen,
127                     int proc_nr,
128                     xdrproc_t args_filter, char *args,
129                     xdrproc_t ret_filter, char *ret);
130 static int remoteAuthenticate(virConnectPtr conn, struct private_data *priv,
131                               virConnectAuthPtr auth, const char *authtype);
132 #if WITH_SASL
133 static int remoteAuthSASL(virConnectPtr conn, struct private_data *priv,
134                           virConnectAuthPtr auth, const char *mech);
135 #endif /* WITH_SASL */
136 static int remoteAuthPolkit(virConnectPtr conn, struct private_data *priv,
137                             virConnectAuthPtr auth);
138 
139 static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain);
140 static virNetworkPtr get_nonnull_network(virConnectPtr conn, remote_nonnull_network network);
141 static virNetworkPortPtr get_nonnull_network_port(virConnectPtr conn, remote_nonnull_network_port port);
142 static virNWFilterPtr get_nonnull_nwfilter(virConnectPtr conn, remote_nonnull_nwfilter nwfilter);
143 static virNWFilterBindingPtr get_nonnull_nwfilter_binding(virConnectPtr conn, remote_nonnull_nwfilter_binding binding);
144 static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface);
145 static virStoragePoolPtr get_nonnull_storage_pool(virConnectPtr conn, remote_nonnull_storage_pool pool);
146 static virStorageVolPtr get_nonnull_storage_vol(virConnectPtr conn, remote_nonnull_storage_vol vol);
147 static virNodeDevicePtr get_nonnull_node_device(virConnectPtr conn, remote_nonnull_node_device dev);
148 static virSecretPtr get_nonnull_secret(virConnectPtr conn, remote_nonnull_secret secret);
149 static virDomainCheckpointPtr get_nonnull_domain_checkpoint(virDomainPtr domain, remote_nonnull_domain_checkpoint checkpoint);
150 static virDomainSnapshotPtr get_nonnull_domain_snapshot(virDomainPtr domain, remote_nonnull_domain_snapshot snapshot);
151 static void make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src);
152 static void make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src);
153 static void make_nonnull_network_port(remote_nonnull_network_port *port_dst, virNetworkPortPtr port_src);
154 static void make_nonnull_interface(remote_nonnull_interface *interface_dst, virInterfacePtr interface_src);
155 static void make_nonnull_storage_pool(remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src);
156 static void make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src);
157 static void
158 make_nonnull_node_device(remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src);
159 static void make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src);
160 static void make_nonnull_nwfilter(remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src);
161 static void make_nonnull_nwfilter_binding(remote_nonnull_nwfilter_binding *binding_dst, virNWFilterBindingPtr binding_src);
162 static void make_nonnull_domain_checkpoint(remote_nonnull_domain_checkpoint *checkpoint_dst, virDomainCheckpointPtr checkpoint_src);
163 static void make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src);
164 
165 /*----------------------------------------------------------------------*/
166 
167 /* Helper functions for remoteOpen. */
168 
169 
170 static int
remoteStateInitialize(bool privileged G_GNUC_UNUSED,const char * root G_GNUC_UNUSED,virStateInhibitCallback callback G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)171 remoteStateInitialize(bool privileged G_GNUC_UNUSED,
172                       const char *root G_GNUC_UNUSED,
173                       virStateInhibitCallback callback G_GNUC_UNUSED,
174                       void *opaque G_GNUC_UNUSED)
175 {
176     /* Mark that we're inside the daemon so we can avoid
177      * re-entering ourselves
178      */
179     inside_daemon = true;
180     return VIR_DRV_STATE_INIT_COMPLETE;
181 }
182 
183 
184 static void
185 remoteDomainBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
186                                 virNetClient *client G_GNUC_UNUSED,
187                                 void *evdata, void *opaque);
188 static void
189 remoteDomainBuildEventCallbackLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
190                                         virNetClient *client G_GNUC_UNUSED,
191                                         void *evdata, void *opaque);
192 
193 static void
194 remoteDomainBuildEventReboot(virNetClientProgram *prog G_GNUC_UNUSED,
195                              virNetClient *client G_GNUC_UNUSED,
196                              void *evdata, void *opaque);
197 static void
198 remoteDomainBuildEventCallbackReboot(virNetClientProgram *prog G_GNUC_UNUSED,
199                                      virNetClient *client G_GNUC_UNUSED,
200                                      void *evdata, void *opaque);
201 
202 static void
203 remoteDomainBuildEventRTCChange(virNetClientProgram *prog,
204                                 virNetClient *client,
205                                 void *evdata, void *opaque);
206 static void
207 remoteDomainBuildEventCallbackRTCChange(virNetClientProgram *prog,
208                                         virNetClient *client,
209                                         void *evdata, void *opaque);
210 
211 static void
212 remoteDomainBuildEventWatchdog(virNetClientProgram *prog,
213                                virNetClient *client,
214                                void *evdata, void *opaque);
215 static void
216 remoteDomainBuildEventCallbackWatchdog(virNetClientProgram *prog,
217                                        virNetClient *client,
218                                        void *evdata, void *opaque);
219 
220 static void
221 remoteDomainBuildEventIOError(virNetClientProgram *prog,
222                               virNetClient *client,
223                               void *evdata, void *opaque);
224 static void
225 remoteDomainBuildEventCallbackIOError(virNetClientProgram *prog,
226                                       virNetClient *client,
227                                       void *evdata, void *opaque);
228 
229 static void
230 remoteDomainBuildEventIOErrorReason(virNetClientProgram *prog,
231                                     virNetClient *client,
232                                     void *evdata, void *opaque);
233 static void
234 remoteDomainBuildEventCallbackIOErrorReason(virNetClientProgram *prog,
235                                             virNetClient *client,
236                                             void *evdata, void *opaque);
237 
238 static void
239 remoteDomainBuildEventGraphics(virNetClientProgram *prog,
240                                virNetClient *client,
241                                void *evdata, void *opaque);
242 static void
243 remoteDomainBuildEventCallbackGraphics(virNetClientProgram *prog,
244                                        virNetClient *client,
245                                        void *evdata, void *opaque);
246 
247 static void
248 remoteDomainBuildEventControlError(virNetClientProgram *prog,
249                                    virNetClient *client,
250                                    void *evdata, void *opaque);
251 static void
252 remoteDomainBuildEventCallbackControlError(virNetClientProgram *prog,
253                                            virNetClient *client,
254                                            void *evdata, void *opaque);
255 
256 static void
257 remoteDomainBuildEventBlockJob(virNetClientProgram *prog,
258                                virNetClient *client,
259                                void *evdata, void *opaque);
260 static void
261 remoteDomainBuildEventCallbackBlockJob(virNetClientProgram *prog,
262                                        virNetClient *client,
263                                        void *evdata, void *opaque);
264 
265 
266 static void
267 remoteDomainBuildEventDiskChange(virNetClientProgram *prog,
268                                  virNetClient *client,
269                                  void *evdata, void *opaque);
270 static void
271 remoteDomainBuildEventCallbackDiskChange(virNetClientProgram *prog,
272                                          virNetClient *client,
273                                          void *evdata, void *opaque);
274 
275 static void
276 remoteDomainBuildEventTrayChange(virNetClientProgram *prog,
277                                  virNetClient *client,
278                                  void *evdata, void *opaque);
279 static void
280 remoteDomainBuildEventCallbackTrayChange(virNetClientProgram *prog,
281                                          virNetClient *client,
282                                          void *evdata, void *opaque);
283 
284 static void
285 remoteDomainBuildEventPMWakeup(virNetClientProgram *prog,
286                                virNetClient *client,
287                                void *evdata, void *opaque);
288 static void
289 remoteDomainBuildEventCallbackPMWakeup(virNetClientProgram *prog,
290                                        virNetClient *client,
291                                        void *evdata, void *opaque);
292 
293 static void
294 remoteDomainBuildEventPMSuspend(virNetClientProgram *prog,
295                                 virNetClient *client,
296                                 void *evdata, void *opaque);
297 static void
298 remoteDomainBuildEventCallbackPMSuspend(virNetClientProgram *prog,
299                                         virNetClient *client,
300                                         void *evdata, void *opaque);
301 
302 static void
303 remoteDomainBuildEventBalloonChange(virNetClientProgram *prog,
304                                     virNetClient *client,
305                                     void *evdata, void *opaque);
306 static void
307 remoteDomainBuildEventCallbackBalloonChange(virNetClientProgram *prog,
308                                             virNetClient *client,
309                                             void *evdata, void *opaque);
310 
311 static void
312 remoteDomainBuildEventPMSuspendDisk(virNetClientProgram *prog,
313                                   virNetClient *client,
314                                   void *evdata, void *opaque);
315 static void
316 remoteDomainBuildEventCallbackPMSuspendDisk(virNetClientProgram *prog,
317                                             virNetClient *client,
318                                             void *evdata, void *opaque);
319 
320 static void
321 remoteDomainBuildEventDeviceRemoved(virNetClientProgram *prog,
322                                     virNetClient *client,
323                                     void *evdata, void *opaque);
324 static void
325 remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgram *prog,
326                                             virNetClient *client,
327                                             void *evdata, void *opaque);
328 static void
329 remoteDomainBuildEventCallbackDeviceAdded(virNetClientProgram *prog,
330                                           virNetClient *client,
331                                           void *evdata, void *opaque);
332 static void
333 remoteDomainBuildEventCallbackDeviceRemovalFailed(virNetClientProgram *prog,
334                                                   virNetClient *client,
335                                                   void *evdata, void *opaque);
336 
337 static void
338 remoteDomainBuildEventBlockJob2(virNetClientProgram *prog,
339                                 virNetClient *client,
340                                 void *evdata, void *opaque);
341 
342 static void
343 remoteDomainBuildEventCallbackTunable(virNetClientProgram *prog,
344                                       virNetClient *client,
345                                       void *evdata, void *opaque);
346 
347 static void
348 remoteDomainBuildEventCallbackAgentLifecycle(virNetClientProgram *prog,
349                                              virNetClient *client,
350                                              void *evdata, void *opaque);
351 
352 static void
353 remoteDomainBuildEventCallbackMigrationIteration(virNetClientProgram *prog,
354                                                  virNetClient *client,
355                                                  void *evdata, void *opaque);
356 
357 static void
358 remoteDomainBuildEventCallbackJobCompleted(virNetClientProgram *prog,
359                                            virNetClient *client,
360                                            void *evdata, void *opaque);
361 
362 static void
363 remoteDomainBuildEventCallbackMetadataChange(virNetClientProgram *prog,
364                                              virNetClient *client,
365                                              void *evdata, void *opaque);
366 
367 static void
368 remoteNetworkBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
369                                  virNetClient *client G_GNUC_UNUSED,
370                                  void *evdata, void *opaque);
371 
372 static void
373 remoteStoragePoolBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
374                                      virNetClient *client G_GNUC_UNUSED,
375                                      void *evdata, void *opaque);
376 
377 static void
378 remoteStoragePoolBuildEventRefresh(virNetClientProgram *prog G_GNUC_UNUSED,
379                                    virNetClient *client G_GNUC_UNUSED,
380                                    void *evdata, void *opaque);
381 
382 static void
383 remoteNodeDeviceBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
384                                     virNetClient *client G_GNUC_UNUSED,
385                                     void *evdata, void *opaque);
386 
387 static void
388 remoteNodeDeviceBuildEventUpdate(virNetClientProgram *prog G_GNUC_UNUSED,
389                                  virNetClient *client G_GNUC_UNUSED,
390                                  void *evdata, void *opaque);
391 
392 static void
393 remoteSecretBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
394                                 virNetClient *client G_GNUC_UNUSED,
395                                 void *evdata, void *opaque);
396 
397 static void
398 remoteSecretBuildEventValueChanged(virNetClientProgram *prog G_GNUC_UNUSED,
399                                    virNetClient *client G_GNUC_UNUSED,
400                                    void *evdata, void *opaque);
401 
402 static void
403 remoteDomainBuildEventBlockThreshold(virNetClientProgram *prog,
404                                      virNetClient *client,
405                                      void *evdata, void *opaque);
406 
407 static void
408 remoteDomainBuildEventMemoryFailure(virNetClientProgram *prog,
409                                     virNetClient *client,
410                                     void *evdata, void *opaque);
411 
412 static void
413 remoteDomainBuildEventMemoryDeviceSizeChange(virNetClientProgram *prog,
414                                              virNetClient *client,
415                                              void *evdata, void *opaque);
416 static void
417 remoteConnectNotifyEventConnectionClosed(virNetClientProgram *prog G_GNUC_UNUSED,
418                                          virNetClient *client G_GNUC_UNUSED,
419                                          void *evdata, void *opaque);
420 
421 static virNetClientProgramEvent remoteEvents[] = {
422     { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
423       remoteDomainBuildEventLifecycle,
424       sizeof(remote_domain_event_lifecycle_msg),
425       (xdrproc_t)xdr_remote_domain_event_lifecycle_msg },
426     { REMOTE_PROC_DOMAIN_EVENT_REBOOT,
427       remoteDomainBuildEventReboot,
428       sizeof(remote_domain_event_reboot_msg),
429       (xdrproc_t)xdr_remote_domain_event_reboot_msg },
430     { REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
431       remoteDomainBuildEventRTCChange,
432       sizeof(remote_domain_event_rtc_change_msg),
433       (xdrproc_t)xdr_remote_domain_event_rtc_change_msg },
434     { REMOTE_PROC_DOMAIN_EVENT_WATCHDOG,
435       remoteDomainBuildEventWatchdog,
436       sizeof(remote_domain_event_watchdog_msg),
437       (xdrproc_t)xdr_remote_domain_event_watchdog_msg},
438     { REMOTE_PROC_DOMAIN_EVENT_IO_ERROR,
439       remoteDomainBuildEventIOError,
440       sizeof(remote_domain_event_io_error_msg),
441       (xdrproc_t)xdr_remote_domain_event_io_error_msg },
442     { REMOTE_PROC_DOMAIN_EVENT_GRAPHICS,
443       remoteDomainBuildEventGraphics,
444       sizeof(remote_domain_event_graphics_msg),
445       (xdrproc_t)xdr_remote_domain_event_graphics_msg },
446     { REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON,
447       remoteDomainBuildEventIOErrorReason,
448       sizeof(remote_domain_event_io_error_reason_msg),
449       (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg },
450     { REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR,
451       remoteDomainBuildEventControlError,
452       sizeof(remote_domain_event_control_error_msg),
453       (xdrproc_t)xdr_remote_domain_event_control_error_msg },
454     { REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB,
455       remoteDomainBuildEventBlockJob,
456       sizeof(remote_domain_event_block_job_msg),
457       (xdrproc_t)xdr_remote_domain_event_block_job_msg },
458     { REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE,
459       remoteDomainBuildEventDiskChange,
460       sizeof(remote_domain_event_disk_change_msg),
461       (xdrproc_t)xdr_remote_domain_event_disk_change_msg },
462     { REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE,
463       remoteDomainBuildEventTrayChange,
464       sizeof(remote_domain_event_tray_change_msg),
465       (xdrproc_t)xdr_remote_domain_event_tray_change_msg },
466     { REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP,
467       remoteDomainBuildEventPMWakeup,
468       sizeof(remote_domain_event_pmwakeup_msg),
469       (xdrproc_t)xdr_remote_domain_event_pmwakeup_msg },
470     { REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND,
471       remoteDomainBuildEventPMSuspend,
472       sizeof(remote_domain_event_pmsuspend_msg),
473       (xdrproc_t)xdr_remote_domain_event_pmsuspend_msg },
474     { REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE,
475       remoteDomainBuildEventBalloonChange,
476       sizeof(remote_domain_event_balloon_change_msg),
477       (xdrproc_t)xdr_remote_domain_event_balloon_change_msg },
478     { REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK,
479       remoteDomainBuildEventPMSuspendDisk,
480       sizeof(remote_domain_event_pmsuspend_disk_msg),
481       (xdrproc_t)xdr_remote_domain_event_pmsuspend_disk_msg },
482     { REMOTE_PROC_DOMAIN_EVENT_DEVICE_REMOVED,
483       remoteDomainBuildEventDeviceRemoved,
484       sizeof(remote_domain_event_device_removed_msg),
485       (xdrproc_t)xdr_remote_domain_event_device_removed_msg },
486     /* All events above here are legacy events, missing the callback
487      * ID, which means the server has a single global registration and
488      * we do full filtering in the client.  If the server lacks
489      * VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK, those are the only
490      * events we should ever receive.  Conversely, all events below
491      * here should only be triggered by modern servers, and all
492      * contain a callbackID.  Although we have to duplicate the first
493      * 16 domain events in both styles for back-compat, any future
494      * domain event additions should only use the modern style.  */
495     { REMOTE_PROC_NETWORK_EVENT_LIFECYCLE,
496       remoteNetworkBuildEventLifecycle,
497       sizeof(remote_network_event_lifecycle_msg),
498       (xdrproc_t)xdr_remote_network_event_lifecycle_msg },
499     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_LIFECYCLE,
500       remoteDomainBuildEventCallbackLifecycle,
501       sizeof(remote_domain_event_callback_lifecycle_msg),
502       (xdrproc_t)xdr_remote_domain_event_callback_lifecycle_msg },
503     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_REBOOT,
504       remoteDomainBuildEventCallbackReboot,
505       sizeof(remote_domain_event_callback_reboot_msg),
506       (xdrproc_t)xdr_remote_domain_event_callback_reboot_msg },
507     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_RTC_CHANGE,
508       remoteDomainBuildEventCallbackRTCChange,
509       sizeof(remote_domain_event_callback_rtc_change_msg),
510       (xdrproc_t)xdr_remote_domain_event_callback_rtc_change_msg },
511     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_WATCHDOG,
512       remoteDomainBuildEventCallbackWatchdog,
513       sizeof(remote_domain_event_callback_watchdog_msg),
514       (xdrproc_t)xdr_remote_domain_event_callback_watchdog_msg},
515     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR,
516       remoteDomainBuildEventCallbackIOError,
517       sizeof(remote_domain_event_callback_io_error_msg),
518       (xdrproc_t)xdr_remote_domain_event_callback_io_error_msg },
519     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_GRAPHICS,
520       remoteDomainBuildEventCallbackGraphics,
521       sizeof(remote_domain_event_callback_graphics_msg),
522       (xdrproc_t)xdr_remote_domain_event_callback_graphics_msg },
523     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_IO_ERROR_REASON,
524       remoteDomainBuildEventCallbackIOErrorReason,
525       sizeof(remote_domain_event_callback_io_error_reason_msg),
526       (xdrproc_t)xdr_remote_domain_event_callback_io_error_reason_msg },
527     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CONTROL_ERROR,
528       remoteDomainBuildEventCallbackControlError,
529       sizeof(remote_domain_event_callback_control_error_msg),
530       (xdrproc_t)xdr_remote_domain_event_callback_control_error_msg },
531     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BLOCK_JOB,
532       remoteDomainBuildEventCallbackBlockJob,
533       sizeof(remote_domain_event_callback_block_job_msg),
534       (xdrproc_t)xdr_remote_domain_event_callback_block_job_msg },
535     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DISK_CHANGE,
536       remoteDomainBuildEventCallbackDiskChange,
537       sizeof(remote_domain_event_callback_disk_change_msg),
538       (xdrproc_t)xdr_remote_domain_event_callback_disk_change_msg },
539     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TRAY_CHANGE,
540       remoteDomainBuildEventCallbackTrayChange,
541       sizeof(remote_domain_event_callback_tray_change_msg),
542       (xdrproc_t)xdr_remote_domain_event_callback_tray_change_msg },
543     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMWAKEUP,
544       remoteDomainBuildEventCallbackPMWakeup,
545       sizeof(remote_domain_event_callback_pmwakeup_msg),
546       (xdrproc_t)xdr_remote_domain_event_callback_pmwakeup_msg },
547     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND,
548       remoteDomainBuildEventCallbackPMSuspend,
549       sizeof(remote_domain_event_callback_pmsuspend_msg),
550       (xdrproc_t)xdr_remote_domain_event_callback_pmsuspend_msg },
551     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_BALLOON_CHANGE,
552       remoteDomainBuildEventCallbackBalloonChange,
553       sizeof(remote_domain_event_callback_balloon_change_msg),
554       (xdrproc_t)xdr_remote_domain_event_callback_balloon_change_msg },
555     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_PMSUSPEND_DISK,
556       remoteDomainBuildEventCallbackPMSuspendDisk,
557       sizeof(remote_domain_event_callback_pmsuspend_disk_msg),
558       (xdrproc_t)xdr_remote_domain_event_callback_pmsuspend_disk_msg },
559     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVED,
560       remoteDomainBuildEventCallbackDeviceRemoved,
561       sizeof(remote_domain_event_callback_device_removed_msg),
562       (xdrproc_t)xdr_remote_domain_event_callback_device_removed_msg },
563     { REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB_2,
564       remoteDomainBuildEventBlockJob2,
565       sizeof(remote_domain_event_block_job_2_msg),
566       (xdrproc_t)xdr_remote_domain_event_block_job_2_msg },
567     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE,
568       remoteDomainBuildEventCallbackTunable,
569       sizeof(remote_domain_event_callback_tunable_msg),
570       (xdrproc_t)xdr_remote_domain_event_callback_tunable_msg },
571     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_AGENT_LIFECYCLE,
572       remoteDomainBuildEventCallbackAgentLifecycle,
573       sizeof(remote_domain_event_callback_agent_lifecycle_msg),
574       (xdrproc_t)xdr_remote_domain_event_callback_agent_lifecycle_msg },
575     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_ADDED,
576       remoteDomainBuildEventCallbackDeviceAdded,
577       sizeof(remote_domain_event_callback_device_added_msg),
578       (xdrproc_t)xdr_remote_domain_event_callback_device_added_msg },
579     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_MIGRATION_ITERATION,
580       remoteDomainBuildEventCallbackMigrationIteration,
581       sizeof(remote_domain_event_callback_migration_iteration_msg),
582       (xdrproc_t)xdr_remote_domain_event_callback_migration_iteration_msg },
583     { REMOTE_PROC_CONNECT_EVENT_CONNECTION_CLOSED,
584       remoteConnectNotifyEventConnectionClosed,
585       sizeof(remote_connect_event_connection_closed_msg),
586       (xdrproc_t)xdr_remote_connect_event_connection_closed_msg },
587     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_JOB_COMPLETED,
588       remoteDomainBuildEventCallbackJobCompleted,
589       sizeof(remote_domain_event_callback_job_completed_msg),
590       (xdrproc_t)xdr_remote_domain_event_callback_job_completed_msg },
591     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_DEVICE_REMOVAL_FAILED,
592       remoteDomainBuildEventCallbackDeviceRemovalFailed,
593       sizeof(remote_domain_event_callback_device_removal_failed_msg),
594       (xdrproc_t)xdr_remote_domain_event_callback_device_removal_failed_msg },
595     { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_METADATA_CHANGE,
596       remoteDomainBuildEventCallbackMetadataChange,
597       sizeof(remote_domain_event_callback_metadata_change_msg),
598       (xdrproc_t)xdr_remote_domain_event_callback_metadata_change_msg },
599     { REMOTE_PROC_STORAGE_POOL_EVENT_LIFECYCLE,
600       remoteStoragePoolBuildEventLifecycle,
601       sizeof(remote_storage_pool_event_lifecycle_msg),
602       (xdrproc_t)xdr_remote_storage_pool_event_lifecycle_msg },
603     { REMOTE_PROC_STORAGE_POOL_EVENT_REFRESH,
604       remoteStoragePoolBuildEventRefresh,
605       sizeof(remote_storage_pool_event_refresh_msg),
606       (xdrproc_t)xdr_remote_storage_pool_event_refresh_msg },
607     { REMOTE_PROC_NODE_DEVICE_EVENT_LIFECYCLE,
608       remoteNodeDeviceBuildEventLifecycle,
609       sizeof(remote_node_device_event_lifecycle_msg),
610       (xdrproc_t)xdr_remote_node_device_event_lifecycle_msg },
611     { REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE,
612       remoteNodeDeviceBuildEventUpdate,
613       sizeof(remote_node_device_event_update_msg),
614       (xdrproc_t)xdr_remote_node_device_event_update_msg },
615     { REMOTE_PROC_SECRET_EVENT_LIFECYCLE,
616       remoteSecretBuildEventLifecycle,
617       sizeof(remote_secret_event_lifecycle_msg),
618       (xdrproc_t)xdr_remote_secret_event_lifecycle_msg },
619     { REMOTE_PROC_SECRET_EVENT_VALUE_CHANGED,
620       remoteSecretBuildEventValueChanged,
621       sizeof(remote_secret_event_value_changed_msg),
622       (xdrproc_t)xdr_remote_secret_event_value_changed_msg },
623     { REMOTE_PROC_DOMAIN_EVENT_BLOCK_THRESHOLD,
624       remoteDomainBuildEventBlockThreshold,
625       sizeof(remote_domain_event_block_threshold_msg),
626       (xdrproc_t)xdr_remote_domain_event_block_threshold_msg },
627     { REMOTE_PROC_DOMAIN_EVENT_MEMORY_FAILURE,
628       remoteDomainBuildEventMemoryFailure,
629       sizeof(remote_domain_event_memory_failure_msg),
630       (xdrproc_t)xdr_remote_domain_event_memory_failure_msg },
631     { REMOTE_PROC_DOMAIN_EVENT_MEMORY_DEVICE_SIZE_CHANGE,
632       remoteDomainBuildEventMemoryDeviceSizeChange,
633       sizeof(remote_domain_event_memory_device_size_change_msg),
634       (xdrproc_t)xdr_remote_domain_event_memory_device_size_change_msg },
635 };
636 
637 static void
remoteConnectNotifyEventConnectionClosed(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)638 remoteConnectNotifyEventConnectionClosed(virNetClientProgram *prog G_GNUC_UNUSED,
639                                          virNetClient *client G_GNUC_UNUSED,
640                                          void *evdata, void *opaque)
641 {
642     virConnectPtr conn = opaque;
643     struct private_data *priv = conn->privateData;
644     remote_connect_event_connection_closed_msg *msg = evdata;
645 
646     virConnectCloseCallbackDataCall(priv->closeCallback, msg->reason);
647 }
648 
649 static void
650 remoteDomainBuildQemuMonitorEvent(virNetClientProgram *prog G_GNUC_UNUSED,
651                                   virNetClient *client G_GNUC_UNUSED,
652                                   void *evdata, void *opaque);
653 
654 static virNetClientProgramEvent qemuEvents[] = {
655     { QEMU_PROC_DOMAIN_MONITOR_EVENT,
656       remoteDomainBuildQemuMonitorEvent,
657       sizeof(qemu_domain_monitor_event_msg),
658       (xdrproc_t)xdr_qemu_domain_monitor_event_msg },
659 };
660 
661 
662 static void
remoteClientCloseFunc(virNetClient * client G_GNUC_UNUSED,int reason,void * opaque)663 remoteClientCloseFunc(virNetClient *client G_GNUC_UNUSED,
664                       int reason,
665                       void *opaque)
666 {
667     virConnectCloseCallbackDataCall((virConnectCloseCallbackData *)opaque,
668                                     reason);
669 }
670 
671 static bool
remoteConnectSupportsFeatureUnlocked(virConnectPtr conn,struct private_data * priv,int feature)672 remoteConnectSupportsFeatureUnlocked(virConnectPtr conn,
673                                      struct private_data *priv,
674                                      int feature)
675 {
676     remote_connect_supports_feature_args args = { feature };
677     remote_connect_supports_feature_ret ret = { 0 };
678     int rc;
679 
680     rc = call(conn, priv, 0, REMOTE_PROC_CONNECT_SUPPORTS_FEATURE,
681               (xdrproc_t)xdr_remote_connect_supports_feature_args, (char *) &args,
682               (xdrproc_t)xdr_remote_connect_supports_feature_ret, (char *) &ret);
683 
684     return rc != -1 && ret.supported;
685 }
686 
687 /* helper macro to ease extraction of arguments from the URI */
688 #define EXTRACT_URI_ARG_STR(ARG_NAME, ARG_VAR) \
689     if (STRCASEEQ(var->name, ARG_NAME)) { \
690         VIR_FREE(ARG_VAR); \
691         ARG_VAR = g_strdup(var->value); \
692         var->ignore = 1; \
693         continue; \
694     }
695 
696 #define EXTRACT_URI_ARG_BOOL(ARG_NAME, ARG_VAR) \
697     if (STRCASEEQ(var->name, ARG_NAME)) { \
698         int tmp; \
699         if (virStrToLong_i(var->value, NULL, 10, &tmp) < 0) { \
700             virReportError(VIR_ERR_INVALID_ARG, \
701                            _("Failed to parse value of URI component %s"), \
702                            var->name); \
703             goto failed; \
704         } \
705         ARG_VAR = tmp == 0; \
706         var->ignore = 1; \
707         continue; \
708     }
709 
710 
711 /*
712  * URIs that this driver needs to handle:
713  *
714  * The easy answer:
715  *   - Everything that no one else has yet claimed, but nothing if
716  *     we're inside the libvirtd daemon
717  *
718  * The hard answer:
719  *   - Plain paths (///var/lib/xen/xend-socket)  -> UNIX domain socket
720  *   - xxx://servername/      -> TLS connection
721  *   - xxx+tls://servername/  -> TLS connection
722  *   - xxx+tls:///            -> TLS connection to localhost
723  *   - xxx+tcp://servername/  -> TCP connection
724  *   - xxx+tcp:///            -> TCP connection to localhost
725  *   - xxx+unix:///           -> UNIX domain socket
726  *   - xxx:///                -> UNIX domain socket
727  *   - xxx+ssh:///            -> SSH connection (legacy)
728  *   - xxx+libssh2:///        -> SSH connection (using libssh2)
729  *   - xxx+libssh:///         -> SSH connection (using libssh)
730  */
731 static int
doRemoteOpen(virConnectPtr conn,struct private_data * priv,const char * driver_str,remoteDriverTransport transport,virConnectAuthPtr auth G_GNUC_UNUSED,virConf * conf,unsigned int flags)732 doRemoteOpen(virConnectPtr conn,
733              struct private_data *priv,
734              const char *driver_str,
735              remoteDriverTransport transport,
736              virConnectAuthPtr auth G_GNUC_UNUSED,
737              virConf *conf,
738              unsigned int flags)
739 {
740     g_autofree char *tls_priority = NULL;
741     g_autofree char *name = NULL;
742     g_autofree char *command = NULL;
743     g_autofree char *sockname = NULL;
744     g_autofree char *netcat = NULL;
745     g_autofree char *port = NULL;
746     g_autofree char *authtype = NULL;
747     g_autofree char *username = NULL;
748     g_autofree char *pkipath = NULL;
749     g_autofree char *keyfile = NULL;
750     g_autofree char *sshauth = NULL;
751     g_autofree char *knownHostsVerify = NULL;
752     g_autofree char *knownHosts = NULL;
753     g_autofree char *mode_str = NULL;
754     g_autofree char *daemon_path = NULL;
755     g_autofree char *proxy_str = NULL;
756     bool sanity = true;
757     bool verify = true;
758 #ifndef WIN32
759     bool tty = true;
760 #endif
761     int mode;
762     size_t i;
763     int proxy;
764 
765     /* We handle *ALL* URIs here. The caller has rejected any
766      * URIs we don't care about */
767 
768     /* Remote server defaults to "localhost" if not specified. */
769     if (conn->uri && conn->uri->port != 0) {
770         port = g_strdup_printf("%d", conn->uri->port);
771     } else if (transport == REMOTE_DRIVER_TRANSPORT_TLS) {
772         port = g_strdup(LIBVIRTD_TLS_PORT);
773     } else if (transport == REMOTE_DRIVER_TRANSPORT_TCP) {
774         port = g_strdup(LIBVIRTD_TCP_PORT);
775     } /* Port not used for unix, ext., default for ssh */
776 
777     priv->hostname = g_strdup(conn->uri && conn->uri->server ? conn->uri->server : "localhost");
778 
779     if (conn->uri)
780         username = g_strdup(conn->uri->user);
781 
782     /* Get the variables from the query string.
783      * Then we need to reconstruct the query string (because
784      * feasibly it might contain variables needed by the real driver,
785      * although that won't be the case for now).
786      */
787     if (conn->uri) {
788         for (i = 0; i < conn->uri->paramsCount; i++) {
789             virURIParam *var = &conn->uri->params[i];
790             EXTRACT_URI_ARG_STR("name", name);
791             EXTRACT_URI_ARG_STR("command", command);
792             EXTRACT_URI_ARG_STR("socket", sockname);
793             EXTRACT_URI_ARG_STR("auth", authtype);
794             EXTRACT_URI_ARG_STR("sshauth", sshauth);
795             EXTRACT_URI_ARG_STR("netcat", netcat);
796             EXTRACT_URI_ARG_STR("keyfile", keyfile);
797             EXTRACT_URI_ARG_STR("pkipath", pkipath);
798             EXTRACT_URI_ARG_STR("known_hosts", knownHosts);
799             EXTRACT_URI_ARG_STR("known_hosts_verify", knownHostsVerify);
800             EXTRACT_URI_ARG_STR("tls_priority", tls_priority);
801             EXTRACT_URI_ARG_STR("mode", mode_str);
802             EXTRACT_URI_ARG_STR("proxy", proxy_str);
803             EXTRACT_URI_ARG_BOOL("no_sanity", sanity);
804             EXTRACT_URI_ARG_BOOL("no_verify", verify);
805 #ifndef WIN32
806             EXTRACT_URI_ARG_BOOL("no_tty", tty);
807 #endif
808 
809             if (STRCASEEQ(var->name, "authfile")) {
810                 /* Strip this param, used by virauth.c */
811                 var->ignore = 1;
812                 continue;
813             }
814 
815             VIR_DEBUG("passing through variable '%s' ('%s') to remote end",
816                        var->name, var->value);
817         }
818 
819         /* Construct the original name. */
820         if (!name) {
821             if (conn->uri->scheme &&
822                 (STREQ(conn->uri->scheme, "remote") ||
823                  STRPREFIX(conn->uri->scheme, "remote+"))) {
824                 /* Allow remote serve to probe */
825                 name = g_strdup("");
826             } else {
827                 virURI tmpuri = {
828                     .scheme = (char *)driver_str,
829                     .query = virURIFormatParams(conn->uri),
830                     .path = conn->uri->path,
831                     .fragment = conn->uri->fragment,
832                 };
833 
834                 name = virURIFormat(&tmpuri);
835 
836                 VIR_FREE(tmpuri.query);
837 
838                 if (!name)
839                     goto failed;
840             }
841         }
842     } else {
843         /* Probe URI server side */
844         name = g_strdup("");
845     }
846 
847     if (conf && !mode_str &&
848         virConfGetValueString(conf, "remote_mode", &mode_str) < 0)
849         goto failed;
850 
851     if (mode_str) {
852         if ((mode = remoteDriverModeTypeFromString(mode_str)) < 0) {
853             virReportError(VIR_ERR_INVALID_ARG,
854                            _("Unknown remote mode '%s'"), mode_str);
855             goto failed;
856         }
857     } else {
858         if (inside_daemon && !conn->uri->server) {
859             mode = REMOTE_DRIVER_MODE_DIRECT;
860         } else {
861             mode = REMOTE_DRIVER_MODE_AUTO;
862         }
863     }
864 
865     if (conf && !proxy_str &&
866         virConfGetValueString(conf, "remote_proxy", &proxy_str) < 0)
867         goto failed;
868 
869     if (proxy_str) {
870         if ((proxy = virNetClientProxyTypeFromString(proxy_str)) < 0) {
871             virReportError(VIR_ERR_INVALID_ARG,
872                            _("Unnkown proxy type '%s'"), proxy_str);
873             goto failed;
874         }
875     } else {
876         /*
877          * Goal is to maximise usage of virt-ssh-helper
878          *
879          * Historically tunnelling access for the session mode
880          * daemon did not automatically work, since we can't
881          * construct the accurate path remotely. Users could,
882          * however, specify the 'socket' URI parameter explicitly.
883          *
884          * If we see a 'socket' path we must always use netcat,
885          * since virt-ssh-helper won't handle an explicit socket.
886          * Autostart won't work for session mode, so we assume
887          * user started it manually on the remote host in this
888          * case.
889          *
890          * If we have a 'session' URI without explicit socket,
891          * we can just assume the use of virt-ssh-helper, since
892          * logic for constructing socket paths relies on env
893          * envs whose values have no guarantee of matching those
894          * on the remote host. It was explicitly blocked with an
895          * error check before virt-ssh-helper was introduced.
896          *
897          * For 'system' URIs, we need to try virt-ssh-helper but
898          * with fallback to netcat for back compat.
899          */
900         if (sockname)
901             proxy = VIR_NET_CLIENT_PROXY_NETCAT;
902         else if (flags & REMOTE_DRIVER_OPEN_USER)
903             proxy = VIR_NET_CLIENT_PROXY_NATIVE;
904         else
905             proxy = VIR_NET_CLIENT_PROXY_AUTO;
906     }
907 
908     /* Sanity check that nothing requested !direct mode by mistake */
909     if (inside_daemon && !conn->uri->server && mode != REMOTE_DRIVER_MODE_DIRECT) {
910         virReportError(VIR_ERR_INVALID_ARG, "%s",
911                        _("Connections from inside daemon must be direct"));
912         return VIR_DRV_OPEN_ERROR;
913     }
914 
915     VIR_DEBUG("proceeding with name = %s", name);
916 
917     /* For ext transport, command is required. */
918     if (transport == REMOTE_DRIVER_TRANSPORT_EXT && !command) {
919         virReportError(VIR_ERR_INVALID_ARG, "%s",
920                        _("remote_open: for 'ext' transport, command is required"));
921         goto failed;
922     }
923 
924     VIR_DEBUG("Connecting with transport %d", transport);
925 
926     switch ((remoteDriverTransport)transport) {
927     case REMOTE_DRIVER_TRANSPORT_UNIX:
928     case REMOTE_DRIVER_TRANSPORT_SSH:
929     case REMOTE_DRIVER_TRANSPORT_LIBSSH:
930     case REMOTE_DRIVER_TRANSPORT_LIBSSH2:
931         if (!sockname &&
932             !(sockname = remoteGetUNIXSocket(transport, mode, driver_str,
933                                              flags, &daemon_path)))
934             goto failed;
935         break;
936 
937     case REMOTE_DRIVER_TRANSPORT_TCP:
938     case REMOTE_DRIVER_TRANSPORT_TLS:
939     case REMOTE_DRIVER_TRANSPORT_EXT:
940         break;
941 
942     case REMOTE_DRIVER_TRANSPORT_LAST:
943     default:
944         virReportEnumRangeError(remoteDriverTransport, transport);
945         goto failed;
946     }
947 
948     VIR_DEBUG("Chosen UNIX socket %s", NULLSTR(sockname));
949 
950     /* Connect to the remote service. */
951     switch ((remoteDriverTransport)transport) {
952     case REMOTE_DRIVER_TRANSPORT_TLS:
953         if (conf && !tls_priority &&
954             virConfGetValueString(conf, "tls_priority", &tls_priority) < 0)
955             goto failed;
956 
957         priv->tls = virNetTLSContextNewClientPath(pkipath,
958                                                   geteuid() != 0,
959                                                   tls_priority,
960                                                   sanity, verify);
961         if (!priv->tls)
962             goto failed;
963         priv->is_secure = 1;
964         G_GNUC_FALLTHROUGH;
965 
966     case REMOTE_DRIVER_TRANSPORT_TCP:
967         priv->client = virNetClientNewTCP(priv->hostname, port, AF_UNSPEC);
968         if (!priv->client)
969             goto failed;
970 
971         if (priv->tls) {
972             VIR_DEBUG("Starting TLS session");
973             if (virNetClientSetTLSSession(priv->client, priv->tls) < 0)
974                 goto failed;
975         }
976 
977         break;
978 
979     case REMOTE_DRIVER_TRANSPORT_LIBSSH2:
980         VIR_DEBUG("Starting LibSSH2 session");
981 
982         priv->client = virNetClientNewLibSSH2(priv->hostname,
983                                               port,
984                                               AF_UNSPEC,
985                                               username,
986                                               keyfile,
987                                               knownHosts,
988                                               knownHostsVerify,
989                                               sshauth,
990                                               proxy,
991                                               netcat,
992                                               sockname,
993                                               name,
994                                               flags & REMOTE_DRIVER_OPEN_RO,
995                                               auth,
996                                               conn->uri);
997         if (!priv->client)
998             goto failed;
999 
1000         priv->is_secure = 1;
1001         break;
1002 
1003     case REMOTE_DRIVER_TRANSPORT_LIBSSH:
1004         VIR_DEBUG("Starting libssh session");
1005 
1006         priv->client = virNetClientNewLibssh(priv->hostname,
1007                                              port,
1008                                              AF_UNSPEC,
1009                                              username,
1010                                              keyfile,
1011                                              knownHosts,
1012                                              knownHostsVerify,
1013                                              sshauth,
1014                                              proxy,
1015                                              netcat,
1016                                              sockname,
1017                                              name,
1018                                              flags & REMOTE_DRIVER_OPEN_RO,
1019                                              auth,
1020                                              conn->uri);
1021         if (!priv->client)
1022             goto failed;
1023 
1024         priv->is_secure = 1;
1025         break;
1026 
1027 #ifndef WIN32
1028     case REMOTE_DRIVER_TRANSPORT_UNIX:
1029         if (!(priv->client = virNetClientNewUNIX(sockname,
1030                                                  daemon_path)))
1031             goto failed;
1032 
1033         priv->is_secure = 1;
1034         break;
1035 
1036     case REMOTE_DRIVER_TRANSPORT_SSH:
1037         if (!command)
1038             command = g_strdup("ssh");
1039 
1040         if (!(priv->client = virNetClientNewSSH(priv->hostname,
1041                                                 port,
1042                                                 command,
1043                                                 username,
1044                                                 !tty,
1045                                                 !verify,
1046                                                 keyfile,
1047                                                 proxy,
1048                                                 netcat,
1049                                                 sockname,
1050                                                 name,
1051                                                 flags & REMOTE_DRIVER_OPEN_RO)))
1052             goto failed;
1053 
1054         priv->is_secure = 1;
1055         break;
1056 
1057     case REMOTE_DRIVER_TRANSPORT_EXT: {
1058         char const *cmd_argv[] = { command, NULL };
1059         if (!(priv->client = virNetClientNewExternal(cmd_argv)))
1060             goto failed;
1061 
1062         /* Do not set 'is_secure' flag since we can't guarantee
1063          * an external program is secure, and this flag must be
1064          * pessimistic */
1065     }   break;
1066 
1067 #else /* WIN32 */
1068 
1069     case REMOTE_DRIVER_TRANSPORT_UNIX:
1070     case REMOTE_DRIVER_TRANSPORT_SSH:
1071     case REMOTE_DRIVER_TRANSPORT_EXT:
1072         virReportError(VIR_ERR_INVALID_ARG, "%s",
1073                        _("transport methods unix, ssh and ext are not supported "
1074                          "under Windows"));
1075         goto failed;
1076 
1077 #endif /* WIN32 */
1078 
1079     case REMOTE_DRIVER_TRANSPORT_LAST:
1080     default:
1081         virReportEnumRangeError(remoteDriverTransport, transport);
1082         goto failed;
1083     } /* switch (transport) */
1084 
1085 
1086     if (virNetClientRegisterAsyncIO(priv->client) < 0) {
1087         VIR_DEBUG("Failed to add event watch, disabling events and support for"
1088                   " keepalive messages");
1089         virResetLastError();
1090     } else {
1091         if (virNetClientRegisterKeepAlive(priv->client) < 0)
1092             goto failed;
1093     }
1094 
1095     if (!(priv->closeCallback = virNewConnectCloseCallbackData()))
1096         goto failed;
1097     /* ref on behalf of netclient */
1098     virObjectRef(priv->closeCallback);
1099     virNetClientSetCloseCallback(priv->client,
1100                                  remoteClientCloseFunc,
1101                                  priv->closeCallback, virObjectFreeCallback);
1102 
1103     if (!(priv->remoteProgram = virNetClientProgramNew(REMOTE_PROGRAM,
1104                                                        REMOTE_PROTOCOL_VERSION,
1105                                                        remoteEvents,
1106                                                        G_N_ELEMENTS(remoteEvents),
1107                                                        conn)))
1108         goto failed;
1109     if (!(priv->lxcProgram = virNetClientProgramNew(LXC_PROGRAM,
1110                                                     LXC_PROTOCOL_VERSION,
1111                                                     NULL,
1112                                                     0,
1113                                                     NULL)))
1114         goto failed;
1115     if (!(priv->qemuProgram = virNetClientProgramNew(QEMU_PROGRAM,
1116                                                      QEMU_PROTOCOL_VERSION,
1117                                                      qemuEvents,
1118                                                      G_N_ELEMENTS(qemuEvents),
1119                                                      conn)))
1120         goto failed;
1121 
1122     if (virNetClientAddProgram(priv->client, priv->remoteProgram) < 0 ||
1123         virNetClientAddProgram(priv->client, priv->lxcProgram) < 0 ||
1124         virNetClientAddProgram(priv->client, priv->qemuProgram) < 0)
1125         goto failed;
1126 
1127     /* Try and authenticate with server */
1128     VIR_DEBUG("Trying authentication");
1129     if (remoteAuthenticate(conn, priv, auth, authtype) == -1)
1130         goto failed;
1131 
1132     if (virNetClientKeepAliveIsSupported(priv->client)) {
1133         priv->serverKeepAlive = remoteConnectSupportsFeatureUnlocked(conn,
1134                                     priv, VIR_DRV_FEATURE_PROGRAM_KEEPALIVE);
1135         if (!priv->serverKeepAlive) {
1136             VIR_INFO("Disabling keepalive protocol since it is not supported"
1137                      " by the server");
1138         }
1139     }
1140 
1141     /* Finally we can call the remote side's open function. */
1142     {
1143         remote_connect_open_args args = { &name, flags };
1144 
1145         VIR_DEBUG("Trying to open URI '%s'", name);
1146         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_OPEN,
1147                  (xdrproc_t) xdr_remote_connect_open_args, (char *) &args,
1148                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
1149             goto failed;
1150     }
1151 
1152     /* Now try and find out what URI the daemon used */
1153     if (conn->uri == NULL) {
1154         remote_connect_get_uri_ret uriret;
1155 
1156         VIR_DEBUG("Trying to query remote URI");
1157         memset(&uriret, 0, sizeof(uriret));
1158         if (call(conn, priv, 0,
1159                  REMOTE_PROC_CONNECT_GET_URI,
1160                  (xdrproc_t) xdr_void, (char *) NULL,
1161                  (xdrproc_t) xdr_remote_connect_get_uri_ret, (char *) &uriret) < 0)
1162             goto failed;
1163 
1164         VIR_DEBUG("Auto-probed URI is %s", uriret.uri);
1165         conn->uri = virURIParse(uriret.uri);
1166         VIR_FREE(uriret.uri);
1167         if (!conn->uri)
1168             goto failed;
1169     }
1170 
1171     /* Set up events */
1172     if (!(priv->eventState = virObjectEventStateNew()))
1173         goto failed;
1174 
1175     priv->serverEventFilter = remoteConnectSupportsFeatureUnlocked(conn,
1176                                 priv, VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK);
1177     if (!priv->serverEventFilter) {
1178         VIR_INFO("Avoiding server event filtering since it is not "
1179                  "supported by the server");
1180     }
1181 
1182     priv->serverCloseCallback = remoteConnectSupportsFeatureUnlocked(conn,
1183                                     priv, VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK);
1184     if (!priv->serverCloseCallback) {
1185         VIR_INFO("Close callback registering isn't supported "
1186                  "by the remote side.");
1187     }
1188 
1189     return VIR_DRV_OPEN_SUCCESS;
1190 
1191  failed:
1192     virObjectUnref(priv->remoteProgram);
1193     virObjectUnref(priv->lxcProgram);
1194     virObjectUnref(priv->qemuProgram);
1195     virNetClientClose(priv->client);
1196     virObjectUnref(priv->client);
1197     priv->client = NULL;
1198     virObjectUnref(priv->closeCallback);
1199     priv->closeCallback = NULL;
1200     virObjectUnref(priv->tls);
1201     priv->tls = NULL;
1202 
1203     VIR_FREE(priv->hostname);
1204     return VIR_DRV_OPEN_ERROR;
1205 }
1206 #undef EXTRACT_URI_ARG_STR
1207 #undef EXTRACT_URI_ARG_BOOL
1208 
1209 static struct private_data *
remoteAllocPrivateData(void)1210 remoteAllocPrivateData(void)
1211 {
1212     struct private_data *priv;
1213     priv = g_new0(struct private_data, 1);
1214 
1215     if (virMutexInit(&priv->lock) < 0) {
1216         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1217                        _("cannot initialize mutex"));
1218         VIR_FREE(priv);
1219         return NULL;
1220     }
1221     remoteDriverLock(priv);
1222     priv->localUses = 1;
1223 
1224     return priv;
1225 }
1226 
1227 static virDrvOpenStatus
remoteConnectOpen(virConnectPtr conn,virConnectAuthPtr auth,virConf * conf,unsigned int flags)1228 remoteConnectOpen(virConnectPtr conn,
1229                   virConnectAuthPtr auth,
1230                   virConf *conf,
1231                   unsigned int flags)
1232 {
1233     struct private_data *priv;
1234     int ret = VIR_DRV_OPEN_ERROR;
1235     unsigned int rflags = 0;
1236     char *driver = NULL;
1237     remoteDriverTransport transport;
1238 
1239     if (conn->uri) {
1240         if (remoteSplitURIScheme(conn->uri, &driver, &transport) < 0)
1241             goto cleanup;
1242     } else {
1243         /* No URI, then must be probing so use UNIX socket */
1244         transport = REMOTE_DRIVER_TRANSPORT_UNIX;
1245     }
1246 
1247 
1248     if (inside_daemon) {
1249         if (!conn->uri) {
1250             ret = VIR_DRV_OPEN_DECLINED;
1251             goto cleanup;
1252         }
1253 
1254         /* If there's a driver registered we must defer to that.
1255          * If there isn't a driver, we must connect in "direct"
1256          * mode - see doRemoteOpen.
1257          * One exception is if we are trying to connect to an
1258          * unknown socket path as that might be proxied to remote
1259          * host */
1260         if (!conn->uri->server &&
1261             virHasDriverForURIScheme(driver) &&
1262             !virURICheckUnixSocket(conn->uri)) {
1263             ret = VIR_DRV_OPEN_DECLINED;
1264             goto cleanup;
1265         }
1266     }
1267 
1268     if (!(priv = remoteAllocPrivateData()))
1269         goto cleanup;
1270 
1271 
1272     remoteGetURIDaemonInfo(conn->uri, transport, &rflags);
1273     if (flags & VIR_CONNECT_RO)
1274         rflags |= REMOTE_DRIVER_OPEN_RO;
1275 
1276     ret = doRemoteOpen(conn, priv, driver, transport, auth, conf, rflags);
1277     if (ret != VIR_DRV_OPEN_SUCCESS) {
1278         conn->privateData = NULL;
1279         remoteDriverUnlock(priv);
1280         VIR_FREE(priv);
1281     } else {
1282         conn->privateData = priv;
1283         remoteDriverUnlock(priv);
1284     }
1285 
1286  cleanup:
1287     VIR_FREE(driver);
1288     return ret;
1289 }
1290 
1291 
1292 /*----------------------------------------------------------------------*/
1293 
1294 
1295 static int
doRemoteClose(virConnectPtr conn,struct private_data * priv)1296 doRemoteClose(virConnectPtr conn, struct private_data *priv)
1297 {
1298     int ret = 0;
1299 
1300     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_CLOSE,
1301              (xdrproc_t) xdr_void, (char *) NULL,
1302              (xdrproc_t) xdr_void, (char *) NULL) == -1)
1303         ret = -1;
1304 
1305     virObjectUnref(priv->tls);
1306     priv->tls = NULL;
1307 
1308     virNetClientSetCloseCallback(priv->client,
1309                                  NULL,
1310                                  priv->closeCallback, virObjectFreeCallback);
1311 
1312     virNetClientClose(priv->client);
1313     virObjectUnref(priv->client);
1314     priv->client = NULL;
1315     virObjectUnref(priv->closeCallback);
1316     priv->closeCallback = NULL;
1317     virObjectUnref(priv->remoteProgram);
1318     virObjectUnref(priv->lxcProgram);
1319     virObjectUnref(priv->qemuProgram);
1320     priv->remoteProgram = priv->qemuProgram = priv->lxcProgram = NULL;
1321 
1322     /* Free hostname copy */
1323     VIR_FREE(priv->hostname);
1324 
1325     /* See comment for remoteType. */
1326     VIR_FREE(priv->type);
1327 
1328     virObjectUnref(priv->eventState);
1329     priv->eventState = NULL;
1330 
1331     return ret;
1332 }
1333 
1334 static int
remoteConnectClose(virConnectPtr conn)1335 remoteConnectClose(virConnectPtr conn)
1336 {
1337     int ret = 0;
1338     struct private_data *priv = conn->privateData;
1339 
1340     remoteDriverLock(priv);
1341     priv->localUses--;
1342     if (!priv->localUses) {
1343         ret = doRemoteClose(conn, priv);
1344         conn->privateData = NULL;
1345         remoteDriverUnlock(priv);
1346         virMutexDestroy(&priv->lock);
1347         VIR_FREE(priv);
1348     }
1349     if (priv)
1350         remoteDriverUnlock(priv);
1351 
1352     return ret;
1353 }
1354 
1355 
1356 /* Unfortunately this function is defined to return a static string.
1357  * Since the remote end always answers with the same type (for a
1358  * single connection anyway) we cache the type in the connection's
1359  * private data, and free it when we close the connection.
1360  *
1361  * See also:
1362  * https://www.redhat.com/archives/libvir-list/2007-February/msg00096.html
1363  */
1364 static const char *
remoteConnectGetType(virConnectPtr conn)1365 remoteConnectGetType(virConnectPtr conn)
1366 {
1367     char *rv = NULL;
1368     remote_connect_get_type_ret ret;
1369     struct private_data *priv = conn->privateData;
1370 
1371     remoteDriverLock(priv);
1372 
1373     /* Cached? */
1374     if (priv->type) {
1375         rv = priv->type;
1376         goto done;
1377     }
1378 
1379     memset(&ret, 0, sizeof(ret));
1380     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_TYPE,
1381              (xdrproc_t) xdr_void, (char *) NULL,
1382              (xdrproc_t) xdr_remote_connect_get_type_ret, (char *) &ret) == -1)
1383         goto done;
1384 
1385     /* Stash. */
1386     rv = priv->type = ret.type;
1387 
1388  done:
1389     remoteDriverUnlock(priv);
1390     return rv;
1391 }
1392 
remoteConnectIsSecure(virConnectPtr conn)1393 static int remoteConnectIsSecure(virConnectPtr conn)
1394 {
1395     int rv = -1;
1396     struct private_data *priv = conn->privateData;
1397     remote_connect_is_secure_ret ret;
1398     remoteDriverLock(priv);
1399 
1400     memset(&ret, 0, sizeof(ret));
1401     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_IS_SECURE,
1402              (xdrproc_t) xdr_void, (char *) NULL,
1403              (xdrproc_t) xdr_remote_connect_is_secure_ret, (char *) &ret) == -1)
1404         goto done;
1405 
1406     /* We claim to be secure, if the remote driver
1407      * transport itself is secure, and the remote
1408      * HV connection is secure
1409      *
1410      * ie, we don't want to claim to be secure if the
1411      * remote driver is used to connect to a XenD
1412      * driver using unencrypted HTTP:/// access
1413      */
1414     rv = priv->is_secure && ret.secure ? 1 : 0;
1415 
1416  done:
1417     remoteDriverUnlock(priv);
1418     return rv;
1419 }
1420 
remoteConnectIsEncrypted(virConnectPtr conn)1421 static int remoteConnectIsEncrypted(virConnectPtr conn)
1422 {
1423     int rv = -1;
1424     bool encrypted;
1425     struct private_data *priv = conn->privateData;
1426     remote_connect_is_secure_ret ret;
1427     remoteDriverLock(priv);
1428 
1429     memset(&ret, 0, sizeof(ret));
1430     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_IS_SECURE,
1431              (xdrproc_t) xdr_void, (char *) NULL,
1432              (xdrproc_t) xdr_remote_connect_is_secure_ret, (char *) &ret) == -1)
1433         goto done;
1434 
1435     encrypted = virNetClientIsEncrypted(priv->client);
1436 
1437     /* We claim to be encrypted, if the remote driver
1438      * transport itself is encrypted, and the remote
1439      * HV connection is secure.
1440      *
1441      * Yes, we really don't check the remote 'encrypted'
1442      * option, since it will almost always be false,
1443      * even if secure (eg UNIX sockets).
1444      */
1445     rv = encrypted && ret.secure ? 1 : 0;
1446 
1447  done:
1448     remoteDriverUnlock(priv);
1449     return rv;
1450 }
1451 
1452 static int
remoteNodeGetCPUStats(virConnectPtr conn,int cpuNum,virNodeCPUStatsPtr params,int * nparams,unsigned int flags)1453 remoteNodeGetCPUStats(virConnectPtr conn,
1454                       int cpuNum,
1455                       virNodeCPUStatsPtr params, int *nparams,
1456                       unsigned int flags)
1457 {
1458     int rv = -1;
1459     remote_node_get_cpu_stats_args args;
1460     remote_node_get_cpu_stats_ret ret;
1461     size_t i;
1462     struct private_data *priv = conn->privateData;
1463 
1464     remoteDriverLock(priv);
1465 
1466     args.nparams = *nparams;
1467     args.cpuNum = cpuNum;
1468     args.flags = flags;
1469 
1470     memset(&ret, 0, sizeof(ret));
1471     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_CPU_STATS,
1472              (xdrproc_t) xdr_remote_node_get_cpu_stats_args,
1473              (char *) &args,
1474              (xdrproc_t) xdr_remote_node_get_cpu_stats_ret,
1475              (char *) &ret) == -1)
1476         goto done;
1477 
1478     /* Check the length of the returned list carefully. */
1479     if (ret.params.params_len > REMOTE_NODE_CPU_STATS_MAX ||
1480         ret.params.params_len > *nparams) {
1481         virReportError(VIR_ERR_RPC, "%s",
1482                        _("remoteNodeGetCPUStats: "
1483                          "returned number of stats exceeds limit"));
1484         goto cleanup;
1485     }
1486     /* Handle the case when the caller does not know the number of stats
1487      * and is asking for the number of stats supported
1488      */
1489     if (*nparams == 0) {
1490         *nparams = ret.nparams;
1491         rv = 0;
1492         goto cleanup;
1493     }
1494 
1495     *nparams = ret.params.params_len;
1496 
1497     /* Deserialise the result. */
1498     for (i = 0; i < *nparams; ++i) {
1499         if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) < 0) {
1500             virReportError(VIR_ERR_INTERNAL_ERROR,
1501                            _("Stats %s too big for destination"),
1502                            ret.params.params_val[i].field);
1503             goto cleanup;
1504         }
1505         params[i].value = ret.params.params_val[i].value;
1506     }
1507 
1508     rv = 0;
1509 
1510  cleanup:
1511     xdr_free((xdrproc_t) xdr_remote_node_get_cpu_stats_ret, (char *) &ret);
1512  done:
1513     remoteDriverUnlock(priv);
1514     return rv;
1515 }
1516 
1517 static int
remoteNodeGetMemoryStats(virConnectPtr conn,int cellNum,virNodeMemoryStatsPtr params,int * nparams,unsigned int flags)1518 remoteNodeGetMemoryStats(virConnectPtr conn,
1519                          int cellNum,
1520                          virNodeMemoryStatsPtr params,
1521                          int *nparams,
1522                          unsigned int flags)
1523 {
1524     int rv = -1;
1525     remote_node_get_memory_stats_args args;
1526     remote_node_get_memory_stats_ret ret;
1527     size_t i;
1528     struct private_data *priv = conn->privateData;
1529 
1530     remoteDriverLock(priv);
1531 
1532     args.nparams = *nparams;
1533     args.cellNum = cellNum;
1534     args.flags = flags;
1535 
1536     memset(&ret, 0, sizeof(ret));
1537     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_MEMORY_STATS,
1538              (xdrproc_t) xdr_remote_node_get_memory_stats_args, (char *) &args,
1539              (xdrproc_t) xdr_remote_node_get_memory_stats_ret, (char *) &ret) == -1)
1540         goto done;
1541 
1542     /* Check the length of the returned list carefully. */
1543     if (ret.params.params_len > REMOTE_NODE_MEMORY_STATS_MAX ||
1544         ret.params.params_len > *nparams) {
1545         virReportError(VIR_ERR_RPC, "%s",
1546                        _("remoteNodeGetMemoryStats: "
1547                          "returned number of stats exceeds limit"));
1548         goto cleanup;
1549     }
1550     /* Handle the case when the caller does not know the number of stats
1551      * and is asking for the number of stats supported
1552      */
1553     if (*nparams == 0) {
1554         *nparams = ret.nparams;
1555         rv = 0;
1556         goto cleanup;
1557     }
1558 
1559     *nparams = ret.params.params_len;
1560 
1561     /* Deserialise the result. */
1562     for (i = 0; i < *nparams; ++i) {
1563         if (virStrcpyStatic(params[i].field, ret.params.params_val[i].field) < 0) {
1564             virReportError(VIR_ERR_INTERNAL_ERROR,
1565                            _("Stats %s too big for destination"),
1566                            ret.params.params_val[i].field);
1567             goto cleanup;
1568         }
1569         params[i].value = ret.params.params_val[i].value;
1570     }
1571 
1572     rv = 0;
1573 
1574  cleanup:
1575     xdr_free((xdrproc_t) xdr_remote_node_get_memory_stats_ret, (char *) &ret);
1576  done:
1577     remoteDriverUnlock(priv);
1578     return rv;
1579 }
1580 
1581 static int
remoteNodeGetCellsFreeMemory(virConnectPtr conn,unsigned long long * freeMems,int startCell,int maxCells)1582 remoteNodeGetCellsFreeMemory(virConnectPtr conn,
1583                              unsigned long long *freeMems,
1584                              int startCell,
1585                              int maxCells)
1586 {
1587     int rv = -1;
1588     remote_node_get_cells_free_memory_args args;
1589     remote_node_get_cells_free_memory_ret ret;
1590     size_t i;
1591     struct private_data *priv = conn->privateData;
1592 
1593     remoteDriverLock(priv);
1594 
1595     if (maxCells > REMOTE_NODE_MAX_CELLS) {
1596         virReportError(VIR_ERR_RPC,
1597                        _("too many NUMA cells: %d > %d"),
1598                        maxCells, REMOTE_NODE_MAX_CELLS);
1599         goto done;
1600     }
1601 
1602     args.startCell = startCell;
1603     args.maxcells = maxCells;
1604 
1605     memset(&ret, 0, sizeof(ret));
1606     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY,
1607              (xdrproc_t) xdr_remote_node_get_cells_free_memory_args, (char *)&args,
1608              (xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *)&ret) == -1)
1609         goto done;
1610 
1611     for (i = 0; i < ret.cells.cells_len; i++)
1612         freeMems[i] = ret.cells.cells_val[i];
1613 
1614     xdr_free((xdrproc_t) xdr_remote_node_get_cells_free_memory_ret, (char *) &ret);
1615 
1616     rv = ret.cells.cells_len;
1617 
1618  done:
1619     remoteDriverUnlock(priv);
1620     return rv;
1621 }
1622 
1623 static int
remoteConnectListDomains(virConnectPtr conn,int * ids,int maxids)1624 remoteConnectListDomains(virConnectPtr conn, int *ids, int maxids)
1625 {
1626     int rv = -1;
1627     size_t i;
1628     remote_connect_list_domains_args args;
1629     remote_connect_list_domains_ret ret;
1630     struct private_data *priv = conn->privateData;
1631 
1632     remoteDriverLock(priv);
1633 
1634     if (maxids > REMOTE_DOMAIN_LIST_MAX) {
1635         virReportError(VIR_ERR_RPC,
1636                        _("Too many domains '%d' for limit '%d'"),
1637                        maxids, REMOTE_DOMAIN_LIST_MAX);
1638         goto done;
1639     }
1640     args.maxids = maxids;
1641 
1642     memset(&ret, 0, sizeof(ret));
1643     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_LIST_DOMAINS,
1644              (xdrproc_t) xdr_remote_connect_list_domains_args, (char *) &args,
1645              (xdrproc_t) xdr_remote_connect_list_domains_ret, (char *) &ret) == -1)
1646         goto done;
1647 
1648     if (ret.ids.ids_len > maxids) {
1649         virReportError(VIR_ERR_RPC,
1650                        _("Too many domains '%d' for limit '%d'"),
1651                        ret.ids.ids_len, maxids);
1652         goto cleanup;
1653     }
1654 
1655     for (i = 0; i < ret.ids.ids_len; ++i)
1656         ids[i] = ret.ids.ids_val[i];
1657 
1658     rv = ret.ids.ids_len;
1659 
1660  cleanup:
1661     xdr_free((xdrproc_t) xdr_remote_connect_list_domains_ret, (char *) &ret);
1662 
1663  done:
1664     remoteDriverUnlock(priv);
1665     return rv;
1666 }
1667 
1668 static int
remoteDeserializeDomainDiskErrors(remote_domain_disk_error * ret_errors_val,u_int ret_errors_len,int limit,virDomainDiskErrorPtr errors,int maxerrors)1669 remoteDeserializeDomainDiskErrors(remote_domain_disk_error *ret_errors_val,
1670                                   u_int ret_errors_len,
1671                                   int limit,
1672                                   virDomainDiskErrorPtr errors,
1673                                   int maxerrors)
1674 {
1675     size_t i = 0;
1676     size_t j;
1677 
1678     if (ret_errors_len > limit || ret_errors_len > maxerrors) {
1679         virReportError(VIR_ERR_RPC, "%s",
1680                        _("returned number of disk errors exceeds limit"));
1681         goto error;
1682     }
1683 
1684     for (i = 0; i < ret_errors_len; i++) {
1685         errors[i].disk = g_strdup(ret_errors_val[i].disk);
1686         errors[i].error = ret_errors_val[i].error;
1687     }
1688 
1689     return 0;
1690 
1691  error:
1692     for (j = 0; j < i; j++)
1693         VIR_FREE(errors[j].disk);
1694 
1695     return -1;
1696 }
1697 
1698 static int
remoteDomainBlockStatsFlags(virDomainPtr domain,const char * path,virTypedParameterPtr params,int * nparams,unsigned int flags)1699 remoteDomainBlockStatsFlags(virDomainPtr domain,
1700                             const char *path,
1701                             virTypedParameterPtr params,
1702                             int *nparams,
1703                             unsigned int flags)
1704 {
1705     int rv = -1;
1706     remote_domain_block_stats_flags_args args;
1707     remote_domain_block_stats_flags_ret ret;
1708     struct private_data *priv = domain->conn->privateData;
1709 
1710     remoteDriverLock(priv);
1711 
1712     make_nonnull_domain(&args.dom, domain);
1713     args.nparams = *nparams;
1714     args.path = (char *) path;
1715     args.flags = flags;
1716 
1717     memset(&ret, 0, sizeof(ret));
1718     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS,
1719              (xdrproc_t) xdr_remote_domain_block_stats_flags_args, (char *) &args,
1720              (xdrproc_t) xdr_remote_domain_block_stats_flags_ret, (char *) &ret) == -1)
1721         goto done;
1722 
1723     /* Check the length of the returned list carefully. */
1724     if (ret.params.params_len > REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX ||
1725         ret.params.params_len > *nparams) {
1726         virReportError(VIR_ERR_RPC, "%s",
1727                        _("remoteDomainBlockStatsFlags: "
1728                          "returned number of stats exceeds limit"));
1729         goto cleanup;
1730     }
1731 
1732     /* Handle the case when the caller does not know the number of stats
1733      * and is asking for the number of stats supported
1734      */
1735     if (*nparams == 0) {
1736         *nparams = ret.nparams;
1737         rv = 0;
1738         goto cleanup;
1739     }
1740 
1741     *nparams = ret.params.params_len;
1742 
1743     /* Deserialize the result. */
1744     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
1745                                   ret.params.params_len,
1746                                   REMOTE_DOMAIN_BLOCK_STATS_PARAMETERS_MAX,
1747                                   &params,
1748                                   nparams) < 0)
1749         goto cleanup;
1750 
1751     rv = 0;
1752 
1753  cleanup:
1754     xdr_free((xdrproc_t) xdr_remote_domain_block_stats_flags_ret,
1755              (char *) &ret);
1756  done:
1757     remoteDriverUnlock(priv);
1758     return rv;
1759 }
1760 
1761 static int
remoteDomainGetMemoryParameters(virDomainPtr domain,virTypedParameterPtr params,int * nparams,unsigned int flags)1762 remoteDomainGetMemoryParameters(virDomainPtr domain,
1763                                 virTypedParameterPtr params, int *nparams,
1764                                 unsigned int flags)
1765 {
1766     int rv = -1;
1767     remote_domain_get_memory_parameters_args args;
1768     remote_domain_get_memory_parameters_ret ret;
1769     struct private_data *priv = domain->conn->privateData;
1770 
1771     remoteDriverLock(priv);
1772 
1773     make_nonnull_domain(&args.dom, domain);
1774     args.nparams = *nparams;
1775     args.flags = flags;
1776 
1777     memset(&ret, 0, sizeof(ret));
1778     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS,
1779              (xdrproc_t) xdr_remote_domain_get_memory_parameters_args, (char *) &args,
1780              (xdrproc_t) xdr_remote_domain_get_memory_parameters_ret, (char *) &ret) == -1)
1781         goto done;
1782 
1783     /* Handle the case when the caller does not know the number of parameters
1784      * and is asking for the number of parameters supported
1785      */
1786     if (*nparams == 0) {
1787         *nparams = ret.nparams;
1788         rv = 0;
1789         goto cleanup;
1790     }
1791 
1792     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
1793                                   ret.params.params_len,
1794                                   REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX,
1795                                   &params,
1796                                   nparams) < 0)
1797         goto cleanup;
1798 
1799     rv = 0;
1800 
1801  cleanup:
1802     xdr_free((xdrproc_t) xdr_remote_domain_get_memory_parameters_ret,
1803              (char *) &ret);
1804  done:
1805     remoteDriverUnlock(priv);
1806     return rv;
1807 }
1808 
1809 static int
remoteDomainGetNumaParameters(virDomainPtr domain,virTypedParameterPtr params,int * nparams,unsigned int flags)1810 remoteDomainGetNumaParameters(virDomainPtr domain,
1811                               virTypedParameterPtr params, int *nparams,
1812                               unsigned int flags)
1813 {
1814     int rv = -1;
1815     remote_domain_get_numa_parameters_args args;
1816     remote_domain_get_numa_parameters_ret ret;
1817     struct private_data *priv = domain->conn->privateData;
1818 
1819     remoteDriverLock(priv);
1820 
1821     make_nonnull_domain(&args.dom, domain);
1822     args.nparams = *nparams;
1823     args.flags = flags;
1824 
1825     memset(&ret, 0, sizeof(ret));
1826     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS,
1827              (xdrproc_t) xdr_remote_domain_get_numa_parameters_args, (char *) &args,
1828              (xdrproc_t) xdr_remote_domain_get_numa_parameters_ret, (char *) &ret) == -1)
1829         goto done;
1830 
1831     /* Handle the case when the caller does not know the number of parameters
1832      * and is asking for the number of parameters supported
1833      */
1834     if (*nparams == 0) {
1835         *nparams = ret.nparams;
1836         rv = 0;
1837         goto cleanup;
1838     }
1839 
1840     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
1841                                   ret.params.params_len,
1842                                   REMOTE_DOMAIN_NUMA_PARAMETERS_MAX,
1843                                   &params,
1844                                   nparams) < 0)
1845         goto cleanup;
1846 
1847     rv = 0;
1848 
1849  cleanup:
1850     xdr_free((xdrproc_t) xdr_remote_domain_get_numa_parameters_ret,
1851              (char *) &ret);
1852  done:
1853     remoteDriverUnlock(priv);
1854     return rv;
1855 }
1856 
1857 static int
remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,virTypedParameterPtr * params,int * nparams,unsigned int flags)1858 remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
1859                                   virTypedParameterPtr *params,
1860                                   int *nparams,
1861                                   unsigned int flags)
1862 {
1863     int rv = -1;
1864     remote_domain_get_launch_security_info_args args;
1865     remote_domain_get_launch_security_info_ret ret;
1866     struct private_data *priv = domain->conn->privateData;
1867 
1868     remoteDriverLock(priv);
1869 
1870     make_nonnull_domain(&args.dom, domain);
1871     args.flags = flags;
1872 
1873     memset(&ret, 0, sizeof(ret));
1874     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
1875              (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, (char *) &args,
1876              (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char *) &ret) == -1)
1877         goto done;
1878 
1879     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
1880                                   ret.params.params_len,
1881                                   REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
1882                                   params,
1883                                   nparams) < 0)
1884         goto cleanup;
1885 
1886     rv = 0;
1887 
1888  cleanup:
1889     xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
1890              (char *) &ret);
1891  done:
1892     remoteDriverUnlock(priv);
1893     return rv;
1894 }
1895 
1896 static int
remoteDomainGetPerfEvents(virDomainPtr domain,virTypedParameterPtr * params,int * nparams,unsigned int flags)1897 remoteDomainGetPerfEvents(virDomainPtr domain,
1898                           virTypedParameterPtr *params,
1899                           int *nparams,
1900                           unsigned int flags)
1901 {
1902     int rv = -1;
1903     remote_domain_get_perf_events_args args;
1904     remote_domain_get_perf_events_ret ret;
1905     struct private_data *priv = domain->conn->privateData;
1906 
1907     remoteDriverLock(priv);
1908 
1909     make_nonnull_domain(&args.dom, domain);
1910     args.flags = flags;
1911 
1912     memset(&ret, 0, sizeof(ret));
1913     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_PERF_EVENTS,
1914              (xdrproc_t) xdr_remote_domain_get_perf_events_args, (char *) &args,
1915              (xdrproc_t) xdr_remote_domain_get_perf_events_ret, (char *) &ret) == -1)
1916         goto done;
1917 
1918     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
1919                                   ret.params.params_len,
1920                                   REMOTE_DOMAIN_PERF_EVENTS_MAX,
1921                                   params,
1922                                   nparams) < 0)
1923         goto cleanup;
1924 
1925     rv = 0;
1926 
1927  cleanup:
1928     xdr_free((xdrproc_t) xdr_remote_domain_get_perf_events_ret,
1929              (char *) &ret);
1930  done:
1931     remoteDriverUnlock(priv);
1932     return rv;
1933 }
1934 
1935 static int
remoteDomainGetBlkioParameters(virDomainPtr domain,virTypedParameterPtr params,int * nparams,unsigned int flags)1936 remoteDomainGetBlkioParameters(virDomainPtr domain,
1937                                virTypedParameterPtr params, int *nparams,
1938                                unsigned int flags)
1939 {
1940     int rv = -1;
1941     remote_domain_get_blkio_parameters_args args;
1942     remote_domain_get_blkio_parameters_ret ret;
1943     struct private_data *priv = domain->conn->privateData;
1944 
1945     remoteDriverLock(priv);
1946 
1947     make_nonnull_domain(&args.dom, domain);
1948     args.nparams = *nparams;
1949     args.flags = flags;
1950 
1951     memset(&ret, 0, sizeof(ret));
1952     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS,
1953              (xdrproc_t) xdr_remote_domain_get_blkio_parameters_args, (char *) &args,
1954              (xdrproc_t) xdr_remote_domain_get_blkio_parameters_ret, (char *) &ret) == -1)
1955         goto done;
1956 
1957     /* Handle the case when the caller does not know the number of parameters
1958      * and is asking for the number of parameters supported
1959      */
1960     if (*nparams == 0) {
1961         *nparams = ret.nparams;
1962         rv = 0;
1963         goto cleanup;
1964     }
1965 
1966     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
1967                                   ret.params.params_len,
1968                                   REMOTE_DOMAIN_BLKIO_PARAMETERS_MAX,
1969                                   &params,
1970                                   nparams) < 0)
1971         goto cleanup;
1972 
1973     rv = 0;
1974 
1975  cleanup:
1976     xdr_free((xdrproc_t) xdr_remote_domain_get_blkio_parameters_ret,
1977              (char *) &ret);
1978  done:
1979     remoteDriverUnlock(priv);
1980     return rv;
1981 }
1982 
1983 static int
remoteDomainGetVcpuPinInfo(virDomainPtr domain,int ncpumaps,unsigned char * cpumaps,int maplen,unsigned int flags)1984 remoteDomainGetVcpuPinInfo(virDomainPtr domain,
1985                            int ncpumaps,
1986                            unsigned char *cpumaps,
1987                            int maplen,
1988                            unsigned int flags)
1989 {
1990     int rv = -1;
1991     size_t i;
1992     remote_domain_get_vcpu_pin_info_args args;
1993     remote_domain_get_vcpu_pin_info_ret ret;
1994     struct private_data *priv = domain->conn->privateData;
1995 
1996     remoteDriverLock(priv);
1997 
1998     if (ncpumaps > REMOTE_VCPUINFO_MAX) {
1999         virReportError(VIR_ERR_RPC,
2000                        _("vCPU count exceeds maximum: %d > %d"),
2001                        ncpumaps, REMOTE_VCPUINFO_MAX);
2002         goto done;
2003     }
2004 
2005     if (VIR_INT_MULTIPLY_OVERFLOW(ncpumaps, maplen) ||
2006         ncpumaps * maplen > REMOTE_CPUMAPS_MAX) {
2007         virReportError(VIR_ERR_RPC,
2008                        _("vCPU map buffer length exceeds maximum: %d > %d"),
2009                        ncpumaps * maplen, REMOTE_CPUMAPS_MAX);
2010         goto done;
2011     }
2012 
2013     make_nonnull_domain(&args.dom, domain);
2014     args.ncpumaps = ncpumaps;
2015     args.maplen = maplen;
2016     args.flags = flags;
2017 
2018     memset(&ret, 0, sizeof(ret));
2019 
2020     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO,
2021              (xdrproc_t) xdr_remote_domain_get_vcpu_pin_info_args,
2022              (char *) &args,
2023              (xdrproc_t) xdr_remote_domain_get_vcpu_pin_info_ret,
2024              (char *) &ret) == -1)
2025         goto done;
2026 
2027     if (ret.num > ncpumaps) {
2028         virReportError(VIR_ERR_RPC,
2029                        _("host reports too many vCPUs: %d > %d"),
2030                        ret.num, ncpumaps);
2031         goto cleanup;
2032     }
2033 
2034     if (ret.cpumaps.cpumaps_len > ncpumaps * maplen) {
2035         virReportError(VIR_ERR_RPC,
2036                        _("host reports map buffer length exceeds maximum: %d > %d"),
2037                        ret.cpumaps.cpumaps_len, ncpumaps * maplen);
2038         goto cleanup;
2039     }
2040 
2041     memset(cpumaps, 0, ncpumaps * maplen);
2042 
2043     for (i = 0; i < ret.cpumaps.cpumaps_len; ++i)
2044         cpumaps[i] = ret.cpumaps.cpumaps_val[i];
2045 
2046     rv = ret.num;
2047 
2048  cleanup:
2049     xdr_free((xdrproc_t) xdr_remote_domain_get_vcpu_pin_info_ret, (char *) &ret);
2050 
2051  done:
2052     remoteDriverUnlock(priv);
2053     return rv;
2054 }
2055 
2056 static int
remoteDomainPinEmulator(virDomainPtr dom,unsigned char * cpumap,int cpumaplen,unsigned int flags)2057 remoteDomainPinEmulator(virDomainPtr dom,
2058                         unsigned char *cpumap,
2059                         int cpumaplen,
2060                         unsigned int flags)
2061 {
2062     int rv = -1;
2063     struct private_data *priv = dom->conn->privateData;
2064     remote_domain_pin_emulator_args args;
2065 
2066     remoteDriverLock(priv);
2067 
2068     if (cpumaplen > REMOTE_CPUMAP_MAX) {
2069         virReportError(VIR_ERR_RPC,
2070                        _("%s length greater than maximum: %d > %d"),
2071                        "cpumap", cpumaplen, REMOTE_CPUMAP_MAX);
2072         goto done;
2073     }
2074 
2075     make_nonnull_domain(&args.dom, dom);
2076     args.cpumap.cpumap_val = (char *)cpumap;
2077     args.cpumap.cpumap_len = cpumaplen;
2078     args.flags = flags;
2079 
2080     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_PIN_EMULATOR,
2081              (xdrproc_t) xdr_remote_domain_pin_emulator_args,
2082              (char *) &args,
2083              (xdrproc_t) xdr_void, (char *) NULL) == -1) {
2084         goto done;
2085     }
2086 
2087     rv = 0;
2088 
2089  done:
2090     remoteDriverUnlock(priv);
2091     return rv;
2092 }
2093 
2094 
2095 static int
remoteDomainGetEmulatorPinInfo(virDomainPtr domain,unsigned char * cpumaps,int maplen,unsigned int flags)2096 remoteDomainGetEmulatorPinInfo(virDomainPtr domain,
2097                                unsigned char *cpumaps,
2098                                int maplen,
2099                                unsigned int flags)
2100 {
2101     int rv = -1;
2102     size_t i;
2103     remote_domain_get_emulator_pin_info_args args;
2104     remote_domain_get_emulator_pin_info_ret ret;
2105     struct private_data *priv = domain->conn->privateData;
2106 
2107     remoteDriverLock(priv);
2108 
2109     /* There is only one cpumap for all emulator threads */
2110     if (maplen > REMOTE_CPUMAPS_MAX) {
2111         virReportError(VIR_ERR_RPC,
2112                        _("vCPU map buffer length exceeds maximum: %d > %d"),
2113                        maplen, REMOTE_CPUMAPS_MAX);
2114         goto done;
2115     }
2116 
2117     make_nonnull_domain(&args.dom, domain);
2118     args.maplen = maplen;
2119     args.flags = flags;
2120 
2121     memset(&ret, 0, sizeof(ret));
2122 
2123     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_EMULATOR_PIN_INFO,
2124              (xdrproc_t) xdr_remote_domain_get_emulator_pin_info_args,
2125              (char *) &args,
2126              (xdrproc_t) xdr_remote_domain_get_emulator_pin_info_ret,
2127              (char *) &ret) == -1)
2128         goto done;
2129 
2130     if (ret.cpumaps.cpumaps_len > maplen) {
2131         virReportError(VIR_ERR_RPC,
2132                        _("host reports map buffer length exceeds maximum: %d > %d"),
2133                        ret.cpumaps.cpumaps_len, maplen);
2134         goto cleanup;
2135     }
2136 
2137     memset(cpumaps, 0, maplen);
2138 
2139     for (i = 0; i < ret.cpumaps.cpumaps_len; ++i)
2140         cpumaps[i] = ret.cpumaps.cpumaps_val[i];
2141 
2142     rv = ret.ret;
2143 
2144  cleanup:
2145     xdr_free((xdrproc_t) xdr_remote_domain_get_emulator_pin_info_ret,
2146              (char *) &ret);
2147 
2148  done:
2149     remoteDriverUnlock(priv);
2150     return rv;
2151 }
2152 
2153 static int
remoteDomainGetVcpus(virDomainPtr domain,virVcpuInfoPtr info,int maxinfo,unsigned char * cpumaps,int maplen)2154 remoteDomainGetVcpus(virDomainPtr domain,
2155                      virVcpuInfoPtr info,
2156                      int maxinfo,
2157                      unsigned char *cpumaps,
2158                      int maplen)
2159 {
2160     int rv = -1;
2161     size_t i;
2162     remote_domain_get_vcpus_args args;
2163     remote_domain_get_vcpus_ret ret;
2164     struct private_data *priv = domain->conn->privateData;
2165 
2166     remoteDriverLock(priv);
2167 
2168     if (maxinfo > REMOTE_VCPUINFO_MAX) {
2169         virReportError(VIR_ERR_RPC,
2170                        _("vCPU count exceeds maximum: %d > %d"),
2171                        maxinfo, REMOTE_VCPUINFO_MAX);
2172         goto done;
2173     }
2174     if (VIR_INT_MULTIPLY_OVERFLOW(maxinfo, maplen) ||
2175         maxinfo * maplen > REMOTE_CPUMAPS_MAX) {
2176         virReportError(VIR_ERR_RPC,
2177                        _("vCPU map buffer length exceeds maximum: %d > %d"),
2178                        maxinfo * maplen, REMOTE_CPUMAPS_MAX);
2179         goto done;
2180     }
2181 
2182     make_nonnull_domain(&args.dom, domain);
2183     args.maxinfo = maxinfo;
2184     args.maplen = maplen;
2185 
2186     memset(&ret, 0, sizeof(ret));
2187     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS,
2188              (xdrproc_t) xdr_remote_domain_get_vcpus_args, (char *) &args,
2189              (xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret) == -1)
2190         goto done;
2191 
2192     if (ret.info.info_len > maxinfo) {
2193         virReportError(VIR_ERR_RPC,
2194                        _("host reports too many vCPUs: %d > %d"),
2195                        ret.info.info_len, maxinfo);
2196         goto cleanup;
2197     }
2198     if (ret.cpumaps.cpumaps_len > maxinfo * maplen) {
2199         virReportError(VIR_ERR_RPC,
2200                        _("host reports map buffer length exceeds maximum: %d > %d"),
2201                        ret.cpumaps.cpumaps_len, maxinfo * maplen);
2202         goto cleanup;
2203     }
2204 
2205     memset(info, 0, sizeof(virVcpuInfo) * maxinfo);
2206     memset(cpumaps, 0, maxinfo * maplen);
2207 
2208     for (i = 0; i < ret.info.info_len; ++i) {
2209         info[i].number = ret.info.info_val[i].number;
2210         info[i].state = ret.info.info_val[i].state;
2211         info[i].cpuTime = ret.info.info_val[i].cpu_time;
2212         info[i].cpu = ret.info.info_val[i].cpu;
2213     }
2214 
2215     for (i = 0; i < ret.cpumaps.cpumaps_len; ++i)
2216         cpumaps[i] = ret.cpumaps.cpumaps_val[i];
2217 
2218     rv = ret.info.info_len;
2219 
2220  cleanup:
2221     xdr_free((xdrproc_t) xdr_remote_domain_get_vcpus_ret, (char *) &ret);
2222 
2223  done:
2224     remoteDriverUnlock(priv);
2225     return rv;
2226 }
2227 
2228 static int
remoteDomainGetIOThreadInfo(virDomainPtr dom,virDomainIOThreadInfoPtr ** info,unsigned int flags)2229 remoteDomainGetIOThreadInfo(virDomainPtr dom,
2230                             virDomainIOThreadInfoPtr **info,
2231                             unsigned int flags)
2232 {
2233     int rv = -1;
2234     size_t i;
2235     struct private_data *priv = dom->conn->privateData;
2236     remote_domain_get_iothread_info_args args;
2237     remote_domain_get_iothread_info_ret ret;
2238     remote_domain_iothread_info *src;
2239 
2240     remoteDriverLock(priv);
2241 
2242     make_nonnull_domain(&args.dom, dom);
2243 
2244     args.flags = flags;
2245 
2246     memset(&ret, 0, sizeof(ret));
2247 
2248     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_IOTHREAD_INFO,
2249              (xdrproc_t)xdr_remote_domain_get_iothread_info_args,
2250              (char *)&args,
2251              (xdrproc_t)xdr_remote_domain_get_iothread_info_ret,
2252              (char *)&ret) == -1)
2253         goto done;
2254 
2255     if (ret.info.info_len > REMOTE_IOTHREAD_INFO_MAX) {
2256         virReportError(VIR_ERR_INTERNAL_ERROR,
2257                        _("Too many IOThreads in info: %d for limit %d"),
2258                        ret.info.info_len, REMOTE_IOTHREAD_INFO_MAX);
2259         goto cleanup;
2260     }
2261 
2262     if (info) {
2263         virDomainIOThreadInfoPtr *info_ret = NULL;
2264 
2265         if (!ret.info.info_len) {
2266             *info = NULL;
2267             rv = ret.ret;
2268             goto cleanup;
2269         }
2270 
2271         info_ret = g_new0(virDomainIOThreadInfoPtr, ret.info.info_len);
2272 
2273         for (i = 0; i < ret.info.info_len; i++) {
2274             src = &ret.info.info_val[i];
2275 
2276             info_ret[i] = g_new0(virDomainIOThreadInfo, 1);
2277 
2278             info_ret[i]->iothread_id = src->iothread_id;
2279             info_ret[i]->cpumap = g_new0(unsigned char, src->cpumap.cpumap_len);
2280             memcpy(info_ret[i]->cpumap, src->cpumap.cpumap_val,
2281                    src->cpumap.cpumap_len);
2282             info_ret[i]->cpumaplen = src->cpumap.cpumap_len;
2283         }
2284         *info = info_ret;
2285     }
2286 
2287     rv = ret.ret;
2288 
2289  cleanup:
2290     xdr_free((xdrproc_t)xdr_remote_domain_get_iothread_info_ret,
2291              (char *) &ret);
2292 
2293  done:
2294     remoteDriverUnlock(priv);
2295     return rv;
2296 }
2297 
2298 static int
remoteDomainGetSecurityLabel(virDomainPtr domain,virSecurityLabelPtr seclabel)2299 remoteDomainGetSecurityLabel(virDomainPtr domain, virSecurityLabelPtr seclabel)
2300 {
2301     remote_domain_get_security_label_args args;
2302     remote_domain_get_security_label_ret ret;
2303     struct private_data *priv = domain->conn->privateData;
2304     int rv = -1;
2305 
2306     remoteDriverLock(priv);
2307 
2308     make_nonnull_domain(&args.dom, domain);
2309     memset(&ret, 0, sizeof(ret));
2310     memset(seclabel, 0, sizeof(*seclabel));
2311 
2312     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL,
2313              (xdrproc_t) xdr_remote_domain_get_security_label_args, (char *)&args,
2314              (xdrproc_t) xdr_remote_domain_get_security_label_ret, (char *)&ret) == -1) {
2315         goto done;
2316     }
2317 
2318     if (ret.label.label_val != NULL) {
2319         if (virStrcpyStatic(seclabel->label, ret.label.label_val) < 0) {
2320             virReportError(VIR_ERR_RPC, _("security label exceeds maximum: %zu"),
2321                            sizeof(seclabel->label) - 1);
2322             goto cleanup;
2323         }
2324         seclabel->enforcing = ret.enforcing;
2325     }
2326 
2327     rv = 0;
2328 
2329  cleanup:
2330     xdr_free((xdrproc_t) xdr_remote_domain_get_security_label_ret, (char *)&ret);
2331 
2332  done:
2333     remoteDriverUnlock(priv);
2334     return rv;
2335 }
2336 
2337 static int
remoteDomainGetSecurityLabelList(virDomainPtr domain,virSecurityLabelPtr * seclabels)2338 remoteDomainGetSecurityLabelList(virDomainPtr domain, virSecurityLabelPtr* seclabels)
2339 {
2340     remote_domain_get_security_label_list_args args;
2341     remote_domain_get_security_label_list_ret ret;
2342     struct private_data *priv = domain->conn->privateData;
2343     size_t i;
2344     int rv = -1;
2345 
2346     remoteDriverLock(priv);
2347 
2348     make_nonnull_domain(&args.dom, domain);
2349     memset(&ret, 0, sizeof(ret));
2350 
2351     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST,
2352              (xdrproc_t) xdr_remote_domain_get_security_label_list_args, (char *)&args,
2353              (xdrproc_t) xdr_remote_domain_get_security_label_list_ret, (char *)&ret) == -1) {
2354         goto done;
2355     }
2356 
2357     *seclabels = g_new0(virSecurityLabel, ret.labels.labels_len);
2358 
2359     for (i = 0; i < ret.labels.labels_len; i++) {
2360         remote_domain_get_security_label_ret *cur = &ret.labels.labels_val[i];
2361         if (cur->label.label_val != NULL) {
2362             if (virStrcpyStatic((*seclabels)[i].label, cur->label.label_val) < 0) {
2363                 virReportError(VIR_ERR_RPC, _("security label exceeds maximum: %zd"),
2364                                sizeof((*seclabels)->label) - 1);
2365                 VIR_FREE(*seclabels);
2366                 goto cleanup;
2367             }
2368             (*seclabels)[i].enforcing = cur->enforcing;
2369         }
2370     }
2371     rv = ret.ret;
2372 
2373  cleanup:
2374     xdr_free((xdrproc_t) xdr_remote_domain_get_security_label_list_ret, (char *)&ret);
2375 
2376  done:
2377     remoteDriverUnlock(priv);
2378     return rv;
2379 }
2380 
2381 static int
remoteDomainGetState(virDomainPtr domain,int * state,int * reason,unsigned int flags)2382 remoteDomainGetState(virDomainPtr domain,
2383                      int *state,
2384                      int *reason,
2385                      unsigned int flags)
2386 {
2387     int rv = -1;
2388     remote_domain_get_state_args args;
2389     remote_domain_get_state_ret ret;
2390     struct private_data *priv = domain->conn->privateData;
2391 
2392     remoteDriverLock(priv);
2393 
2394     make_nonnull_domain(&args.dom, domain);
2395     args.flags = flags;
2396 
2397     memset(&ret, 0, sizeof(ret));
2398     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_STATE,
2399              (xdrproc_t) xdr_remote_domain_get_state_args, (char *) &args,
2400              (xdrproc_t) xdr_remote_domain_get_state_ret, (char *) &ret) == -1)
2401         goto done;
2402 
2403     *state = ret.state;
2404     if (reason)
2405         *reason = ret.reason;
2406 
2407     rv = 0;
2408 
2409  done:
2410     remoteDriverUnlock(priv);
2411     return rv;
2412 }
2413 
2414 static int
remoteNodeGetSecurityModel(virConnectPtr conn,virSecurityModelPtr secmodel)2415 remoteNodeGetSecurityModel(virConnectPtr conn, virSecurityModelPtr secmodel)
2416 {
2417     remote_node_get_security_model_ret ret;
2418     struct private_data *priv = conn->privateData;
2419     int rv = -1;
2420 
2421     remoteDriverLock(priv);
2422 
2423     memset(&ret, 0, sizeof(ret));
2424     memset(secmodel, 0, sizeof(*secmodel));
2425 
2426     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_SECURITY_MODEL,
2427              (xdrproc_t) xdr_void, NULL,
2428              (xdrproc_t) xdr_remote_node_get_security_model_ret, (char *)&ret) == -1) {
2429         goto done;
2430     }
2431 
2432     if (ret.model.model_val != NULL) {
2433         if (virStrcpyStatic(secmodel->model, ret.model.model_val) < 0) {
2434             virReportError(VIR_ERR_RPC, _("security model exceeds maximum: %zu"),
2435                            sizeof(secmodel->model) - 1);
2436             goto cleanup;
2437         }
2438     }
2439 
2440     if (ret.doi.doi_val != NULL) {
2441         if (virStrcpyStatic(secmodel->doi, ret.doi.doi_val) < 0) {
2442             virReportError(VIR_ERR_RPC, _("security doi exceeds maximum: %zu"),
2443                            sizeof(secmodel->doi) - 1);
2444             goto cleanup;
2445         }
2446     }
2447 
2448     rv = 0;
2449 
2450  cleanup:
2451     xdr_free((xdrproc_t) xdr_remote_node_get_security_model_ret, (char *)&ret);
2452 
2453  done:
2454     remoteDriverUnlock(priv);
2455     return rv;
2456 }
2457 
2458 static int
remoteDomainMigratePrepare(virConnectPtr dconn,char ** cookie,int * cookielen,const char * uri_in,char ** uri_out,unsigned long flags,const char * dname,unsigned long resource)2459 remoteDomainMigratePrepare(virConnectPtr dconn,
2460                            char **cookie, int *cookielen,
2461                            const char *uri_in, char **uri_out,
2462                            unsigned long flags, const char *dname,
2463                            unsigned long resource)
2464 {
2465     int rv = -1;
2466     remote_domain_migrate_prepare_args args;
2467     remote_domain_migrate_prepare_ret ret;
2468     struct private_data *priv = dconn->privateData;
2469 
2470     remoteDriverLock(priv);
2471 
2472     args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
2473     args.flags = flags;
2474     args.dname = dname == NULL ? NULL : (char **) &dname;
2475     args.resource = resource;
2476 
2477     memset(&ret, 0, sizeof(ret));
2478     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE,
2479              (xdrproc_t) xdr_remote_domain_migrate_prepare_args, (char *) &args,
2480              (xdrproc_t) xdr_remote_domain_migrate_prepare_ret, (char *) &ret) == -1)
2481         goto done;
2482 
2483     if (ret.cookie.cookie_len > 0) {
2484         *cookie = ret.cookie.cookie_val; /* Caller frees. */
2485         *cookielen = ret.cookie.cookie_len;
2486     }
2487     if (ret.uri_out)
2488         *uri_out = *ret.uri_out; /* Caller frees. */
2489 
2490     VIR_FREE(ret.uri_out);
2491     rv = 0;
2492 
2493  done:
2494     remoteDriverUnlock(priv);
2495     return rv;
2496 }
2497 
2498 static int
remoteDomainMigratePrepare2(virConnectPtr dconn,char ** cookie,int * cookielen,const char * uri_in,char ** uri_out,unsigned long flags,const char * dname,unsigned long resource,const char * dom_xml)2499 remoteDomainMigratePrepare2(virConnectPtr dconn,
2500                             char **cookie, int *cookielen,
2501                             const char *uri_in, char **uri_out,
2502                             unsigned long flags, const char *dname,
2503                             unsigned long resource,
2504                             const char *dom_xml)
2505 {
2506     int rv = -1;
2507     remote_domain_migrate_prepare2_args args;
2508     remote_domain_migrate_prepare2_ret ret;
2509     struct private_data *priv = dconn->privateData;
2510 
2511     remoteDriverLock(priv);
2512 
2513     args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
2514     args.flags = flags;
2515     args.dname = dname == NULL ? NULL : (char **) &dname;
2516     args.resource = resource;
2517     args.dom_xml = (char *) dom_xml;
2518 
2519     memset(&ret, 0, sizeof(ret));
2520     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2,
2521              (xdrproc_t) xdr_remote_domain_migrate_prepare2_args, (char *) &args,
2522              (xdrproc_t) xdr_remote_domain_migrate_prepare2_ret, (char *) &ret) == -1)
2523         goto done;
2524 
2525     if (ret.cookie.cookie_len > 0) {
2526         if (!cookie || !cookielen) {
2527             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2528                            _("caller ignores cookie or cookielen"));
2529             goto error;
2530         }
2531         *cookie = ret.cookie.cookie_val; /* Caller frees. */
2532         *cookielen = ret.cookie.cookie_len;
2533     }
2534     if (ret.uri_out) {
2535         if (!uri_out) {
2536             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2537                            _("caller ignores uri_out"));
2538             goto error;
2539         }
2540         *uri_out = *ret.uri_out; /* Caller frees. */
2541     }
2542 
2543     rv = 0;
2544 
2545  done:
2546     VIR_FREE(ret.uri_out);
2547     remoteDriverUnlock(priv);
2548     return rv;
2549  error:
2550     if (ret.cookie.cookie_len)
2551         VIR_FREE(ret.cookie.cookie_val);
2552     if (ret.uri_out)
2553         VIR_FREE(*ret.uri_out);
2554     goto done;
2555 }
2556 
2557 static int
remoteDomainCreate(virDomainPtr domain)2558 remoteDomainCreate(virDomainPtr domain)
2559 {
2560     int rv = -1;
2561     remote_domain_create_args args;
2562     remote_domain_lookup_by_uuid_args args2;
2563     remote_domain_lookup_by_uuid_ret ret2;
2564     struct private_data *priv = domain->conn->privateData;
2565 
2566     remoteDriverLock(priv);
2567 
2568     make_nonnull_domain(&args.dom, domain);
2569 
2570     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_CREATE,
2571              (xdrproc_t) xdr_remote_domain_create_args, (char *) &args,
2572              (xdrproc_t) xdr_void, (char *) NULL) == -1)
2573         goto done;
2574 
2575     /* Need to do a lookup figure out ID of newly started guest, because
2576      * bug in design of REMOTE_PROC_DOMAIN_CREATE means we aren't getting
2577      * it returned.
2578      */
2579     memcpy(args2.uuid, domain->uuid, VIR_UUID_BUFLEN);
2580     memset(&ret2, 0, sizeof(ret2));
2581     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID,
2582              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_args, (char *) &args2,
2583              (xdrproc_t) xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2) == -1)
2584         goto done;
2585 
2586     domain->id = ret2.dom.id;
2587     xdr_free((xdrproc_t) &xdr_remote_domain_lookup_by_uuid_ret, (char *) &ret2);
2588 
2589     rv = 0;
2590 
2591  done:
2592     remoteDriverUnlock(priv);
2593     return rv;
2594 }
2595 
2596 static char *
remoteDomainGetSchedulerType(virDomainPtr domain,int * nparams)2597 remoteDomainGetSchedulerType(virDomainPtr domain, int *nparams)
2598 {
2599     char *rv = NULL;
2600     remote_domain_get_scheduler_type_args args;
2601     remote_domain_get_scheduler_type_ret ret;
2602     struct private_data *priv = domain->conn->privateData;
2603 
2604     remoteDriverLock(priv);
2605 
2606     make_nonnull_domain(&args.dom, domain);
2607 
2608     memset(&ret, 0, sizeof(ret));
2609     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE,
2610              (xdrproc_t) xdr_remote_domain_get_scheduler_type_args, (char *) &args,
2611              (xdrproc_t) xdr_remote_domain_get_scheduler_type_ret, (char *) &ret) == -1)
2612         goto done;
2613 
2614     if (nparams) *nparams = ret.nparams;
2615 
2616     /* Caller frees this. */
2617     rv = ret.type;
2618 
2619  done:
2620     remoteDriverUnlock(priv);
2621     return rv;
2622 }
2623 
2624 static int
remoteDomainMemoryStats(virDomainPtr domain,virDomainMemoryStatPtr stats,unsigned int nr_stats,unsigned int flags)2625 remoteDomainMemoryStats(virDomainPtr domain,
2626                         virDomainMemoryStatPtr stats,
2627                         unsigned int nr_stats,
2628                         unsigned int flags)
2629 {
2630     int rv = -1;
2631     remote_domain_memory_stats_args args;
2632     remote_domain_memory_stats_ret ret;
2633     struct private_data *priv = domain->conn->privateData;
2634     size_t i;
2635 
2636     remoteDriverLock(priv);
2637 
2638     make_nonnull_domain(&args.dom, domain);
2639     if (nr_stats > REMOTE_DOMAIN_MEMORY_STATS_MAX) {
2640         virReportError(VIR_ERR_RPC,
2641                        _("too many memory stats requested: %d > %d"), nr_stats,
2642                        REMOTE_DOMAIN_MEMORY_STATS_MAX);
2643         goto done;
2644     }
2645     args.maxStats = nr_stats;
2646     args.flags = flags;
2647     memset(&ret, 0, sizeof(ret));
2648 
2649     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MEMORY_STATS,
2650              (xdrproc_t) xdr_remote_domain_memory_stats_args,
2651              (char *) &args,
2652              (xdrproc_t) xdr_remote_domain_memory_stats_ret,
2653              (char *) &ret) == -1)
2654         goto done;
2655 
2656     for (i = 0; i < ret.stats.stats_len; i++) {
2657         stats[i].tag = ret.stats.stats_val[i].tag;
2658         stats[i].val = ret.stats.stats_val[i].val;
2659     }
2660     rv = ret.stats.stats_len;
2661     xdr_free((xdrproc_t) xdr_remote_domain_memory_stats_ret, (char *) &ret);
2662 
2663  done:
2664     remoteDriverUnlock(priv);
2665     return rv;
2666 }
2667 
2668 static int
remoteDomainBlockPeek(virDomainPtr domain,const char * path,unsigned long long offset,size_t size,void * buffer,unsigned int flags)2669 remoteDomainBlockPeek(virDomainPtr domain,
2670                       const char *path,
2671                       unsigned long long offset,
2672                       size_t size,
2673                       void *buffer,
2674                       unsigned int flags)
2675 {
2676     int rv = -1;
2677     remote_domain_block_peek_args args;
2678     remote_domain_block_peek_ret ret;
2679     struct private_data *priv = domain->conn->privateData;
2680 
2681     remoteDriverLock(priv);
2682 
2683     if (size > REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX) {
2684         virReportError(VIR_ERR_RPC,
2685                        _("block peek request too large for remote protocol, %zi > %d"),
2686                        size, REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX);
2687         goto done;
2688     }
2689 
2690     make_nonnull_domain(&args.dom, domain);
2691     args.path = (char *) path;
2692     args.offset = offset;
2693     args.size = size;
2694     args.flags = flags;
2695 
2696     memset(&ret, 0, sizeof(ret));
2697     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_BLOCK_PEEK,
2698              (xdrproc_t) xdr_remote_domain_block_peek_args,
2699              (char *) &args,
2700              (xdrproc_t) xdr_remote_domain_block_peek_ret,
2701              (char *) &ret) == -1)
2702         goto done;
2703 
2704     if (ret.buffer.buffer_len != size) {
2705         virReportError(VIR_ERR_RPC, "%s",
2706                        _("returned buffer is not same size as requested"));
2707         goto cleanup;
2708     }
2709 
2710     memcpy(buffer, ret.buffer.buffer_val, size);
2711     rv = 0;
2712 
2713  cleanup:
2714     VIR_FREE(ret.buffer.buffer_val);
2715 
2716  done:
2717     remoteDriverUnlock(priv);
2718     return rv;
2719 }
2720 
2721 static int
remoteDomainMemoryPeek(virDomainPtr domain,unsigned long long offset,size_t size,void * buffer,unsigned int flags)2722 remoteDomainMemoryPeek(virDomainPtr domain,
2723                        unsigned long long offset,
2724                        size_t size,
2725                        void *buffer,
2726                        unsigned int flags)
2727 {
2728     int rv = -1;
2729     remote_domain_memory_peek_args args;
2730     remote_domain_memory_peek_ret ret;
2731     struct private_data *priv = domain->conn->privateData;
2732 
2733     remoteDriverLock(priv);
2734 
2735     if (size > REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX) {
2736         virReportError(VIR_ERR_RPC,
2737                        _("memory peek request too large for remote protocol, %zi > %d"),
2738                        size, REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX);
2739         goto done;
2740     }
2741 
2742     make_nonnull_domain(&args.dom, domain);
2743     args.offset = offset;
2744     args.size = size;
2745     args.flags = flags;
2746 
2747     memset(&ret, 0, sizeof(ret));
2748     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MEMORY_PEEK,
2749              (xdrproc_t) xdr_remote_domain_memory_peek_args,
2750              (char *) &args,
2751              (xdrproc_t) xdr_remote_domain_memory_peek_ret,
2752              (char *) &ret) == -1)
2753         goto done;
2754 
2755     if (ret.buffer.buffer_len != size) {
2756         virReportError(VIR_ERR_RPC, "%s",
2757                        _("returned buffer is not same size as requested"));
2758         goto cleanup;
2759     }
2760 
2761     memcpy(buffer, ret.buffer.buffer_val, size);
2762     rv = 0;
2763 
2764  cleanup:
2765     VIR_FREE(ret.buffer.buffer_val);
2766 
2767  done:
2768     remoteDriverUnlock(priv);
2769     return rv;
2770 }
2771 
remoteDomainGetBlockJobInfo(virDomainPtr domain,const char * path,virDomainBlockJobInfoPtr info,unsigned int flags)2772 static int remoteDomainGetBlockJobInfo(virDomainPtr domain,
2773                                        const char *path,
2774                                        virDomainBlockJobInfoPtr info,
2775                                        unsigned int flags)
2776 {
2777     int rv = -1;
2778     remote_domain_get_block_job_info_args args;
2779     remote_domain_get_block_job_info_ret ret;
2780     struct private_data *priv = domain->conn->privateData;
2781 
2782     remoteDriverLock(priv);
2783 
2784     make_nonnull_domain(&args.dom, domain);
2785     args.path = (char *)path;
2786     args.flags = flags;
2787 
2788     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_JOB_INFO,
2789              (xdrproc_t)xdr_remote_domain_get_block_job_info_args,
2790                (char *)&args,
2791              (xdrproc_t)xdr_remote_domain_get_block_job_info_ret,
2792                (char *)&ret) == -1)
2793         goto done;
2794 
2795     if (ret.found) {
2796         info->type = ret.type;
2797         info->bandwidth = ret.bandwidth;
2798         info->cur = ret.cur;
2799         info->end = ret.end;
2800         rv = 1;
2801     } else {
2802         rv = 0;
2803     }
2804 
2805  done:
2806     remoteDriverUnlock(priv);
2807     return rv;
2808 }
2809 
remoteDomainGetBlockIoTune(virDomainPtr domain,const char * disk,virTypedParameterPtr params,int * nparams,unsigned int flags)2810 static int remoteDomainGetBlockIoTune(virDomainPtr domain,
2811                                       const char *disk,
2812                                       virTypedParameterPtr params,
2813                                       int *nparams,
2814                                       unsigned int flags)
2815 {
2816     int rv = -1;
2817     remote_domain_get_block_io_tune_args args;
2818     remote_domain_get_block_io_tune_ret ret;
2819     struct private_data *priv = domain->conn->privateData;
2820 
2821     remoteDriverLock(priv);
2822 
2823     make_nonnull_domain(&args.dom, domain);
2824     args.disk = disk ? (char **)&disk : NULL;
2825     args.nparams = *nparams;
2826     args.flags = flags;
2827 
2828     memset(&ret, 0, sizeof(ret));
2829 
2830 
2831     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_BLOCK_IO_TUNE,
2832              (xdrproc_t) xdr_remote_domain_get_block_io_tune_args,
2833                (char *) &args,
2834              (xdrproc_t) xdr_remote_domain_get_block_io_tune_ret,
2835                (char *) &ret) == -1) {
2836         goto done;
2837     }
2838 
2839     /* Handle the case when the caller does not know the number of parameters
2840      * and is asking for the number of parameters supported
2841      */
2842     if (*nparams == 0) {
2843         *nparams = ret.nparams;
2844         rv = 0;
2845         goto cleanup;
2846     }
2847 
2848     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
2849                                   ret.params.params_len,
2850                                   REMOTE_DOMAIN_BLOCK_IO_TUNE_PARAMETERS_MAX,
2851                                   &params,
2852                                   nparams) < 0)
2853         goto cleanup;
2854 
2855     rv = 0;
2856 
2857  cleanup:
2858     xdr_free((xdrproc_t) xdr_remote_domain_get_block_io_tune_ret,
2859              (char *) &ret);
2860  done:
2861     remoteDriverUnlock(priv);
2862     return rv;
2863 }
2864 
remoteDomainGetCPUStats(virDomainPtr domain,virTypedParameterPtr params,unsigned int nparams,int start_cpu,unsigned int ncpus,unsigned int flags)2865 static int remoteDomainGetCPUStats(virDomainPtr domain,
2866                                    virTypedParameterPtr params,
2867                                    unsigned int nparams,
2868                                    int start_cpu,
2869                                    unsigned int ncpus,
2870                                    unsigned int flags)
2871 {
2872     struct private_data *priv = domain->conn->privateData;
2873     remote_domain_get_cpu_stats_args args;
2874     remote_domain_get_cpu_stats_ret ret;
2875     int rv = -1;
2876     int cpu;
2877 
2878     remoteDriverLock(priv);
2879 
2880     if (nparams > REMOTE_NODE_CPU_STATS_MAX) {
2881         virReportError(VIR_ERR_RPC,
2882                        _("nparams count exceeds maximum: %u > %u"),
2883                        nparams, REMOTE_NODE_CPU_STATS_MAX);
2884         goto done;
2885     }
2886     if (ncpus > REMOTE_DOMAIN_GET_CPU_STATS_NCPUS_MAX) {
2887         virReportError(VIR_ERR_RPC,
2888                        _("ncpus count exceeds maximum: %u > %u"),
2889                        ncpus, REMOTE_DOMAIN_GET_CPU_STATS_NCPUS_MAX);
2890         goto done;
2891     }
2892 
2893     make_nonnull_domain(&args.dom, domain);
2894     args.nparams = nparams;
2895     args.start_cpu = start_cpu;
2896     args.ncpus = ncpus;
2897     args.flags = flags;
2898 
2899     memset(&ret, 0, sizeof(ret));
2900 
2901     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_CPU_STATS,
2902              (xdrproc_t) xdr_remote_domain_get_cpu_stats_args,
2903              (char *) &args,
2904              (xdrproc_t) xdr_remote_domain_get_cpu_stats_ret,
2905              (char *) &ret) == -1)
2906         goto done;
2907 
2908     /* Check the length of the returned list carefully. */
2909     if (ret.params.params_len > nparams * ncpus ||
2910         (ret.params.params_len &&
2911          ((ret.params.params_len % ret.nparams) || ret.nparams > nparams))) {
2912         virReportError(VIR_ERR_RPC, "%s",
2913                        _("remoteDomainGetCPUStats: "
2914                          "returned number of stats exceeds limit"));
2915         memset(params, 0, sizeof(*params) * nparams * ncpus);
2916         goto cleanup;
2917     }
2918 
2919     /* Handle the case when the caller does not know the number of stats
2920      * and is asking for the number of stats supported
2921      */
2922     if (nparams == 0) {
2923         rv = ret.nparams;
2924         goto cleanup;
2925     }
2926 
2927     /* The remote side did not send back any zero entries, so we have
2928      * to expand things back into a possibly sparse array, where the
2929      * tail of the array may be omitted.
2930      */
2931     memset(params, 0, sizeof(*params) * nparams * ncpus);
2932     ncpus = ret.params.params_len / ret.nparams;
2933     for (cpu = 0; cpu < ncpus; cpu++) {
2934         int tmp = nparams;
2935         virTypedParameterPtr cpu_params = &params[cpu * nparams];
2936         remote_typed_param *stride = &ret.params.params_val[cpu * ret.nparams];
2937 
2938         if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) stride,
2939                                       ret.nparams,
2940                                       REMOTE_NODE_CPU_STATS_MAX,
2941                                       &cpu_params, &tmp) < 0)
2942             goto cleanup;
2943     }
2944 
2945     rv = ret.nparams;
2946  cleanup:
2947     if (rv < 0)
2948         virTypedParamsClear(params, nparams * ncpus);
2949 
2950     xdr_free((xdrproc_t) xdr_remote_domain_get_cpu_stats_ret,
2951              (char *) &ret);
2952  done:
2953     remoteDriverUnlock(priv);
2954     return rv;
2955 }
2956 
2957 
2958 static int
remoteConnectNetworkEventRegisterAny(virConnectPtr conn,virNetworkPtr net,int eventID,virConnectNetworkEventGenericCallback callback,void * opaque,virFreeCallback freecb)2959 remoteConnectNetworkEventRegisterAny(virConnectPtr conn,
2960                                      virNetworkPtr net,
2961                                      int eventID,
2962                                      virConnectNetworkEventGenericCallback callback,
2963                                      void *opaque,
2964                                      virFreeCallback freecb)
2965 {
2966     int rv = -1;
2967     struct private_data *priv = conn->privateData;
2968     remote_connect_network_event_register_any_args args;
2969     remote_connect_network_event_register_any_ret ret;
2970     int callbackID;
2971     int count;
2972     remote_nonnull_network network;
2973 
2974     remoteDriverLock(priv);
2975 
2976     if ((count = virNetworkEventStateRegisterClient(conn, priv->eventState,
2977                                                     net, eventID, callback,
2978                                                     opaque, freecb,
2979                                                     &callbackID)) < 0)
2980         goto done;
2981 
2982     /* If this is the first callback for this eventID, we need to enable
2983      * events on the server */
2984     if (count == 1) {
2985         args.eventID = eventID;
2986         if (net) {
2987             make_nonnull_network(&network, net);
2988             args.net = &network;
2989         } else {
2990             args.net = NULL;
2991         }
2992 
2993         memset(&ret, 0, sizeof(ret));
2994         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_REGISTER_ANY,
2995                  (xdrproc_t) xdr_remote_connect_network_event_register_any_args, (char *) &args,
2996                  (xdrproc_t) xdr_remote_connect_network_event_register_any_ret, (char *) &ret) == -1) {
2997             virObjectEventStateDeregisterID(conn, priv->eventState,
2998                                             callbackID, false);
2999             goto done;
3000         }
3001         virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
3002                                      ret.callbackID);
3003     }
3004 
3005     rv = callbackID;
3006 
3007  done:
3008     remoteDriverUnlock(priv);
3009     return rv;
3010 }
3011 
3012 
3013 static int
remoteConnectNetworkEventDeregisterAny(virConnectPtr conn,int callbackID)3014 remoteConnectNetworkEventDeregisterAny(virConnectPtr conn,
3015                                        int callbackID)
3016 {
3017     struct private_data *priv = conn->privateData;
3018     int rv = -1;
3019     remote_connect_network_event_deregister_any_args args;
3020     int eventID;
3021     int remoteID;
3022     int count;
3023 
3024     remoteDriverLock(priv);
3025 
3026     if ((eventID = virObjectEventStateEventID(conn, priv->eventState,
3027                                               callbackID, &remoteID)) < 0)
3028         goto done;
3029 
3030     if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
3031                                                  callbackID, true)) < 0)
3032         goto done;
3033 
3034     /* If that was the last callback for this eventID, we need to disable
3035      * events on the server */
3036     if (count == 0) {
3037         args.callbackID = remoteID;
3038 
3039         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NETWORK_EVENT_DEREGISTER_ANY,
3040                  (xdrproc_t) xdr_remote_connect_network_event_deregister_any_args, (char *) &args,
3041                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
3042             goto done;
3043     }
3044 
3045     rv = 0;
3046 
3047  done:
3048     remoteDriverUnlock(priv);
3049     return rv;
3050 }
3051 
3052 static int
remoteConnectStoragePoolEventRegisterAny(virConnectPtr conn,virStoragePoolPtr pool,int eventID,virConnectStoragePoolEventGenericCallback callback,void * opaque,virFreeCallback freecb)3053 remoteConnectStoragePoolEventRegisterAny(virConnectPtr conn,
3054                                          virStoragePoolPtr pool,
3055                                          int eventID,
3056                                          virConnectStoragePoolEventGenericCallback callback,
3057                                          void *opaque,
3058                                          virFreeCallback freecb)
3059 {
3060     int rv = -1;
3061     struct private_data *priv = conn->privateData;
3062     remote_connect_storage_pool_event_register_any_args args;
3063     remote_connect_storage_pool_event_register_any_ret ret;
3064     int callbackID;
3065     int count;
3066     remote_nonnull_storage_pool storage_pool;
3067 
3068     remoteDriverLock(priv);
3069 
3070     if ((count = virStoragePoolEventStateRegisterClient(conn, priv->eventState,
3071                                                         pool, eventID, callback,
3072                                                         opaque, freecb,
3073                                                         &callbackID)) < 0)
3074         goto done;
3075 
3076     /* If this is the first callback for this eventID, we need to enable
3077      * events on the server */
3078     if (count == 1) {
3079         args.eventID = eventID;
3080         if (pool) {
3081             make_nonnull_storage_pool(&storage_pool, pool);
3082             args.pool = &storage_pool;
3083         } else {
3084             args.pool = NULL;
3085         }
3086 
3087         memset(&ret, 0, sizeof(ret));
3088         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_STORAGE_POOL_EVENT_REGISTER_ANY,
3089                  (xdrproc_t) xdr_remote_connect_storage_pool_event_register_any_args, (char *) &args,
3090                  (xdrproc_t) xdr_remote_connect_storage_pool_event_register_any_ret, (char *) &ret) == -1) {
3091             virObjectEventStateDeregisterID(conn, priv->eventState,
3092                                             callbackID, false);
3093             goto done;
3094         }
3095 
3096         virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
3097                                      ret.callbackID);
3098     }
3099 
3100     rv = callbackID;
3101 
3102  done:
3103     remoteDriverUnlock(priv);
3104     return rv;
3105 }
3106 
3107 static int
remoteConnectStoragePoolEventDeregisterAny(virConnectPtr conn,int callbackID)3108 remoteConnectStoragePoolEventDeregisterAny(virConnectPtr conn,
3109                                            int callbackID)
3110 {
3111     struct private_data *priv = conn->privateData;
3112     int rv = -1;
3113     remote_connect_storage_pool_event_deregister_any_args args;
3114     int eventID;
3115     int remoteID;
3116     int count;
3117 
3118     remoteDriverLock(priv);
3119 
3120     if ((eventID = virObjectEventStateEventID(conn, priv->eventState,
3121                                               callbackID, &remoteID)) < 0)
3122         goto done;
3123 
3124     if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
3125                                                  callbackID, true)) < 0)
3126         goto done;
3127 
3128     /* If that was the last callback for this eventID, we need to disable
3129      * events on the server */
3130     if (count == 0) {
3131         args.callbackID = remoteID;
3132 
3133         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_STORAGE_POOL_EVENT_DEREGISTER_ANY,
3134                  (xdrproc_t) xdr_remote_connect_storage_pool_event_deregister_any_args, (char *) &args,
3135                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
3136             goto done;
3137 
3138     }
3139 
3140     rv = 0;
3141 
3142  done:
3143     remoteDriverUnlock(priv);
3144     return rv;
3145 }
3146 
3147 
3148 static int
remoteConnectNodeDeviceEventRegisterAny(virConnectPtr conn,virNodeDevicePtr dev,int eventID,virConnectNodeDeviceEventGenericCallback callback,void * opaque,virFreeCallback freecb)3149 remoteConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
3150                                         virNodeDevicePtr dev,
3151                                         int eventID,
3152                                         virConnectNodeDeviceEventGenericCallback callback,
3153                                         void *opaque,
3154                                         virFreeCallback freecb)
3155 {
3156     int rv = -1;
3157     struct private_data *priv = conn->privateData;
3158     remote_connect_node_device_event_register_any_args args;
3159     remote_connect_node_device_event_register_any_ret ret;
3160     int callbackID;
3161     int count;
3162     remote_nonnull_node_device node_device;
3163 
3164     remoteDriverLock(priv);
3165 
3166     if ((count = virNodeDeviceEventStateRegisterClient(conn, priv->eventState,
3167                                                        dev, eventID, callback,
3168                                                        opaque, freecb,
3169                                                        &callbackID)) < 0)
3170         goto done;
3171 
3172     /* If this is the first callback for this eventID, we need to enable
3173      * events on the server */
3174     if (count == 1) {
3175         args.eventID = eventID;
3176         if (dev) {
3177             make_nonnull_node_device(&node_device, dev);
3178             args.dev = &node_device;
3179         } else {
3180             args.dev = NULL;
3181         }
3182 
3183         memset(&ret, 0, sizeof(ret));
3184         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NODE_DEVICE_EVENT_REGISTER_ANY,
3185                  (xdrproc_t) xdr_remote_connect_node_device_event_register_any_args, (char *) &args,
3186                  (xdrproc_t) xdr_remote_connect_node_device_event_register_any_ret, (char *) &ret) == -1) {
3187             virObjectEventStateDeregisterID(conn, priv->eventState,
3188                                             callbackID, false);
3189             goto done;
3190         }
3191 
3192         virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
3193                                      ret.callbackID);
3194     }
3195 
3196     rv = callbackID;
3197 
3198  done:
3199     remoteDriverUnlock(priv);
3200     return rv;
3201 }
3202 
3203 
3204 static int
remoteConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,int callbackID)3205 remoteConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
3206                                           int callbackID)
3207 {
3208     struct private_data *priv = conn->privateData;
3209     int rv = -1;
3210     remote_connect_node_device_event_deregister_any_args args;
3211     int eventID;
3212     int remoteID;
3213     int count;
3214 
3215     remoteDriverLock(priv);
3216 
3217     if ((eventID = virObjectEventStateEventID(conn, priv->eventState,
3218                                               callbackID, &remoteID)) < 0)
3219         goto done;
3220 
3221     if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
3222                                                  callbackID, true)) < 0)
3223         goto done;
3224 
3225     /* If that was the last callback for this eventID, we need to disable
3226      * events on the server */
3227     if (count == 0) {
3228         args.callbackID = remoteID;
3229 
3230         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_NODE_DEVICE_EVENT_DEREGISTER_ANY,
3231                  (xdrproc_t) xdr_remote_connect_node_device_event_deregister_any_args, (char *) &args,
3232                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
3233             goto done;
3234 
3235     }
3236 
3237     rv = 0;
3238 
3239  done:
3240     remoteDriverUnlock(priv);
3241     return rv;
3242 }
3243 
3244 
3245 static int
remoteConnectSecretEventRegisterAny(virConnectPtr conn,virSecretPtr secret,int eventID,virConnectSecretEventGenericCallback callback,void * opaque,virFreeCallback freecb)3246 remoteConnectSecretEventRegisterAny(virConnectPtr conn,
3247                                     virSecretPtr secret,
3248                                     int eventID,
3249                                     virConnectSecretEventGenericCallback callback,
3250                                     void *opaque,
3251                                     virFreeCallback freecb)
3252 {
3253     int rv = -1;
3254     struct private_data *priv = conn->privateData;
3255     remote_connect_secret_event_register_any_args args;
3256     remote_connect_secret_event_register_any_ret ret;
3257     int callbackID;
3258     int count;
3259     remote_nonnull_secret sec;
3260 
3261     remoteDriverLock(priv);
3262 
3263     if ((count = virSecretEventStateRegisterClient(conn, priv->eventState,
3264                                                    secret, eventID, callback,
3265                                                    opaque, freecb,
3266                                                    &callbackID)) < 0)
3267         goto done;
3268 
3269     /* If this is the first callback for this eventID, we need to enable
3270      * events on the server */
3271     if (count == 1) {
3272         args.eventID = eventID;
3273         if (secret) {
3274             make_nonnull_secret(&sec, secret);
3275             args.secret = &sec;
3276         } else {
3277             args.secret = NULL;
3278         }
3279 
3280         memset(&ret, 0, sizeof(ret));
3281         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_SECRET_EVENT_REGISTER_ANY,
3282                  (xdrproc_t) xdr_remote_connect_secret_event_register_any_args, (char *) &args,
3283                  (xdrproc_t) xdr_remote_connect_secret_event_register_any_ret, (char *) &ret) == -1) {
3284             virObjectEventStateDeregisterID(conn, priv->eventState,
3285                                             callbackID, false);
3286             goto done;
3287         }
3288 
3289         virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
3290                                      ret.callbackID);
3291     }
3292 
3293     rv = callbackID;
3294 
3295  done:
3296     remoteDriverUnlock(priv);
3297     return rv;
3298 }
3299 
3300 
3301 static int
remoteConnectSecretEventDeregisterAny(virConnectPtr conn,int callbackID)3302 remoteConnectSecretEventDeregisterAny(virConnectPtr conn,
3303                                           int callbackID)
3304 {
3305     struct private_data *priv = conn->privateData;
3306     int rv = -1;
3307     remote_connect_secret_event_deregister_any_args args;
3308     int eventID;
3309     int remoteID;
3310     int count;
3311 
3312     remoteDriverLock(priv);
3313 
3314     if ((eventID = virObjectEventStateEventID(conn, priv->eventState,
3315                                               callbackID, &remoteID)) < 0)
3316         goto done;
3317 
3318     if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
3319                                                  callbackID, true)) < 0)
3320         goto done;
3321 
3322     /* If that was the last callback for this eventID, we need to disable
3323      * events on the server */
3324     if (count == 0) {
3325         args.callbackID = remoteID;
3326 
3327         if (call(conn, priv, 0, REMOTE_PROC_CONNECT_SECRET_EVENT_DEREGISTER_ANY,
3328                  (xdrproc_t) xdr_remote_connect_secret_event_deregister_any_args, (char *) &args,
3329                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
3330             goto done;
3331 
3332     }
3333 
3334     rv = 0;
3335 
3336  done:
3337     remoteDriverUnlock(priv);
3338     return rv;
3339 }
3340 
3341 
3342 static int
remoteConnectDomainQemuMonitorEventRegister(virConnectPtr conn,virDomainPtr dom,const char * event,virConnectDomainQemuMonitorEventCallback callback,void * opaque,virFreeCallback freecb,unsigned int flags)3343 remoteConnectDomainQemuMonitorEventRegister(virConnectPtr conn,
3344                                             virDomainPtr dom,
3345                                             const char *event,
3346                                             virConnectDomainQemuMonitorEventCallback callback,
3347                                             void *opaque,
3348                                             virFreeCallback freecb,
3349                                             unsigned int flags)
3350 {
3351     int rv = -1;
3352     struct private_data *priv = conn->privateData;
3353     qemu_connect_domain_monitor_event_register_args args;
3354     qemu_connect_domain_monitor_event_register_ret ret;
3355     int callbackID;
3356     int count;
3357     remote_nonnull_domain domain;
3358 
3359     remoteDriverLock(priv);
3360 
3361     if ((count = virDomainQemuMonitorEventStateRegisterID(conn,
3362                                                           priv->eventState,
3363                                                           dom, event, callback,
3364                                                           opaque, freecb, -1,
3365                                                           &callbackID)) < 0)
3366         goto done;
3367 
3368     /* If this is the first callback for this event, we need to enable
3369      * events on the server */
3370     if (count == 1) {
3371         if (dom) {
3372             make_nonnull_domain(&domain, dom);
3373             args.dom = &domain;
3374         } else {
3375             args.dom = NULL;
3376         }
3377         args.event = event ? (char **) &event : NULL;
3378         args.flags = flags;
3379 
3380         memset(&ret, 0, sizeof(ret));
3381         if (call(conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER,
3382                  (xdrproc_t) xdr_qemu_connect_domain_monitor_event_register_args, (char *) &args,
3383                  (xdrproc_t) xdr_qemu_connect_domain_monitor_event_register_ret, (char *) &ret) == -1) {
3384             virObjectEventStateDeregisterID(conn, priv->eventState,
3385                                             callbackID, false);
3386             goto done;
3387         }
3388         virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
3389                                      ret.callbackID);
3390     }
3391 
3392     rv = callbackID;
3393 
3394  done:
3395     remoteDriverUnlock(priv);
3396     return rv;
3397 }
3398 
3399 
3400 static int
remoteConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,int callbackID)3401 remoteConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,
3402                                               int callbackID)
3403 {
3404     struct private_data *priv = conn->privateData;
3405     int rv = -1;
3406     qemu_connect_domain_monitor_event_deregister_args args;
3407     int remoteID;
3408     int count;
3409 
3410     remoteDriverLock(priv);
3411 
3412     if (virObjectEventStateEventID(conn, priv->eventState,
3413                                    callbackID, &remoteID) < 0)
3414         goto done;
3415 
3416     if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
3417                                                  callbackID, true)) < 0)
3418         goto done;
3419 
3420     /* If that was the last callback for this event, we need to disable
3421      * events on the server */
3422     if (count == 0) {
3423         args.callbackID = remoteID;
3424 
3425         if (call(conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER,
3426                  (xdrproc_t) xdr_qemu_connect_domain_monitor_event_deregister_args, (char *) &args,
3427                  (xdrproc_t) xdr_void, (char *) NULL) == -1)
3428             goto done;
3429     }
3430 
3431     rv = 0;
3432 
3433  done:
3434     remoteDriverUnlock(priv);
3435     return rv;
3436 }
3437 
3438 /*----------------------------------------------------------------------*/
3439 
3440 static char *
remoteConnectFindStoragePoolSources(virConnectPtr conn,const char * type,const char * srcSpec,unsigned int flags)3441 remoteConnectFindStoragePoolSources(virConnectPtr conn,
3442                                     const char *type,
3443                                     const char *srcSpec,
3444                                     unsigned int flags)
3445 {
3446     char *rv = NULL;
3447     remote_connect_find_storage_pool_sources_args args;
3448     remote_connect_find_storage_pool_sources_ret ret;
3449     struct private_data *priv = conn->privateData;
3450 
3451     remoteDriverLock(priv);
3452 
3453     args.type = (char*)type;
3454     args.srcSpec = srcSpec ? (char **)&srcSpec : NULL;
3455     args.flags = flags;
3456 
3457     memset(&ret, 0, sizeof(ret));
3458     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_FIND_STORAGE_POOL_SOURCES,
3459              (xdrproc_t) xdr_remote_connect_find_storage_pool_sources_args, (char *) &args,
3460              (xdrproc_t) xdr_remote_connect_find_storage_pool_sources_ret, (char *) &ret) == -1)
3461         goto done;
3462 
3463     rv = g_steal_pointer(&ret.xml); /* To stop xdr_free free'ing it */
3464 
3465     xdr_free((xdrproc_t) xdr_remote_connect_find_storage_pool_sources_ret, (char *) &ret);
3466 
3467  done:
3468     remoteDriverUnlock(priv);
3469     return rv;
3470 }
3471 
3472 /*----------------------------------------------------------------------*/
3473 
3474 static int
remoteNodeDeviceDettach(virNodeDevicePtr dev)3475 remoteNodeDeviceDettach(virNodeDevicePtr dev)
3476 {
3477     int rv = -1;
3478     remote_node_device_dettach_args args;
3479     struct private_data *priv = dev->conn->privateData;
3480 
3481     remoteDriverLock(priv);
3482 
3483     args.name = dev->name;
3484 
3485     if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DETTACH,
3486              (xdrproc_t) xdr_remote_node_device_dettach_args, (char *) &args,
3487              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3488         goto done;
3489 
3490     rv = 0;
3491 
3492  done:
3493     remoteDriverUnlock(priv);
3494     return rv;
3495 }
3496 
3497 static int
remoteNodeDeviceDetachFlags(virNodeDevicePtr dev,const char * driverName,unsigned int flags)3498 remoteNodeDeviceDetachFlags(virNodeDevicePtr dev,
3499                             const char *driverName,
3500                             unsigned int flags)
3501 {
3502     int rv = -1;
3503     remote_node_device_detach_flags_args args;
3504     struct private_data *priv = dev->conn->privateData;
3505 
3506     remoteDriverLock(priv);
3507 
3508     args.name = dev->name;
3509     args.driverName = driverName ? (char**)&driverName : NULL;
3510     args.flags = flags;
3511 
3512     if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_DETACH_FLAGS,
3513              (xdrproc_t) xdr_remote_node_device_detach_flags_args,
3514              (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1)
3515         goto done;
3516 
3517     rv = 0;
3518 
3519  done:
3520     remoteDriverUnlock(priv);
3521     return rv;
3522 }
3523 
3524 static int
remoteNodeDeviceReAttach(virNodeDevicePtr dev)3525 remoteNodeDeviceReAttach(virNodeDevicePtr dev)
3526 {
3527     int rv = -1;
3528     remote_node_device_re_attach_args args;
3529     struct private_data *priv = dev->conn->privateData;
3530 
3531     remoteDriverLock(priv);
3532 
3533     args.name = dev->name;
3534 
3535     if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_RE_ATTACH,
3536              (xdrproc_t) xdr_remote_node_device_re_attach_args, (char *) &args,
3537              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3538         goto done;
3539 
3540     rv = 0;
3541 
3542  done:
3543     remoteDriverUnlock(priv);
3544     return rv;
3545 }
3546 
3547 static int
remoteNodeDeviceReset(virNodeDevicePtr dev)3548 remoteNodeDeviceReset(virNodeDevicePtr dev)
3549 {
3550     int rv = -1;
3551     remote_node_device_reset_args args;
3552     /* This method is unusual in that it uses the HV driver, not the devMon driver
3553      * hence its use of privateData, instead of nodeDevicePrivateData */
3554     struct private_data *priv = dev->conn->privateData;
3555 
3556     remoteDriverLock(priv);
3557 
3558     args.name = dev->name;
3559 
3560     if (call(dev->conn, priv, 0, REMOTE_PROC_NODE_DEVICE_RESET,
3561              (xdrproc_t) xdr_remote_node_device_reset_args, (char *) &args,
3562              (xdrproc_t) xdr_void, (char *) NULL) == -1)
3563         goto done;
3564 
3565     rv = 0;
3566 
3567  done:
3568     remoteDriverUnlock(priv);
3569     return rv;
3570 }
3571 
3572 
3573 /*----------------------------------------------------------------------*/
3574 
3575 static int
remoteAuthenticate(virConnectPtr conn,struct private_data * priv,virConnectAuthPtr auth G_GNUC_UNUSED,const char * authtype)3576 remoteAuthenticate(virConnectPtr conn, struct private_data *priv,
3577                    virConnectAuthPtr auth G_GNUC_UNUSED,
3578                    const char *authtype)
3579 {
3580     struct remote_auth_list_ret ret;
3581     int err, type = REMOTE_AUTH_NONE;
3582 
3583     memset(&ret, 0, sizeof(ret));
3584     err = call(conn, priv, 0,
3585                REMOTE_PROC_AUTH_LIST,
3586                (xdrproc_t) xdr_void, (char *) NULL,
3587                (xdrproc_t) xdr_remote_auth_list_ret, (char *) &ret);
3588     if (err < 0) {
3589         if (virGetLastErrorCode() == VIR_ERR_NO_SUPPORT) {
3590             /* Missing RPC - old server - ignore */
3591             virResetLastError();
3592             return 0;
3593         }
3594         return -1;
3595     }
3596 
3597     if (ret.types.types_len == 0)
3598         return 0;
3599 
3600     if (authtype) {
3601         int want;
3602         size_t i;
3603         if (STRCASEEQ(authtype, "sasl") ||
3604             STRCASEEQLEN(authtype, "sasl.", 5)) {
3605             want = REMOTE_AUTH_SASL;
3606         } else if (STRCASEEQ(authtype, "polkit")) {
3607             want = REMOTE_AUTH_POLKIT;
3608         } else {
3609             virReportError(VIR_ERR_AUTH_FAILED,
3610                            _("unknown authentication type %s"), authtype);
3611             return -1;
3612         }
3613         for (i = 0; i < ret.types.types_len; i++) {
3614             if (ret.types.types_val[i] == want)
3615                 type = want;
3616         }
3617         if (type == REMOTE_AUTH_NONE) {
3618             virReportError(VIR_ERR_AUTH_FAILED,
3619                            _("requested authentication type %s rejected"),
3620                            authtype);
3621             return -1;
3622         }
3623     } else {
3624         type = ret.types.types_val[0];
3625     }
3626 
3627     switch (type) {
3628 #if WITH_SASL
3629     case REMOTE_AUTH_SASL: {
3630         const char *mech = NULL;
3631         if (authtype &&
3632             STRCASEEQLEN(authtype, "sasl.", 5))
3633             mech = authtype + 5;
3634 
3635         if (remoteAuthSASL(conn, priv, auth, mech) < 0) {
3636             VIR_FREE(ret.types.types_val);
3637             return -1;
3638         }
3639         break;
3640     }
3641 #endif
3642 
3643     case REMOTE_AUTH_POLKIT:
3644         if (remoteAuthPolkit(conn, priv, auth) < 0) {
3645             VIR_FREE(ret.types.types_val);
3646             return -1;
3647         }
3648         break;
3649 
3650     case REMOTE_AUTH_NONE:
3651         /* Nothing todo, hurrah ! */
3652         break;
3653 
3654     default:
3655         virReportError(VIR_ERR_AUTH_FAILED,
3656                        _("unsupported authentication type %d"),
3657                        ret.types.types_val[0]);
3658         VIR_FREE(ret.types.types_val);
3659         return -1;
3660     }
3661 
3662     VIR_FREE(ret.types.types_val);
3663 
3664     return 0;
3665 }
3666 
3667 
3668 
3669 #if WITH_SASL
remoteAuthCredVir2SASL(int vircred)3670 static int remoteAuthCredVir2SASL(int vircred)
3671 {
3672     switch (vircred) {
3673     case VIR_CRED_USERNAME:
3674         return SASL_CB_USER;
3675 
3676     case VIR_CRED_AUTHNAME:
3677         return SASL_CB_AUTHNAME;
3678 
3679     case VIR_CRED_LANGUAGE:
3680         return SASL_CB_LANGUAGE;
3681 
3682     case VIR_CRED_CNONCE:
3683         return SASL_CB_CNONCE;
3684 
3685     case VIR_CRED_PASSPHRASE:
3686         return SASL_CB_PASS;
3687 
3688     case VIR_CRED_ECHOPROMPT:
3689         return SASL_CB_ECHOPROMPT;
3690 
3691     case VIR_CRED_NOECHOPROMPT:
3692         return SASL_CB_NOECHOPROMPT;
3693 
3694     case VIR_CRED_REALM:
3695         return SASL_CB_GETREALM;
3696     }
3697 
3698     return 0;
3699 }
3700 
remoteAuthCredSASL2Vir(int vircred)3701 static int remoteAuthCredSASL2Vir(int vircred)
3702 {
3703     switch (vircred) {
3704     case SASL_CB_USER:
3705         return VIR_CRED_USERNAME;
3706 
3707     case SASL_CB_AUTHNAME:
3708         return VIR_CRED_AUTHNAME;
3709 
3710     case SASL_CB_LANGUAGE:
3711         return VIR_CRED_LANGUAGE;
3712 
3713     case SASL_CB_CNONCE:
3714         return VIR_CRED_CNONCE;
3715 
3716     case SASL_CB_PASS:
3717         return VIR_CRED_PASSPHRASE;
3718 
3719     case SASL_CB_ECHOPROMPT:
3720         return VIR_CRED_ECHOPROMPT;
3721 
3722     case SASL_CB_NOECHOPROMPT:
3723         return VIR_CRED_NOECHOPROMPT;
3724 
3725     case SASL_CB_GETREALM:
3726         return VIR_CRED_REALM;
3727     }
3728 
3729     return 0;
3730 }
3731 
3732 /*
3733  * @param credtype array of credential types client supports
3734  * @param ncredtype size of credtype array
3735  * @return the SASL callback structure, or NULL on error
3736  *
3737  * Build up the SASL callback structure. We register one callback for
3738  * each credential type that the libvirt client indicated they support.
3739  * We explicitly leave the callback function pointer at NULL though,
3740  * because we don't actually want to get SASL callbacks triggered.
3741  * Instead, we want the start/step functions to return SASL_INTERACT.
3742  * This lets us give the libvirt client a list of all required
3743  * credentials in one go, rather than triggering the callback one
3744  * credential at a time,
3745  */
remoteAuthMakeCallbacks(int * credtype,int ncredtype)3746 static sasl_callback_t *remoteAuthMakeCallbacks(int *credtype, int ncredtype)
3747 {
3748     sasl_callback_t *cbs;
3749     size_t i;
3750     int n;
3751     cbs = g_new0(sasl_callback_t, ncredtype + 1);
3752 
3753     for (i = 0, n = 0; i < ncredtype; i++) {
3754         int id = remoteAuthCredVir2SASL(credtype[i]);
3755         if (id != 0)
3756             cbs[n++].id = id;
3757         /* Don't fill proc or context fields of sasl_callback_t
3758          * because we want to use interactions instead */
3759     }
3760     cbs[n].id = 0;
3761     return cbs;
3762 }
3763 
3764 
3765 /*
3766  * @param interact SASL interactions required
3767  * @param cred populated with libvirt credential metadata
3768  * @return the size of the cred array returned
3769  *
3770  * Builds up an array of libvirt credential structs, populating
3771  * with data from the SASL interaction struct. These two structs
3772  * are basically a 1-to-1 copy of each other.
3773  */
remoteAuthMakeCredentials(sasl_interact_t * interact,virConnectCredentialPtr * cred,size_t * ncred)3774 static int remoteAuthMakeCredentials(sasl_interact_t *interact,
3775                                      virConnectCredentialPtr *cred,
3776                                      size_t *ncred)
3777 {
3778     int ninteract;
3779     if (!cred)
3780         return -1;
3781 
3782     for (ninteract = 0, *ncred = 0; interact[ninteract].id != 0; ninteract++) {
3783         if (interact[ninteract].result)
3784             continue;
3785         (*ncred)++;
3786     }
3787 
3788     *cred = g_new0(virConnectCredential, *ncred);
3789 
3790     for (ninteract = 0, *ncred = 0; interact[ninteract].id != 0; ninteract++) {
3791         if (interact[ninteract].result)
3792             continue;
3793 
3794         (*cred)[*ncred].type = remoteAuthCredSASL2Vir(interact[ninteract].id);
3795         if (!(*cred)[*ncred].type) {
3796             *ncred = 0;
3797             VIR_FREE(*cred);
3798             return -1;
3799         }
3800         if (interact[*ncred].challenge)
3801             (*cred)[*ncred].challenge = interact[ninteract].challenge;
3802         (*cred)[*ncred].prompt = interact[ninteract].prompt;
3803         if (interact[*ncred].defresult)
3804             (*cred)[*ncred].defresult = interact[ninteract].defresult;
3805         (*cred)[*ncred].result = NULL;
3806 
3807         (*ncred)++;
3808     }
3809 
3810     return 0;
3811 }
3812 
3813 
3814 /*
3815  * @param cred the populated libvirt credentials
3816  * @param interact the SASL interactions to fill in results for
3817  *
3818  * Fills the SASL interactions with the result from the libvirt
3819  * callbacks
3820  */
remoteAuthFillInteract(virConnectCredentialPtr cred,sasl_interact_t * interact)3821 static void remoteAuthFillInteract(virConnectCredentialPtr cred,
3822                                    sasl_interact_t *interact)
3823 {
3824     int ninteract, ncred;
3825     for (ninteract = 0, ncred = 0; interact[ninteract].id != 0; ninteract++) {
3826         if (interact[ninteract].result)
3827             continue;
3828         interact[ninteract].result = cred[ncred].result;
3829         interact[ninteract].len = cred[ncred].resultlen;
3830         ncred++;
3831     }
3832 }
3833 
3834 struct remoteAuthInteractState {
3835     sasl_interact_t *interact;
3836     virConnectCredentialPtr cred;
3837     size_t ncred;
3838     virAuthConfig *config;
3839 };
3840 
3841 
3842 
remoteAuthFillFromConfig(virConnectPtr conn,struct remoteAuthInteractState * state)3843 static int remoteAuthFillFromConfig(virConnectPtr conn,
3844                                     struct remoteAuthInteractState *state)
3845 {
3846     int ret = -1;
3847     int ninteract;
3848     const char *credname;
3849     char *path = NULL;
3850 
3851     VIR_DEBUG("Trying to fill auth parameters from config file");
3852 
3853     if (!state->config) {
3854         if (virAuthGetConfigFilePath(conn, &path) < 0)
3855             goto cleanup;
3856         if (path == NULL) {
3857             ret = 0;
3858             goto cleanup;
3859         }
3860 
3861         if (!(state->config = virAuthConfigNew(path)))
3862             goto cleanup;
3863     }
3864 
3865     for (ninteract = 0; state->interact[ninteract].id != 0; ninteract++) {
3866         char *value = NULL;
3867 
3868         switch (state->interact[ninteract].id) {
3869         case SASL_CB_USER:
3870             credname = "username";
3871             break;
3872         case SASL_CB_AUTHNAME:
3873             credname = "authname";
3874             break;
3875         case SASL_CB_PASS:
3876             credname = "password";
3877             break;
3878         case SASL_CB_GETREALM:
3879             credname = "realm";
3880             break;
3881         default:
3882             credname = NULL;
3883             break;
3884         }
3885 
3886         if (credname &&
3887             virAuthConfigLookup(state->config,
3888                                 "libvirt",
3889                                 VIR_URI_SERVER(conn->uri),
3890                                 credname,
3891                                 &value) < 0)
3892             goto cleanup;
3893 
3894         if (value) {
3895             state->interact[ninteract].result = value;
3896             state->interact[ninteract].len = strlen(value);
3897         }
3898     }
3899 
3900     ret = 0;
3901 
3902  cleanup:
3903     VIR_FREE(path);
3904     return ret;
3905 }
3906 
3907 
remoteAuthInteractStateClear(struct remoteAuthInteractState * state,bool final)3908 static void remoteAuthInteractStateClear(struct remoteAuthInteractState *state,
3909                                          bool final)
3910 {
3911     size_t i;
3912     if (!state)
3913         return;
3914 
3915     for (i = 0; i < state->ncred; i++)
3916         VIR_FREE(state->cred[i].result);
3917     VIR_FREE(state->cred);
3918     state->ncred = 0;
3919 
3920     if (final)
3921         virAuthConfigFree(state->config);
3922 }
3923 
3924 
remoteAuthInteract(virConnectPtr conn,struct remoteAuthInteractState * state,virConnectAuthPtr auth)3925 static int remoteAuthInteract(virConnectPtr conn,
3926                               struct remoteAuthInteractState *state,
3927                               virConnectAuthPtr auth)
3928 {
3929     VIR_DEBUG("Starting SASL interaction");
3930     remoteAuthInteractStateClear(state, false);
3931 
3932     /* Fills state->interact with any values from the auth config file */
3933     if (remoteAuthFillFromConfig(conn, state) < 0)
3934         return -1;
3935 
3936     /* Populates state->cred for anything not found in the auth config */
3937     if (remoteAuthMakeCredentials(state->interact, &state->cred, &state->ncred) < 0) {
3938         virReportError(VIR_ERR_AUTH_FAILED, "%s",
3939                        _("Failed to make auth credentials"));
3940         return -1;
3941     }
3942 
3943     /* If there was anything not in the auth config, we need to
3944      * run the interactive callback
3945      */
3946     if (state->ncred) {
3947         /* Run the authentication callback */
3948         if (!auth || !auth->cb) {
3949             virReportError(VIR_ERR_AUTH_FAILED, "%s",
3950                            _("No authentication callback available"));
3951             return -1;
3952         }
3953 
3954         if ((*(auth->cb))(state->cred, state->ncred, auth->cbdata) < 0) {
3955             virReportError(VIR_ERR_AUTH_FAILED, "%s",
3956                            _("Failed to collect auth credentials"));
3957             return -1;
3958         }
3959 
3960         /* Copy user's responses from cred into interact */
3961         remoteAuthFillInteract(state->cred, state->interact);
3962     }
3963 
3964     /*
3965      * 'interact' now has pointers to strings in 'state->cred'
3966      * so we must not free state->cred until the *next*
3967      * sasl_start/step function is complete. Hence we
3968      * call remoteAuthInteractStateClear() at the *start*
3969      * of this method, rather than the end.
3970      */
3971 
3972     return 0;
3973 }
3974 
3975 
3976 /* Perform the SASL authentication process
3977  */
3978 static int
remoteAuthSASL(virConnectPtr conn,struct private_data * priv,virConnectAuthPtr auth,const char * wantmech)3979 remoteAuthSASL(virConnectPtr conn, struct private_data *priv,
3980                virConnectAuthPtr auth, const char *wantmech)
3981 {
3982     remote_auth_sasl_init_ret iret;
3983     remote_auth_sasl_start_args sargs;
3984     remote_auth_sasl_start_ret sret;
3985     remote_auth_sasl_step_args pargs;
3986     remote_auth_sasl_step_ret pret;
3987     const char *clientout;
3988     char *serverin = NULL;
3989     size_t clientoutlen, serverinlen;
3990     const char *mech;
3991     int err, complete;
3992     int ssf;
3993     sasl_callback_t *saslcb = NULL;
3994     int ret = -1;
3995     const char *mechlist;
3996     virNetSASLContext *saslCtxt;
3997     virNetSASLSession *sasl = NULL;
3998     struct remoteAuthInteractState state;
3999 
4000     memset(&state, 0, sizeof(state));
4001 
4002     VIR_DEBUG("Client initialize SASL authentication");
4003 
4004     if (!(saslCtxt = virNetSASLContextNewClient()))
4005         goto cleanup;
4006 
4007     if (auth) {
4008         if ((saslcb = remoteAuthMakeCallbacks(auth->credtype, auth->ncredtype)) == NULL)
4009             goto cleanup;
4010     } else {
4011         saslcb = NULL;
4012     }
4013 
4014     /* Setup a handle for being a client */
4015     if (!(sasl = virNetSASLSessionNewClient(saslCtxt,
4016                                             "libvirt",
4017                                             priv->hostname,
4018                                             virNetClientLocalAddrStringSASL(priv->client),
4019                                             virNetClientRemoteAddrStringSASL(priv->client),
4020                                             saslcb)))
4021         goto cleanup;
4022     /* saslcb is now owned by sasl */
4023     saslcb = NULL;
4024 
4025     /* Initialize some connection props we care about */
4026     if (priv->tls) {
4027         if ((ssf = virNetClientGetTLSKeySize(priv->client)) < 0)
4028             goto cleanup;
4029 
4030         ssf *= 8; /* key size is bytes, sasl wants bits */
4031 
4032         VIR_DEBUG("Setting external SSF %d", ssf);
4033         if (virNetSASLSessionExtKeySize(sasl, ssf) < 0)
4034             goto cleanup;
4035     }
4036 
4037     /* If we've got a secure channel (TLS or UNIX sock), we don't care about SSF */
4038     /* If we're not secure, then forbid any anonymous or trivially crackable auth */
4039     if (virNetSASLSessionSecProps(sasl,
4040                                   priv->is_secure ? 0 : 56, /* Equiv to DES supported by all Kerberos */
4041                                   priv->is_secure ? 0 : 100000, /* Very strong ! AES == 256 */
4042                                   priv->is_secure ? true : false) < 0)
4043         goto cleanup;
4044 
4045     /* First call is to inquire about supported mechanisms in the server */
4046     memset(&iret, 0, sizeof(iret));
4047     if (call(conn, priv, 0, REMOTE_PROC_AUTH_SASL_INIT,
4048              (xdrproc_t) xdr_void, (char *)NULL,
4049              (xdrproc_t) xdr_remote_auth_sasl_init_ret, (char *) &iret) != 0)
4050         goto cleanup;
4051 
4052 
4053     mechlist = iret.mechlist;
4054     if (wantmech) {
4055         if (strstr(mechlist, wantmech) == NULL) {
4056             virReportError(VIR_ERR_AUTH_FAILED,
4057                            _("SASL mechanism %s not supported by server"),
4058                            wantmech);
4059             VIR_FREE(iret.mechlist);
4060             goto cleanup;
4061         }
4062         mechlist = wantmech;
4063     }
4064  restart:
4065     /* Start the auth negotiation on the client end first */
4066     VIR_DEBUG("Client start negotiation mechlist '%s'", mechlist);
4067     if ((err = virNetSASLSessionClientStart(sasl,
4068                                             mechlist,
4069                                             &state.interact,
4070                                             &clientout,
4071                                             &clientoutlen,
4072                                             &mech)) < 0)
4073         goto cleanup;
4074 
4075     /* Need to gather some credentials from the client */
4076     if (err == VIR_NET_SASL_INTERACT) {
4077         if (remoteAuthInteract(conn, &state, auth) < 0) {
4078             VIR_FREE(iret.mechlist);
4079             goto cleanup;
4080         }
4081         goto restart;
4082     }
4083     VIR_FREE(iret.mechlist);
4084 
4085     if (clientoutlen > REMOTE_AUTH_SASL_DATA_MAX) {
4086         virReportError(VIR_ERR_AUTH_FAILED,
4087                        _("SASL negotiation data too long: %zu bytes"),
4088                        clientoutlen);
4089         goto cleanup;
4090     }
4091     /* NB, distinction of NULL vs "" is *critical* in SASL */
4092     memset(&sargs, 0, sizeof(sargs));
4093     sargs.nil = clientout ? 0 : 1;
4094     sargs.data.data_val = (char*)clientout;
4095     sargs.data.data_len = clientoutlen;
4096     sargs.mech = (char*)mech;
4097     VIR_DEBUG("Server start negotiation with mech %s. Data %zu bytes %p",
4098               mech, clientoutlen, clientout);
4099 
4100     /* Now send the initial auth data to the server */
4101     memset(&sret, 0, sizeof(sret));
4102     if (call(conn, priv, 0, REMOTE_PROC_AUTH_SASL_START,
4103              (xdrproc_t) xdr_remote_auth_sasl_start_args, (char *) &sargs,
4104              (xdrproc_t) xdr_remote_auth_sasl_start_ret, (char *) &sret) != 0)
4105         goto cleanup;
4106 
4107     complete = sret.complete;
4108     /* NB, distinction of NULL vs "" is *critical* in SASL */
4109     serverin = sret.nil ? NULL : sret.data.data_val;
4110     serverinlen = sret.data.data_len;
4111     VIR_DEBUG("Client step result complete: %d. Data %zu bytes %p",
4112               complete, serverinlen, serverin);
4113 
4114     /* Previous server call showed completion & sasl_client_start() told us
4115      * we are locally complete too */
4116     if (complete && err == VIR_NET_SASL_COMPLETE)
4117         goto done;
4118 
4119     /* Loop-the-loop...
4120      * Even if the server has completed, the client must *always* do at least one step
4121      * in this loop to verify the server isn't lying about something. Mutual auth */
4122     for (;;) {
4123         if ((err = virNetSASLSessionClientStep(sasl,
4124                                                serverin,
4125                                                serverinlen,
4126                                                &state.interact,
4127                                                &clientout,
4128                                                &clientoutlen)) < 0)
4129             goto cleanup;
4130 
4131         /* Need to gather some credentials from the client */
4132         if (err == VIR_NET_SASL_INTERACT) {
4133             if (remoteAuthInteract(conn, &state, auth) < 0) {
4134                 VIR_FREE(iret.mechlist);
4135                 goto cleanup;
4136             }
4137             continue;
4138         }
4139 
4140         VIR_FREE(serverin);
4141         VIR_DEBUG("Client step result %d. Data %zu bytes %p",
4142                   err, clientoutlen, clientout);
4143 
4144         /* Previous server call showed completion & we're now locally complete too */
4145         if (complete && err == VIR_NET_SASL_COMPLETE)
4146             break;
4147 
4148         /* Not done, prepare to talk with the server for another iteration */
4149         /* NB, distinction of NULL vs "" is *critical* in SASL */
4150         memset(&pargs, 0, sizeof(pargs));
4151         pargs.nil = clientout ? 0 : 1;
4152         pargs.data.data_val = (char*)clientout;
4153         pargs.data.data_len = clientoutlen;
4154         VIR_DEBUG("Server step with %zu bytes %p",
4155                   clientoutlen, clientout);
4156 
4157         memset(&pret, 0, sizeof(pret));
4158         if (call(conn, priv, 0, REMOTE_PROC_AUTH_SASL_STEP,
4159                  (xdrproc_t) xdr_remote_auth_sasl_step_args, (char *) &pargs,
4160                  (xdrproc_t) xdr_remote_auth_sasl_step_ret, (char *) &pret) != 0)
4161             goto cleanup;
4162 
4163         complete = pret.complete;
4164         /* NB, distinction of NULL vs "" is *critical* in SASL */
4165         serverin = pret.nil ? NULL : pret.data.data_val;
4166         serverinlen = pret.data.data_len;
4167 
4168         VIR_DEBUG("Client step result complete: %d. Data %zu bytes %p",
4169                   complete, serverinlen, serverin);
4170 
4171         /* This server call shows complete, and earlier client step was OK */
4172         if (complete && err == VIR_NET_SASL_COMPLETE) {
4173             VIR_FREE(serverin);
4174             break;
4175         }
4176     }
4177 
4178     /* Check for suitable SSF if not already secure (TLS or UNIX sock) */
4179     if (!priv->is_secure) {
4180         if ((ssf = virNetSASLSessionGetKeySize(sasl)) < 0)
4181             goto cleanup;
4182 
4183         VIR_DEBUG("SASL SSF value %d", ssf);
4184         if (ssf < 56) { /* 56 == DES level, good for Kerberos */
4185             virReportError(VIR_ERR_AUTH_FAILED,
4186                            _("negotiation SSF %d was not strong enough"), ssf);
4187             goto cleanup;
4188         }
4189         if (ssf < SSF_WARNING_LEVEL) {
4190             VIR_WARN("negotiation SSF %d lower than %d will be deprecated. "
4191                      "Please upgrade your ciphers.",
4192                      ssf, SSF_WARNING_LEVEL);
4193         }
4194         priv->is_secure = 1;
4195     }
4196 
4197  done:
4198     VIR_DEBUG("SASL authentication complete");
4199     virNetClientSetSASLSession(priv->client, sasl);
4200     ret = 0;
4201 
4202  cleanup:
4203     VIR_FREE(serverin);
4204 
4205     remoteAuthInteractStateClear(&state, true);
4206     VIR_FREE(saslcb);
4207     virObjectUnref(sasl);
4208     virObjectUnref(saslCtxt);
4209 
4210     return ret;
4211 }
4212 #endif /* WITH_SASL */
4213 
4214 
4215 static int
remoteAuthPolkit(virConnectPtr conn,struct private_data * priv,virConnectAuthPtr auth G_GNUC_UNUSED)4216 remoteAuthPolkit(virConnectPtr conn, struct private_data *priv,
4217                  virConnectAuthPtr auth G_GNUC_UNUSED)
4218 {
4219     remote_auth_polkit_ret ret;
4220     VIR_DEBUG("Client initialize PolicyKit authentication");
4221 
4222     memset(&ret, 0, sizeof(ret));
4223     if (call(conn, priv, 0, REMOTE_PROC_AUTH_POLKIT,
4224              (xdrproc_t) xdr_void, (char *)NULL,
4225              (xdrproc_t) xdr_remote_auth_polkit_ret, (char *) &ret) != 0) {
4226         return -1; /* virError already set by call */
4227     }
4228 
4229     VIR_DEBUG("PolicyKit authentication complete");
4230     return 0;
4231 }
4232 
4233 /*----------------------------------------------------------------------*/
4234 
4235 static int
remoteConnectDomainEventRegister(virConnectPtr conn,virConnectDomainEventCallback callback,void * opaque,virFreeCallback freecb)4236 remoteConnectDomainEventRegister(virConnectPtr conn,
4237                                  virConnectDomainEventCallback callback,
4238                                  void *opaque,
4239                                  virFreeCallback freecb)
4240 {
4241     int callbackID;
4242     int rv = -1;
4243     struct private_data *priv = conn->privateData;
4244     int count;
4245 
4246     remoteDriverLock(priv);
4247 
4248     if ((count = virDomainEventStateRegisterClient(conn, priv->eventState,
4249                                                    NULL,
4250                                                    VIR_DOMAIN_EVENT_ID_LIFECYCLE,
4251                                                    VIR_DOMAIN_EVENT_CALLBACK(callback),
4252                                                    opaque, freecb, true,
4253                                                    &callbackID,
4254                                                    priv->serverEventFilter)) < 0)
4255          goto done;
4256 
4257     if (count == 1) {
4258         /* Tell the server when we are the first callback registering */
4259         if (priv->serverEventFilter) {
4260             remote_connect_domain_event_callback_register_any_args args;
4261             remote_connect_domain_event_callback_register_any_ret ret;
4262 
4263             args.eventID = VIR_DOMAIN_EVENT_ID_LIFECYCLE;
4264             args.dom = NULL;
4265 
4266             memset(&ret, 0, sizeof(ret));
4267             if (call(conn, priv, 0,
4268                      REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY,
4269                      (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_args, (char *) &args,
4270                      (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_ret, (char *) &ret) == -1) {
4271                 virObjectEventStateDeregisterID(conn, priv->eventState,
4272                                                 callbackID, false);
4273                 goto done;
4274             }
4275             virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
4276                                          ret.callbackID);
4277         } else {
4278             if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER,
4279                      (xdrproc_t) xdr_void, (char *) NULL,
4280                      (xdrproc_t) xdr_void, (char *) NULL) == -1) {
4281                 virObjectEventStateDeregisterID(conn, priv->eventState,
4282                                                 callbackID, false);
4283                 goto done;
4284             }
4285         }
4286     }
4287 
4288     rv = 0;
4289 
4290  done:
4291     remoteDriverUnlock(priv);
4292     return rv;
4293 }
4294 
4295 
4296 static int
remoteConnectDomainEventDeregister(virConnectPtr conn,virConnectDomainEventCallback callback)4297 remoteConnectDomainEventDeregister(virConnectPtr conn,
4298                                    virConnectDomainEventCallback callback)
4299 {
4300     struct private_data *priv = conn->privateData;
4301     int rv = -1;
4302     remote_connect_domain_event_callback_deregister_any_args args;
4303     int callbackID;
4304     int remoteID;
4305     int count;
4306 
4307     remoteDriverLock(priv);
4308 
4309     if ((callbackID = virDomainEventStateCallbackID(conn, priv->eventState,
4310                                                     callback,
4311                                                     &remoteID)) < 0)
4312         goto done;
4313 
4314     if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
4315                                                  callbackID, true)) < 0)
4316         goto done;
4317 
4318     if (count == 0) {
4319         /* Tell the server when we are the last callback deregistering */
4320         if (priv->serverEventFilter) {
4321             args.callbackID = remoteID;
4322 
4323             if (call(conn, priv, 0,
4324                      REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY,
4325                      (xdrproc_t) xdr_remote_connect_domain_event_callback_deregister_any_args, (char *) &args,
4326                      (xdrproc_t) xdr_void, (char *) NULL) == -1)
4327                 goto done;
4328         } else {
4329             if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER,
4330                      (xdrproc_t) xdr_void, (char *) NULL,
4331                      (xdrproc_t) xdr_void, (char *) NULL) == -1)
4332                 goto done;
4333         }
4334     }
4335 
4336     rv = 0;
4337 
4338  done:
4339     remoteDriverUnlock(priv);
4340     return rv;
4341 }
4342 
4343 
4344 static void
remoteDomainBuildEventLifecycleHelper(virConnectPtr conn,remote_domain_event_lifecycle_msg * msg,int callbackID)4345 remoteDomainBuildEventLifecycleHelper(virConnectPtr conn,
4346                                       remote_domain_event_lifecycle_msg *msg,
4347                                       int callbackID)
4348 {
4349     struct private_data *priv = conn->privateData;
4350     virDomainPtr dom;
4351     virObjectEvent *event = NULL;
4352 
4353     dom = get_nonnull_domain(conn, msg->dom);
4354     if (!dom)
4355         return;
4356 
4357     event = virDomainEventLifecycleNewFromDom(dom, msg->event, msg->detail);
4358     virObjectUnref(dom);
4359 
4360     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4361 }
4362 static void
remoteDomainBuildEventLifecycle(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4363 remoteDomainBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
4364                                 virNetClient *client G_GNUC_UNUSED,
4365                                 void *evdata, void *opaque)
4366 {
4367     virConnectPtr conn = opaque;
4368     remote_domain_event_lifecycle_msg *msg = evdata;
4369     remoteDomainBuildEventLifecycleHelper(conn, msg, -1);
4370 }
4371 static void
remoteDomainBuildEventCallbackLifecycle(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4372 remoteDomainBuildEventCallbackLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
4373                                         virNetClient *client G_GNUC_UNUSED,
4374                                         void *evdata, void *opaque)
4375 {
4376     virConnectPtr conn = opaque;
4377     remote_domain_event_callback_lifecycle_msg *msg = evdata;
4378     remoteDomainBuildEventLifecycleHelper(conn, &msg->msg, msg->callbackID);
4379 }
4380 
4381 
4382 static void
remoteDomainBuildEventRebootHelper(virConnectPtr conn,remote_domain_event_reboot_msg * msg,int callbackID)4383 remoteDomainBuildEventRebootHelper(virConnectPtr conn,
4384                                    remote_domain_event_reboot_msg *msg,
4385                                    int callbackID)
4386 {
4387     struct private_data *priv = conn->privateData;
4388     virDomainPtr dom;
4389     virObjectEvent *event = NULL;
4390 
4391     dom = get_nonnull_domain(conn, msg->dom);
4392     if (!dom)
4393         return;
4394 
4395     event = virDomainEventRebootNewFromDom(dom);
4396     virObjectUnref(dom);
4397 
4398     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4399 }
4400 static void
remoteDomainBuildEventReboot(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4401 remoteDomainBuildEventReboot(virNetClientProgram *prog G_GNUC_UNUSED,
4402                              virNetClient *client G_GNUC_UNUSED,
4403                              void *evdata, void *opaque)
4404 {
4405     virConnectPtr conn = opaque;
4406     remote_domain_event_reboot_msg *msg = evdata;
4407     remoteDomainBuildEventRebootHelper(conn, msg, -1);
4408 }
4409 static void
remoteDomainBuildEventCallbackReboot(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4410 remoteDomainBuildEventCallbackReboot(virNetClientProgram *prog G_GNUC_UNUSED,
4411                                      virNetClient *client G_GNUC_UNUSED,
4412                                      void *evdata, void *opaque)
4413 {
4414     virConnectPtr conn = opaque;
4415     remote_domain_event_callback_reboot_msg *msg = evdata;
4416     remoteDomainBuildEventRebootHelper(conn, &msg->msg, msg->callbackID);
4417 }
4418 
4419 static void
remoteDomainBuildEventRTCChangeHelper(virConnectPtr conn,remote_domain_event_rtc_change_msg * msg,int callbackID)4420 remoteDomainBuildEventRTCChangeHelper(virConnectPtr conn,
4421                                       remote_domain_event_rtc_change_msg *msg,
4422                                       int callbackID)
4423 {
4424     struct private_data *priv = conn->privateData;
4425     virDomainPtr dom;
4426     virObjectEvent *event = NULL;
4427 
4428     dom = get_nonnull_domain(conn, msg->dom);
4429     if (!dom)
4430         return;
4431 
4432     event = virDomainEventRTCChangeNewFromDom(dom, msg->offset);
4433     virObjectUnref(dom);
4434 
4435     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4436 }
4437 static void
remoteDomainBuildEventRTCChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4438 remoteDomainBuildEventRTCChange(virNetClientProgram *prog G_GNUC_UNUSED,
4439                                 virNetClient *client G_GNUC_UNUSED,
4440                                 void *evdata, void *opaque)
4441 {
4442     virConnectPtr conn = opaque;
4443     remote_domain_event_rtc_change_msg *msg = evdata;
4444     remoteDomainBuildEventRTCChangeHelper(conn, msg, -1);
4445 }
4446 static void
remoteDomainBuildEventCallbackRTCChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4447 remoteDomainBuildEventCallbackRTCChange(virNetClientProgram *prog G_GNUC_UNUSED,
4448                                         virNetClient *client G_GNUC_UNUSED,
4449                                         void *evdata, void *opaque)
4450 {
4451     virConnectPtr conn = opaque;
4452     remote_domain_event_callback_rtc_change_msg *msg = evdata;
4453     remoteDomainBuildEventRTCChangeHelper(conn, &msg->msg, msg->callbackID);
4454 }
4455 
4456 static void
remoteDomainBuildEventWatchdogHelper(virConnectPtr conn,remote_domain_event_watchdog_msg * msg,int callbackID)4457 remoteDomainBuildEventWatchdogHelper(virConnectPtr conn,
4458                                      remote_domain_event_watchdog_msg *msg,
4459                                      int callbackID)
4460 {
4461     struct private_data *priv = conn->privateData;
4462     virDomainPtr dom;
4463     virObjectEvent *event = NULL;
4464 
4465     dom = get_nonnull_domain(conn, msg->dom);
4466     if (!dom)
4467         return;
4468 
4469     event = virDomainEventWatchdogNewFromDom(dom, msg->action);
4470     virObjectUnref(dom);
4471 
4472     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4473 }
4474 static void
remoteDomainBuildEventWatchdog(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4475 remoteDomainBuildEventWatchdog(virNetClientProgram *prog G_GNUC_UNUSED,
4476                                virNetClient *client G_GNUC_UNUSED,
4477                                void *evdata, void *opaque)
4478 {
4479     virConnectPtr conn = opaque;
4480     remote_domain_event_watchdog_msg *msg = evdata;
4481     remoteDomainBuildEventWatchdogHelper(conn, msg, -1);
4482 }
4483 static void
remoteDomainBuildEventCallbackWatchdog(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4484 remoteDomainBuildEventCallbackWatchdog(virNetClientProgram *prog G_GNUC_UNUSED,
4485                                        virNetClient *client G_GNUC_UNUSED,
4486                                        void *evdata, void *opaque)
4487 {
4488     virConnectPtr conn = opaque;
4489     remote_domain_event_callback_watchdog_msg *msg = evdata;
4490     remoteDomainBuildEventWatchdogHelper(conn, &msg->msg, msg->callbackID);
4491 }
4492 
4493 static void
remoteDomainBuildEventIOErrorHelper(virConnectPtr conn,remote_domain_event_io_error_msg * msg,int callbackID)4494 remoteDomainBuildEventIOErrorHelper(virConnectPtr conn,
4495                                     remote_domain_event_io_error_msg *msg,
4496                                     int callbackID)
4497 {
4498     struct private_data *priv = conn->privateData;
4499     virDomainPtr dom;
4500     virObjectEvent *event = NULL;
4501 
4502     dom = get_nonnull_domain(conn, msg->dom);
4503     if (!dom)
4504         return;
4505 
4506     event = virDomainEventIOErrorNewFromDom(dom,
4507                                             msg->srcPath,
4508                                             msg->devAlias,
4509                                             msg->action);
4510     virObjectUnref(dom);
4511 
4512     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4513 }
4514 static void
remoteDomainBuildEventIOError(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4515 remoteDomainBuildEventIOError(virNetClientProgram *prog G_GNUC_UNUSED,
4516                               virNetClient *client G_GNUC_UNUSED,
4517                               void *evdata, void *opaque)
4518 {
4519     virConnectPtr conn = opaque;
4520     remote_domain_event_io_error_msg *msg = evdata;
4521     remoteDomainBuildEventIOErrorHelper(conn, msg, -1);
4522 }
4523 static void
remoteDomainBuildEventCallbackIOError(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4524 remoteDomainBuildEventCallbackIOError(virNetClientProgram *prog G_GNUC_UNUSED,
4525                                       virNetClient *client G_GNUC_UNUSED,
4526                                       void *evdata, void *opaque)
4527 {
4528     virConnectPtr conn = opaque;
4529     remote_domain_event_callback_io_error_msg *msg = evdata;
4530     remoteDomainBuildEventIOErrorHelper(conn, &msg->msg, msg->callbackID);
4531 }
4532 
4533 static void
remoteDomainBuildEventIOErrorReasonHelper(virConnectPtr conn,remote_domain_event_io_error_reason_msg * msg,int callbackID)4534 remoteDomainBuildEventIOErrorReasonHelper(virConnectPtr conn,
4535                                           remote_domain_event_io_error_reason_msg *msg,
4536                                           int callbackID)
4537 {
4538     struct private_data *priv = conn->privateData;
4539     virDomainPtr dom;
4540     virObjectEvent *event = NULL;
4541 
4542     dom = get_nonnull_domain(conn, msg->dom);
4543     if (!dom)
4544         return;
4545 
4546     event = virDomainEventIOErrorReasonNewFromDom(dom,
4547                                                   msg->srcPath,
4548                                                   msg->devAlias,
4549                                                   msg->action,
4550                                                   msg->reason);
4551 
4552     virObjectUnref(dom);
4553 
4554     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4555 }
4556 static void
remoteDomainBuildEventIOErrorReason(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4557 remoteDomainBuildEventIOErrorReason(virNetClientProgram *prog G_GNUC_UNUSED,
4558                                     virNetClient *client G_GNUC_UNUSED,
4559                                     void *evdata, void *opaque)
4560 {
4561     virConnectPtr conn = opaque;
4562     remote_domain_event_io_error_reason_msg *msg = evdata;
4563     remoteDomainBuildEventIOErrorReasonHelper(conn, msg, -1);
4564 }
4565 static void
remoteDomainBuildEventCallbackIOErrorReason(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4566 remoteDomainBuildEventCallbackIOErrorReason(virNetClientProgram *prog G_GNUC_UNUSED,
4567                                             virNetClient *client G_GNUC_UNUSED,
4568                                             void *evdata, void *opaque)
4569 {
4570     virConnectPtr conn = opaque;
4571     remote_domain_event_callback_io_error_reason_msg *msg = evdata;
4572     remoteDomainBuildEventIOErrorReasonHelper(conn, &msg->msg, msg->callbackID);
4573 }
4574 
4575 static void
remoteDomainBuildEventBlockJobHelper(virConnectPtr conn,remote_domain_event_block_job_msg * msg,int callbackID)4576 remoteDomainBuildEventBlockJobHelper(virConnectPtr conn,
4577                                      remote_domain_event_block_job_msg *msg,
4578                                      int callbackID)
4579 {
4580     struct private_data *priv = conn->privateData;
4581     virDomainPtr dom;
4582     virObjectEvent *event = NULL;
4583 
4584     dom = get_nonnull_domain(conn, msg->dom);
4585     if (!dom)
4586         return;
4587 
4588     event = virDomainEventBlockJobNewFromDom(dom, msg->path, msg->type,
4589                                              msg->status);
4590 
4591     virObjectUnref(dom);
4592 
4593     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4594 }
4595 static void
remoteDomainBuildEventBlockJob(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4596 remoteDomainBuildEventBlockJob(virNetClientProgram *prog G_GNUC_UNUSED,
4597                                virNetClient *client G_GNUC_UNUSED,
4598                                void *evdata, void *opaque)
4599 {
4600     virConnectPtr conn = opaque;
4601     remote_domain_event_block_job_msg *msg = evdata;
4602     remoteDomainBuildEventBlockJobHelper(conn, msg, -1);
4603 }
4604 static void
remoteDomainBuildEventCallbackBlockJob(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4605 remoteDomainBuildEventCallbackBlockJob(virNetClientProgram *prog G_GNUC_UNUSED,
4606                                        virNetClient *client G_GNUC_UNUSED,
4607                                        void *evdata, void *opaque)
4608 {
4609     virConnectPtr conn = opaque;
4610     remote_domain_event_callback_block_job_msg *msg = evdata;
4611     remoteDomainBuildEventBlockJobHelper(conn, &msg->msg, msg->callbackID);
4612 }
4613 static void
remoteDomainBuildEventBlockJob2(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4614 remoteDomainBuildEventBlockJob2(virNetClientProgram *prog G_GNUC_UNUSED,
4615                                 virNetClient *client G_GNUC_UNUSED,
4616                                 void *evdata, void *opaque)
4617 {
4618     virConnectPtr conn = opaque;
4619     remote_domain_event_block_job_2_msg *msg = evdata;
4620     struct private_data *priv = conn->privateData;
4621     virDomainPtr dom;
4622     virObjectEvent *event = NULL;
4623 
4624     dom = get_nonnull_domain(conn, msg->dom);
4625     if (!dom)
4626         return;
4627 
4628     event = virDomainEventBlockJob2NewFromDom(dom, msg->dst, msg->type,
4629                                               msg->status);
4630 
4631     virObjectUnref(dom);
4632 
4633     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
4634 }
4635 
4636 static void
remoteDomainBuildEventGraphicsHelper(virConnectPtr conn,remote_domain_event_graphics_msg * msg,int callbackID)4637 remoteDomainBuildEventGraphicsHelper(virConnectPtr conn,
4638                                      remote_domain_event_graphics_msg *msg,
4639                                      int callbackID)
4640 {
4641     struct private_data *priv = conn->privateData;
4642     virDomainPtr dom;
4643     virObjectEvent *event = NULL;
4644     virDomainEventGraphicsAddressPtr localAddr = NULL;
4645     virDomainEventGraphicsAddressPtr remoteAddr = NULL;
4646     virDomainEventGraphicsSubjectPtr subject = NULL;
4647     size_t i;
4648 
4649     dom = get_nonnull_domain(conn, msg->dom);
4650     if (!dom)
4651         return;
4652 
4653     localAddr = g_new0(virDomainEventGraphicsAddress, 1);
4654     localAddr->family = msg->local.family;
4655     localAddr->service = g_strdup(msg->local.service);
4656     localAddr->node = g_strdup(msg->local.node);
4657 
4658     remoteAddr = g_new0(virDomainEventGraphicsAddress, 1);
4659     remoteAddr->family = msg->remote.family;
4660     remoteAddr->service = g_strdup(msg->remote.service);
4661     remoteAddr->node = g_strdup(msg->remote.node);
4662 
4663     subject = g_new0(virDomainEventGraphicsSubject, 1);
4664     subject->identities = g_new0(virDomainEventGraphicsSubjectIdentity, msg->subject.subject_len);
4665     subject->nidentity = msg->subject.subject_len;
4666     for (i = 0; i < subject->nidentity; i++) {
4667         subject->identities[i].type = g_strdup(msg->subject.subject_val[i].type);
4668         subject->identities[i].name = g_strdup(msg->subject.subject_val[i].name);
4669     }
4670 
4671     event = virDomainEventGraphicsNewFromDom(dom,
4672                                              msg->phase,
4673                                              localAddr,
4674                                              remoteAddr,
4675                                              msg->authScheme,
4676                                              subject);
4677 
4678     virObjectUnref(dom);
4679 
4680     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4681     return;
4682 }
4683 static void
remoteDomainBuildEventGraphics(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4684 remoteDomainBuildEventGraphics(virNetClientProgram *prog G_GNUC_UNUSED,
4685                                virNetClient *client G_GNUC_UNUSED,
4686                                void *evdata, void *opaque)
4687 {
4688     virConnectPtr conn = opaque;
4689     remote_domain_event_graphics_msg *msg = evdata;
4690     remoteDomainBuildEventGraphicsHelper(conn, msg, -1);
4691 }
4692 static void
remoteDomainBuildEventCallbackGraphics(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4693 remoteDomainBuildEventCallbackGraphics(virNetClientProgram *prog G_GNUC_UNUSED,
4694                                        virNetClient *client G_GNUC_UNUSED,
4695                                        void *evdata, void *opaque)
4696 {
4697     virConnectPtr conn = opaque;
4698     remote_domain_event_callback_graphics_msg *msg = evdata;
4699     remoteDomainBuildEventGraphicsHelper(conn, &msg->msg, msg->callbackID);
4700 }
4701 
4702 static void
remoteDomainBuildEventControlErrorHelper(virConnectPtr conn,remote_domain_event_control_error_msg * msg,int callbackID)4703 remoteDomainBuildEventControlErrorHelper(virConnectPtr conn,
4704                                          remote_domain_event_control_error_msg *msg,
4705                                          int callbackID)
4706 {
4707     struct private_data *priv = conn->privateData;
4708     virDomainPtr dom;
4709     virObjectEvent *event = NULL;
4710 
4711     dom = get_nonnull_domain(conn, msg->dom);
4712     if (!dom)
4713         return;
4714 
4715     event = virDomainEventControlErrorNewFromDom(dom);
4716 
4717     virObjectUnref(dom);
4718 
4719     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4720 }
4721 static void
remoteDomainBuildEventControlError(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4722 remoteDomainBuildEventControlError(virNetClientProgram *prog G_GNUC_UNUSED,
4723                                    virNetClient *client G_GNUC_UNUSED,
4724                                    void *evdata, void *opaque)
4725 {
4726     virConnectPtr conn = opaque;
4727     remote_domain_event_control_error_msg *msg = evdata;
4728     remoteDomainBuildEventControlErrorHelper(conn, msg, -1);
4729 }
4730 static void
remoteDomainBuildEventCallbackControlError(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4731 remoteDomainBuildEventCallbackControlError(virNetClientProgram *prog G_GNUC_UNUSED,
4732                                            virNetClient *client G_GNUC_UNUSED,
4733                                            void *evdata, void *opaque)
4734 {
4735     virConnectPtr conn = opaque;
4736     remote_domain_event_callback_control_error_msg *msg = evdata;
4737     remoteDomainBuildEventControlErrorHelper(conn, &msg->msg, msg->callbackID);
4738 }
4739 
4740 
4741 static void
remoteDomainBuildEventDiskChangeHelper(virConnectPtr conn,remote_domain_event_disk_change_msg * msg,int callbackID)4742 remoteDomainBuildEventDiskChangeHelper(virConnectPtr conn,
4743                                        remote_domain_event_disk_change_msg *msg,
4744                                        int callbackID)
4745 {
4746     struct private_data *priv = conn->privateData;
4747     virDomainPtr dom;
4748     virObjectEvent *event = NULL;
4749 
4750     dom = get_nonnull_domain(conn, msg->dom);
4751     if (!dom)
4752         return;
4753 
4754     event = virDomainEventDiskChangeNewFromDom(dom,
4755                                                msg->oldSrcPath ? *msg->oldSrcPath : NULL,
4756                                                msg->newSrcPath ? *msg->newSrcPath : NULL,
4757                                                msg->devAlias,
4758                                                msg->reason);
4759 
4760     virObjectUnref(dom);
4761 
4762     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4763 }
4764 static void
remoteDomainBuildEventDiskChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4765 remoteDomainBuildEventDiskChange(virNetClientProgram *prog G_GNUC_UNUSED,
4766                                  virNetClient *client G_GNUC_UNUSED,
4767                                  void *evdata, void *opaque)
4768 {
4769     virConnectPtr conn = opaque;
4770     remote_domain_event_disk_change_msg *msg = evdata;
4771     remoteDomainBuildEventDiskChangeHelper(conn, msg, -1);
4772 }
4773 static void
remoteDomainBuildEventCallbackDiskChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4774 remoteDomainBuildEventCallbackDiskChange(virNetClientProgram *prog G_GNUC_UNUSED,
4775                                          virNetClient *client G_GNUC_UNUSED,
4776                                          void *evdata, void *opaque)
4777 {
4778     virConnectPtr conn = opaque;
4779     remote_domain_event_callback_disk_change_msg *msg = evdata;
4780     remoteDomainBuildEventDiskChangeHelper(conn, &msg->msg, msg->callbackID);
4781 }
4782 
4783 
4784 static void
remoteDomainBuildEventTrayChangeHelper(virConnectPtr conn,remote_domain_event_tray_change_msg * msg,int callbackID)4785 remoteDomainBuildEventTrayChangeHelper(virConnectPtr conn,
4786                                        remote_domain_event_tray_change_msg *msg,
4787                                        int callbackID)
4788 {
4789     struct private_data *priv = conn->privateData;
4790     virDomainPtr dom;
4791     virObjectEvent *event = NULL;
4792 
4793     dom = get_nonnull_domain(conn, msg->dom);
4794     if (!dom)
4795         return;
4796 
4797     event = virDomainEventTrayChangeNewFromDom(dom,
4798                                                msg->devAlias,
4799                                                msg->reason);
4800 
4801     virObjectUnref(dom);
4802 
4803     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4804 }
4805 static void
remoteDomainBuildEventTrayChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4806 remoteDomainBuildEventTrayChange(virNetClientProgram *prog G_GNUC_UNUSED,
4807                                  virNetClient *client G_GNUC_UNUSED,
4808                                  void *evdata, void *opaque)
4809 {
4810     virConnectPtr conn = opaque;
4811     remote_domain_event_tray_change_msg *msg = evdata;
4812     remoteDomainBuildEventTrayChangeHelper(conn, msg, -1);
4813 }
4814 static void
remoteDomainBuildEventCallbackTrayChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4815 remoteDomainBuildEventCallbackTrayChange(virNetClientProgram *prog G_GNUC_UNUSED,
4816                                          virNetClient *client G_GNUC_UNUSED,
4817                                          void *evdata, void *opaque)
4818 {
4819     virConnectPtr conn = opaque;
4820     remote_domain_event_callback_tray_change_msg *msg = evdata;
4821     remoteDomainBuildEventTrayChangeHelper(conn, &msg->msg, msg->callbackID);
4822 }
4823 
4824 static void
remoteDomainBuildEventPMWakeupHelper(virConnectPtr conn,remote_domain_event_pmwakeup_msg * msg,int callbackID,int reason)4825 remoteDomainBuildEventPMWakeupHelper(virConnectPtr conn,
4826                                      remote_domain_event_pmwakeup_msg *msg,
4827                                      int callbackID,
4828                                      int reason)
4829 {
4830     struct private_data *priv = conn->privateData;
4831     virDomainPtr dom;
4832     virObjectEvent *event = NULL;
4833 
4834     dom = get_nonnull_domain(conn, msg->dom);
4835     if (!dom)
4836         return;
4837 
4838     event = virDomainEventPMWakeupNewFromDom(dom, reason);
4839 
4840     virObjectUnref(dom);
4841 
4842     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4843 }
4844 static void
remoteDomainBuildEventPMWakeup(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4845 remoteDomainBuildEventPMWakeup(virNetClientProgram *prog G_GNUC_UNUSED,
4846                                virNetClient *client G_GNUC_UNUSED,
4847                                void *evdata, void *opaque)
4848 {
4849     virConnectPtr conn = opaque;
4850     remote_domain_event_pmwakeup_msg *msg = evdata;
4851     remoteDomainBuildEventPMWakeupHelper(conn, msg, -1, 0);
4852 }
4853 static void
remoteDomainBuildEventCallbackPMWakeup(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4854 remoteDomainBuildEventCallbackPMWakeup(virNetClientProgram *prog G_GNUC_UNUSED,
4855                                        virNetClient *client G_GNUC_UNUSED,
4856                                        void *evdata, void *opaque)
4857 {
4858     virConnectPtr conn = opaque;
4859     remote_domain_event_callback_pmwakeup_msg *msg = evdata;
4860     remoteDomainBuildEventPMWakeupHelper(conn, &msg->msg, msg->callbackID,
4861                                          msg->reason);
4862 }
4863 
4864 static void
remoteDomainBuildEventPMSuspendHelper(virConnectPtr conn,remote_domain_event_pmsuspend_msg * msg,int callbackID,int reason)4865 remoteDomainBuildEventPMSuspendHelper(virConnectPtr conn,
4866                                       remote_domain_event_pmsuspend_msg *msg,
4867                                       int callbackID,
4868                                       int reason)
4869 {
4870     struct private_data *priv = conn->privateData;
4871     virDomainPtr dom;
4872     virObjectEvent *event = NULL;
4873 
4874     dom = get_nonnull_domain(conn, msg->dom);
4875     if (!dom)
4876         return;
4877 
4878     event = virDomainEventPMSuspendNewFromDom(dom, reason);
4879 
4880     virObjectUnref(dom);
4881 
4882     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4883 }
4884 static void
remoteDomainBuildEventPMSuspend(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4885 remoteDomainBuildEventPMSuspend(virNetClientProgram *prog G_GNUC_UNUSED,
4886                                 virNetClient *client G_GNUC_UNUSED,
4887                                 void *evdata, void *opaque)
4888 {
4889     virConnectPtr conn = opaque;
4890     remote_domain_event_pmsuspend_msg *msg = evdata;
4891     remoteDomainBuildEventPMSuspendHelper(conn, msg, -1, 0);
4892 }
4893 static void
remoteDomainBuildEventCallbackPMSuspend(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4894 remoteDomainBuildEventCallbackPMSuspend(virNetClientProgram *prog G_GNUC_UNUSED,
4895                                         virNetClient *client G_GNUC_UNUSED,
4896                                         void *evdata, void *opaque)
4897 {
4898     virConnectPtr conn = opaque;
4899     remote_domain_event_callback_pmsuspend_msg *msg = evdata;
4900     remoteDomainBuildEventPMSuspendHelper(conn, &msg->msg, msg->callbackID,
4901                                           msg->reason);
4902 }
4903 
4904 
4905 static void
remoteDomainBuildEventBalloonChangeHelper(virConnectPtr conn,remote_domain_event_balloon_change_msg * msg,int callbackID)4906 remoteDomainBuildEventBalloonChangeHelper(virConnectPtr conn,
4907                                           remote_domain_event_balloon_change_msg *msg,
4908                                           int callbackID)
4909 {
4910     struct private_data *priv = conn->privateData;
4911     virDomainPtr dom;
4912     virObjectEvent *event = NULL;
4913 
4914     dom = get_nonnull_domain(conn, msg->dom);
4915     if (!dom)
4916         return;
4917 
4918     event = virDomainEventBalloonChangeNewFromDom(dom, msg->actual);
4919     virObjectUnref(dom);
4920 
4921     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4922 }
4923 static void
remoteDomainBuildEventBalloonChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4924 remoteDomainBuildEventBalloonChange(virNetClientProgram *prog G_GNUC_UNUSED,
4925                                     virNetClient *client G_GNUC_UNUSED,
4926                                     void *evdata, void *opaque)
4927 {
4928     virConnectPtr conn = opaque;
4929     remote_domain_event_balloon_change_msg *msg = evdata;
4930     remoteDomainBuildEventBalloonChangeHelper(conn, msg, -1);
4931 }
4932 static void
remoteDomainBuildEventCallbackBalloonChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4933 remoteDomainBuildEventCallbackBalloonChange(virNetClientProgram *prog G_GNUC_UNUSED,
4934                                             virNetClient *client G_GNUC_UNUSED,
4935                                             void *evdata, void *opaque)
4936 {
4937     virConnectPtr conn = opaque;
4938     remote_domain_event_callback_balloon_change_msg *msg = evdata;
4939     remoteDomainBuildEventBalloonChangeHelper(conn, &msg->msg, msg->callbackID);
4940 }
4941 
4942 
4943 static void
remoteDomainBuildEventPMSuspendDiskHelper(virConnectPtr conn,remote_domain_event_pmsuspend_disk_msg * msg,int callbackID,int reason)4944 remoteDomainBuildEventPMSuspendDiskHelper(virConnectPtr conn,
4945                                           remote_domain_event_pmsuspend_disk_msg *msg,
4946                                           int callbackID,
4947                                           int reason)
4948 {
4949     struct private_data *priv = conn->privateData;
4950     virDomainPtr dom;
4951     virObjectEvent *event = NULL;
4952 
4953     dom = get_nonnull_domain(conn, msg->dom);
4954     if (!dom)
4955         return;
4956 
4957     event = virDomainEventPMSuspendDiskNewFromDom(dom, reason);
4958 
4959     virObjectUnref(dom);
4960 
4961     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
4962 }
4963 static void
remoteDomainBuildEventPMSuspendDisk(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4964 remoteDomainBuildEventPMSuspendDisk(virNetClientProgram *prog G_GNUC_UNUSED,
4965                                     virNetClient *client G_GNUC_UNUSED,
4966                                     void *evdata, void *opaque)
4967 {
4968     virConnectPtr conn = opaque;
4969     remote_domain_event_pmsuspend_disk_msg *msg = evdata;
4970     remoteDomainBuildEventPMSuspendDiskHelper(conn, msg, -1, 0);
4971 }
4972 static void
remoteDomainBuildEventCallbackPMSuspendDisk(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)4973 remoteDomainBuildEventCallbackPMSuspendDisk(virNetClientProgram *prog G_GNUC_UNUSED,
4974                                             virNetClient *client G_GNUC_UNUSED,
4975                                             void *evdata, void *opaque)
4976 {
4977     virConnectPtr conn = opaque;
4978     remote_domain_event_callback_pmsuspend_disk_msg *msg = evdata;
4979     remoteDomainBuildEventPMSuspendDiskHelper(conn, &msg->msg, msg->callbackID,
4980                                               msg->reason);
4981 }
4982 
4983 
4984 static void
remoteDomainBuildEventDeviceRemovedHelper(virConnectPtr conn,remote_domain_event_device_removed_msg * msg,int callbackID)4985 remoteDomainBuildEventDeviceRemovedHelper(virConnectPtr conn,
4986                                           remote_domain_event_device_removed_msg *msg,
4987                                           int callbackID)
4988 {
4989     struct private_data *priv = conn->privateData;
4990     virDomainPtr dom;
4991     virObjectEvent *event = NULL;
4992 
4993     dom = get_nonnull_domain(conn, msg->dom);
4994     if (!dom)
4995         return;
4996 
4997     event = virDomainEventDeviceRemovedNewFromDom(dom, msg->devAlias);
4998 
4999     virObjectUnref(dom);
5000 
5001     virObjectEventStateQueueRemote(priv->eventState, event, callbackID);
5002 }
5003 static void
remoteDomainBuildEventDeviceRemoved(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5004 remoteDomainBuildEventDeviceRemoved(virNetClientProgram *prog G_GNUC_UNUSED,
5005                                     virNetClient *client G_GNUC_UNUSED,
5006                                     void *evdata, void *opaque)
5007 {
5008     virConnectPtr conn = opaque;
5009     remote_domain_event_device_removed_msg *msg = evdata;
5010     remoteDomainBuildEventDeviceRemovedHelper(conn, msg, -1);
5011 }
5012 static void
remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5013 remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgram *prog G_GNUC_UNUSED,
5014                                             virNetClient *client G_GNUC_UNUSED,
5015                                             void *evdata, void *opaque)
5016 {
5017     virConnectPtr conn = opaque;
5018     remote_domain_event_callback_device_removed_msg *msg = evdata;
5019     remoteDomainBuildEventDeviceRemovedHelper(conn, &msg->msg, msg->callbackID);
5020 }
5021 
5022 static void
remoteDomainBuildEventCallbackDeviceAdded(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5023 remoteDomainBuildEventCallbackDeviceAdded(virNetClientProgram *prog G_GNUC_UNUSED,
5024                                           virNetClient *client G_GNUC_UNUSED,
5025                                           void *evdata, void *opaque)
5026 {
5027     virConnectPtr conn = opaque;
5028     remote_domain_event_callback_device_added_msg *msg = evdata;
5029     struct private_data *priv = conn->privateData;
5030     virDomainPtr dom;
5031     virObjectEvent *event = NULL;
5032 
5033     dom = get_nonnull_domain(conn, msg->dom);
5034     if (!dom)
5035         return;
5036 
5037     event = virDomainEventDeviceAddedNewFromDom(dom, msg->devAlias);
5038 
5039     virObjectUnref(dom);
5040 
5041     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5042 }
5043 
5044 
5045 static void
remoteDomainBuildEventCallbackDeviceRemovalFailed(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5046 remoteDomainBuildEventCallbackDeviceRemovalFailed(virNetClientProgram *prog G_GNUC_UNUSED,
5047                                                   virNetClient *client G_GNUC_UNUSED,
5048                                                   void *evdata, void *opaque)
5049 {
5050     virConnectPtr conn = opaque;
5051     remote_domain_event_callback_device_removal_failed_msg *msg = evdata;
5052     struct private_data *priv = conn->privateData;
5053     virDomainPtr dom;
5054     virObjectEvent *event = NULL;
5055 
5056     if (!(dom = get_nonnull_domain(conn, msg->dom)))
5057         return;
5058 
5059     event = virDomainEventDeviceRemovalFailedNewFromDom(dom, msg->devAlias);
5060 
5061     virObjectUnref(dom);
5062 
5063     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5064 }
5065 
5066 static void
remoteDomainBuildEventCallbackTunable(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5067 remoteDomainBuildEventCallbackTunable(virNetClientProgram *prog G_GNUC_UNUSED,
5068                                       virNetClient *client G_GNUC_UNUSED,
5069                                       void *evdata, void *opaque)
5070 {
5071     virConnectPtr conn = opaque;
5072     remote_domain_event_callback_tunable_msg *msg = evdata;
5073     struct private_data *priv = conn->privateData;
5074     virDomainPtr dom;
5075     virTypedParameterPtr params = NULL;
5076     int nparams = 0;
5077     virObjectEvent *event = NULL;
5078 
5079     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) msg->params.params_val,
5080                                   msg->params.params_len,
5081                                   REMOTE_DOMAIN_EVENT_TUNABLE_MAX,
5082                                   &params, &nparams) < 0)
5083         return;
5084 
5085     dom = get_nonnull_domain(conn, msg->dom);
5086     if (!dom) {
5087         virTypedParamsFree(params, nparams);
5088         return;
5089     }
5090 
5091     event = virDomainEventTunableNewFromDom(dom, params, nparams);
5092 
5093     virObjectUnref(dom);
5094 
5095     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5096 }
5097 
5098 
5099 static void
remoteDomainBuildEventCallbackAgentLifecycle(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5100 remoteDomainBuildEventCallbackAgentLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
5101                                              virNetClient *client G_GNUC_UNUSED,
5102                                              void *evdata, void *opaque)
5103 {
5104     virConnectPtr conn = opaque;
5105     remote_domain_event_callback_agent_lifecycle_msg *msg = evdata;
5106     struct private_data *priv = conn->privateData;
5107     virDomainPtr dom;
5108     virObjectEvent *event = NULL;
5109 
5110     if (!(dom = get_nonnull_domain(conn, msg->dom)))
5111         return;
5112 
5113     event = virDomainEventAgentLifecycleNewFromDom(dom, msg->state,
5114                                                    msg->reason);
5115 
5116     virObjectUnref(dom);
5117 
5118     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5119 }
5120 
5121 
5122 static void
remoteDomainBuildEventCallbackMigrationIteration(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5123 remoteDomainBuildEventCallbackMigrationIteration(virNetClientProgram *prog G_GNUC_UNUSED,
5124                                                  virNetClient *client G_GNUC_UNUSED,
5125                                                  void *evdata,
5126                                                  void *opaque)
5127 {
5128     virConnectPtr conn = opaque;
5129     remote_domain_event_callback_migration_iteration_msg *msg = evdata;
5130     struct private_data *priv = conn->privateData;
5131     virDomainPtr dom;
5132     virObjectEvent *event = NULL;
5133 
5134     if (!(dom = get_nonnull_domain(conn, msg->dom)))
5135         return;
5136 
5137     event = virDomainEventMigrationIterationNewFromDom(dom, msg->iteration);
5138 
5139     virObjectUnref(dom);
5140 
5141     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5142 }
5143 
5144 
5145 static void
remoteDomainBuildEventCallbackJobCompleted(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5146 remoteDomainBuildEventCallbackJobCompleted(virNetClientProgram *prog G_GNUC_UNUSED,
5147                                            virNetClient *client G_GNUC_UNUSED,
5148                                            void *evdata,
5149                                            void *opaque)
5150 {
5151     virConnectPtr conn = opaque;
5152     remote_domain_event_callback_job_completed_msg *msg = evdata;
5153     struct private_data *priv = conn->privateData;
5154     virDomainPtr dom;
5155     virObjectEvent *event = NULL;
5156     virTypedParameterPtr params = NULL;
5157     int nparams = 0;
5158 
5159     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) msg->params.params_val,
5160                                   msg->params.params_len,
5161                                   REMOTE_DOMAIN_JOB_STATS_MAX,
5162                                   &params, &nparams) < 0)
5163         return;
5164 
5165     if (!(dom = get_nonnull_domain(conn, msg->dom))) {
5166         virTypedParamsFree(params, nparams);
5167         return;
5168     }
5169 
5170     event = virDomainEventJobCompletedNewFromDom(dom, params, nparams);
5171 
5172     virObjectUnref(dom);
5173 
5174     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5175 }
5176 
5177 
5178 static void
remoteDomainBuildEventCallbackMetadataChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5179 remoteDomainBuildEventCallbackMetadataChange(virNetClientProgram *prog G_GNUC_UNUSED,
5180                                              virNetClient *client G_GNUC_UNUSED,
5181                                              void *evdata, void *opaque)
5182 {
5183     virConnectPtr conn = opaque;
5184     remote_domain_event_callback_metadata_change_msg *msg = evdata;
5185     struct private_data *priv = conn->privateData;
5186     virDomainPtr dom;
5187     virObjectEvent *event = NULL;
5188 
5189     if (!(dom = get_nonnull_domain(conn, msg->dom)))
5190         return;
5191 
5192     event = virDomainEventMetadataChangeNewFromDom(dom, msg->type, msg->nsuri ? *msg->nsuri : NULL);
5193 
5194     virObjectUnref(dom);
5195 
5196     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5197 }
5198 
5199 
5200 static void
remoteNetworkBuildEventLifecycle(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5201 remoteNetworkBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
5202                                  virNetClient *client G_GNUC_UNUSED,
5203                                  void *evdata, void *opaque)
5204 {
5205     virConnectPtr conn = opaque;
5206     struct private_data *priv = conn->privateData;
5207     remote_network_event_lifecycle_msg *msg = evdata;
5208     virNetworkPtr net;
5209     virObjectEvent *event = NULL;
5210 
5211     net = get_nonnull_network(conn, msg->net);
5212     if (!net)
5213         return;
5214 
5215     event = virNetworkEventLifecycleNew(net->name, net->uuid, msg->event,
5216                                         msg->detail);
5217     virObjectUnref(net);
5218 
5219     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5220 }
5221 
5222 static void
remoteStoragePoolBuildEventLifecycle(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5223 remoteStoragePoolBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
5224                                      virNetClient *client G_GNUC_UNUSED,
5225                                      void *evdata, void *opaque)
5226 {
5227     virConnectPtr conn = opaque;
5228     struct private_data *priv = conn->privateData;
5229     remote_storage_pool_event_lifecycle_msg *msg = evdata;
5230     virStoragePoolPtr pool;
5231     virObjectEvent *event = NULL;
5232 
5233     pool = get_nonnull_storage_pool(conn, msg->pool);
5234     if (!pool)
5235         return;
5236 
5237     event = virStoragePoolEventLifecycleNew(pool->name, pool->uuid, msg->event,
5238                                             msg->detail);
5239     virObjectUnref(pool);
5240 
5241     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5242 }
5243 
5244 static void
remoteStoragePoolBuildEventRefresh(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5245 remoteStoragePoolBuildEventRefresh(virNetClientProgram *prog G_GNUC_UNUSED,
5246                                    virNetClient *client G_GNUC_UNUSED,
5247                                    void *evdata, void *opaque)
5248 {
5249     virConnectPtr conn = opaque;
5250     struct private_data *priv = conn->privateData;
5251     remote_storage_pool_event_refresh_msg *msg = evdata;
5252     virStoragePoolPtr pool;
5253     virObjectEvent *event = NULL;
5254 
5255     pool = get_nonnull_storage_pool(conn, msg->pool);
5256     if (!pool)
5257         return;
5258 
5259     event = virStoragePoolEventRefreshNew(pool->name, pool->uuid);
5260     virObjectUnref(pool);
5261 
5262     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5263 }
5264 
5265 static void
remoteNodeDeviceBuildEventLifecycle(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5266 remoteNodeDeviceBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
5267                                     virNetClient *client G_GNUC_UNUSED,
5268                                     void *evdata, void *opaque)
5269 {
5270     virConnectPtr conn = opaque;
5271     struct private_data *priv = conn->privateData;
5272     remote_node_device_event_lifecycle_msg *msg = evdata;
5273     virNodeDevicePtr dev;
5274     virObjectEvent *event = NULL;
5275 
5276     dev = get_nonnull_node_device(conn, msg->dev);
5277     if (!dev)
5278         return;
5279 
5280     event = virNodeDeviceEventLifecycleNew(dev->name, msg->event,
5281                                            msg->detail);
5282     virObjectUnref(dev);
5283 
5284     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5285 }
5286 
5287 static void
remoteNodeDeviceBuildEventUpdate(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5288 remoteNodeDeviceBuildEventUpdate(virNetClientProgram *prog G_GNUC_UNUSED,
5289                                  virNetClient *client G_GNUC_UNUSED,
5290                                  void *evdata, void *opaque)
5291 {
5292     virConnectPtr conn = opaque;
5293     struct private_data *priv = conn->privateData;
5294     remote_node_device_event_update_msg *msg = evdata;
5295     virNodeDevicePtr dev;
5296     virObjectEvent *event = NULL;
5297 
5298     dev = get_nonnull_node_device(conn, msg->dev);
5299     if (!dev)
5300         return;
5301 
5302     event = virNodeDeviceEventUpdateNew(dev->name);
5303     virObjectUnref(dev);
5304 
5305     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5306 }
5307 
5308 static void
remoteSecretBuildEventLifecycle(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5309 remoteSecretBuildEventLifecycle(virNetClientProgram *prog G_GNUC_UNUSED,
5310                                 virNetClient *client G_GNUC_UNUSED,
5311                                 void *evdata, void *opaque)
5312 {
5313     virConnectPtr conn = opaque;
5314     struct private_data *priv = conn->privateData;
5315     remote_secret_event_lifecycle_msg *msg = evdata;
5316     virSecretPtr secret;
5317     virObjectEvent *event = NULL;
5318 
5319     secret = get_nonnull_secret(conn, msg->secret);
5320     if (!secret)
5321         return;
5322 
5323     event = virSecretEventLifecycleNew(secret->uuid, secret->usageType, secret->usageID,
5324                                        msg->event, msg->detail);
5325     virObjectUnref(secret);
5326 
5327     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5328 }
5329 
5330 static void
remoteSecretBuildEventValueChanged(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5331 remoteSecretBuildEventValueChanged(virNetClientProgram *prog G_GNUC_UNUSED,
5332                                    virNetClient *client G_GNUC_UNUSED,
5333                                    void *evdata, void *opaque)
5334 {
5335     virConnectPtr conn = opaque;
5336     struct private_data *priv = conn->privateData;
5337     remote_secret_event_value_changed_msg *msg = evdata;
5338     virSecretPtr secret;
5339     virObjectEvent *event = NULL;
5340 
5341     secret = get_nonnull_secret(conn, msg->secret);
5342     if (!secret)
5343         return;
5344 
5345     event = virSecretEventValueChangedNew(secret->uuid, secret->usageType, secret->usageID);
5346     virObjectUnref(secret);
5347 
5348     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5349 }
5350 
5351 static void
remoteDomainBuildQemuMonitorEvent(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5352 remoteDomainBuildQemuMonitorEvent(virNetClientProgram *prog G_GNUC_UNUSED,
5353                                   virNetClient *client G_GNUC_UNUSED,
5354                                   void *evdata, void *opaque)
5355 {
5356     virConnectPtr conn = opaque;
5357     struct private_data *priv = conn->privateData;
5358     qemu_domain_monitor_event_msg *msg = evdata;
5359     virDomainPtr dom;
5360     virObjectEvent *event = NULL;
5361 
5362     dom = get_nonnull_domain(conn, msg->dom);
5363     if (!dom)
5364         return;
5365 
5366     event = virDomainQemuMonitorEventNew(dom->id, dom->name, dom->uuid,
5367                                          msg->event, msg->seconds,
5368                                          msg->micros,
5369                                          msg->details ? *msg->details : NULL);
5370     virObjectUnref(dom);
5371 
5372     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5373 }
5374 
5375 
5376 static unsigned char *
remoteSecretGetValue(virSecretPtr secret,size_t * value_size,unsigned int flags)5377 remoteSecretGetValue(virSecretPtr secret, size_t *value_size,
5378                      unsigned int flags)
5379 {
5380     unsigned char *rv = NULL;
5381     remote_secret_get_value_args args;
5382     remote_secret_get_value_ret ret;
5383     struct private_data *priv = secret->conn->privateData;
5384 
5385     remoteDriverLock(priv);
5386 
5387     make_nonnull_secret(&args.secret, secret);
5388     args.flags = flags;
5389 
5390     memset(&ret, 0, sizeof(ret));
5391     if (call(secret->conn, priv, 0, REMOTE_PROC_SECRET_GET_VALUE,
5392              (xdrproc_t) xdr_remote_secret_get_value_args, (char *) &args,
5393              (xdrproc_t) xdr_remote_secret_get_value_ret, (char *) &ret) == -1)
5394         goto done;
5395 
5396     *value_size = ret.value.value_len;
5397     rv = (unsigned char *) ret.value.value_val; /* Caller frees. */
5398 
5399  done:
5400     remoteDriverUnlock(priv);
5401     return rv;
5402 }
5403 
5404 
5405 static void
remoteDomainBuildEventBlockThreshold(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5406 remoteDomainBuildEventBlockThreshold(virNetClientProgram *prog G_GNUC_UNUSED,
5407                                      virNetClient *client G_GNUC_UNUSED,
5408                                      void *evdata, void *opaque)
5409 {
5410     virConnectPtr conn = opaque;
5411     remote_domain_event_block_threshold_msg *msg = evdata;
5412     struct private_data *priv = conn->privateData;
5413     virDomainPtr dom;
5414     virObjectEvent *event = NULL;
5415 
5416     if (!(dom = get_nonnull_domain(conn, msg->dom)))
5417         return;
5418 
5419     event = virDomainEventBlockThresholdNewFromDom(dom, msg->dev,
5420                                                    msg->path ? *msg->path : NULL,
5421                                                    msg->threshold, msg->excess);
5422 
5423     virObjectUnref(dom);
5424 
5425     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5426 }
5427 
5428 
5429 static void
remoteDomainBuildEventMemoryFailure(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5430 remoteDomainBuildEventMemoryFailure(virNetClientProgram *prog G_GNUC_UNUSED,
5431                                     virNetClient *client G_GNUC_UNUSED,
5432                                     void *evdata, void *opaque)
5433 {
5434     virConnectPtr conn = opaque;
5435     remote_domain_event_memory_failure_msg *msg = evdata;
5436     struct private_data *priv = conn->privateData;
5437     virDomainPtr dom;
5438     virObjectEvent *event = NULL;
5439 
5440     if (!(dom = get_nonnull_domain(conn, msg->dom)))
5441         return;
5442 
5443     event = virDomainEventMemoryFailureNewFromDom(dom, msg->recipient,
5444                                                   msg->action, msg->flags);
5445 
5446     virObjectUnref(dom);
5447 
5448     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5449 }
5450 
5451 
5452 static void
remoteDomainBuildEventMemoryDeviceSizeChange(virNetClientProgram * prog G_GNUC_UNUSED,virNetClient * client G_GNUC_UNUSED,void * evdata,void * opaque)5453 remoteDomainBuildEventMemoryDeviceSizeChange(virNetClientProgram *prog G_GNUC_UNUSED,
5454                                              virNetClient *client G_GNUC_UNUSED,
5455                                              void *evdata, void *opaque)
5456 {
5457     virConnectPtr conn = opaque;
5458     remote_domain_event_memory_device_size_change_msg *msg = evdata;
5459     struct private_data *priv = conn->privateData;
5460     virDomainPtr dom;
5461     virObjectEvent *event = NULL;
5462 
5463     if (!(dom = get_nonnull_domain(conn, msg->dom)))
5464         return;
5465 
5466     event = virDomainEventMemoryDeviceSizeChangeNewFromDom(dom,
5467                                                            msg->alias,
5468                                                            msg->size);
5469 
5470     virObjectUnref(dom);
5471 
5472     virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
5473 }
5474 
5475 
5476 static int
remoteStreamSend(virStreamPtr st,const char * data,size_t nbytes)5477 remoteStreamSend(virStreamPtr st,
5478                  const char *data,
5479                  size_t nbytes)
5480 {
5481     struct private_data *priv = st->conn->privateData;
5482     virNetClientStream *privst = st->privateData;
5483     int rv;
5484 
5485     VIR_DEBUG("st=%p data=%p nbytes=%zu", st, data, nbytes);
5486 
5487     remoteDriverLock(priv);
5488     priv->localUses++;
5489     remoteDriverUnlock(priv);
5490 
5491     rv = virNetClientStreamSendPacket(privst,
5492                                       priv->client,
5493                                       VIR_NET_CONTINUE,
5494                                       data,
5495                                       nbytes);
5496 
5497     remoteDriverLock(priv);
5498     priv->localUses--;
5499     remoteDriverUnlock(priv);
5500     return rv;
5501 }
5502 
5503 
5504 static int
remoteStreamRecvFlags(virStreamPtr st,char * data,size_t nbytes,unsigned int flags)5505 remoteStreamRecvFlags(virStreamPtr st,
5506                       char *data,
5507                       size_t nbytes,
5508                       unsigned int flags)
5509 {
5510     struct private_data *priv = st->conn->privateData;
5511     virNetClientStream *privst = st->privateData;
5512     int rv;
5513 
5514     VIR_DEBUG("st=%p data=%p nbytes=%zu flags=0x%x",
5515               st, data, nbytes, flags);
5516 
5517     virCheckFlags(VIR_STREAM_RECV_STOP_AT_HOLE, -1);
5518 
5519     remoteDriverLock(priv);
5520     priv->localUses++;
5521     remoteDriverUnlock(priv);
5522 
5523     rv = virNetClientStreamRecvPacket(privst,
5524                                       priv->client,
5525                                       data,
5526                                       nbytes,
5527                                       (st->flags & VIR_STREAM_NONBLOCK),
5528                                       flags);
5529 
5530     VIR_DEBUG("Done %d", rv);
5531 
5532     remoteDriverLock(priv);
5533     priv->localUses--;
5534     remoteDriverUnlock(priv);
5535     return rv;
5536 }
5537 
5538 static int
remoteStreamRecv(virStreamPtr st,char * data,size_t nbytes)5539 remoteStreamRecv(virStreamPtr st,
5540                  char *data,
5541                  size_t nbytes)
5542 {
5543     return remoteStreamRecvFlags(st, data, nbytes, 0);
5544 }
5545 
5546 
5547 static int
remoteStreamSendHole(virStreamPtr st,long long length,unsigned int flags)5548 remoteStreamSendHole(virStreamPtr st,
5549                      long long length,
5550                      unsigned int flags)
5551 {
5552     struct private_data *priv = st->conn->privateData;
5553     virNetClientStream *privst = st->privateData;
5554     int rv;
5555 
5556     VIR_DEBUG("st=%p length=%lld flags=0x%x",
5557               st, length, flags);
5558 
5559     remoteDriverLock(priv);
5560     priv->localUses++;
5561     remoteDriverUnlock(priv);
5562 
5563     rv = virNetClientStreamSendHole(privst,
5564                                     priv->client,
5565                                     length,
5566                                     flags);
5567 
5568     remoteDriverLock(priv);
5569     priv->localUses--;
5570     remoteDriverUnlock(priv);
5571     return rv;
5572 }
5573 
5574 
5575 static int
remoteStreamRecvHole(virStreamPtr st,long long * length,unsigned int flags)5576 remoteStreamRecvHole(virStreamPtr st,
5577                      long long *length,
5578                      unsigned int flags)
5579 {
5580     struct private_data *priv = st->conn->privateData;
5581     virNetClientStream *privst = st->privateData;
5582     int rv;
5583 
5584     VIR_DEBUG("st=%p length=%p flags=0x%x",
5585               st, length, flags);
5586 
5587     virCheckFlags(0, -1);
5588 
5589     remoteDriverLock(priv);
5590     priv->localUses++;
5591     remoteDriverUnlock(priv);
5592 
5593     rv = virNetClientStreamRecvHole(priv->client, privst, length);
5594 
5595     remoteDriverLock(priv);
5596     priv->localUses--;
5597     remoteDriverUnlock(priv);
5598     return rv;
5599 }
5600 
5601 
5602 struct remoteStreamCallbackData {
5603     virStreamPtr st;
5604     virStreamEventCallback cb;
5605     void *opaque;
5606     virFreeCallback ff;
5607 };
5608 
remoteStreamEventCallback(virNetClientStream * stream G_GNUC_UNUSED,int events,void * opaque)5609 static void remoteStreamEventCallback(virNetClientStream *stream G_GNUC_UNUSED,
5610                                       int events,
5611                                       void *opaque)
5612 {
5613     struct remoteStreamCallbackData *cbdata = opaque;
5614 
5615     (cbdata->cb)(cbdata->st, events, cbdata->opaque);
5616 }
5617 
5618 
remoteStreamCallbackFree(void * opaque)5619 static void remoteStreamCallbackFree(void *opaque)
5620 {
5621     struct remoteStreamCallbackData *cbdata = opaque;
5622 
5623     if (!cbdata->cb && cbdata->ff)
5624         (cbdata->ff)(cbdata->opaque);
5625 
5626     virObjectUnref(cbdata->st);
5627     g_free(opaque);
5628 }
5629 
5630 
5631 static int
remoteStreamEventAddCallback(virStreamPtr st,int events,virStreamEventCallback cb,void * opaque,virFreeCallback ff)5632 remoteStreamEventAddCallback(virStreamPtr st,
5633                              int events,
5634                              virStreamEventCallback cb,
5635                              void *opaque,
5636                              virFreeCallback ff)
5637 {
5638     struct private_data *priv = st->conn->privateData;
5639     virNetClientStream *privst = st->privateData;
5640     int ret = -1;
5641     struct remoteStreamCallbackData *cbdata;
5642 
5643     cbdata = g_new0(struct remoteStreamCallbackData, 1);
5644     cbdata->cb = cb;
5645     cbdata->opaque = opaque;
5646     cbdata->ff = ff;
5647     cbdata->st = st;
5648     virStreamRef(st);
5649 
5650     remoteDriverLock(priv);
5651 
5652     if ((ret = virNetClientStreamEventAddCallback(privst,
5653                                                   events,
5654                                                   remoteStreamEventCallback,
5655                                                   cbdata,
5656                                                   remoteStreamCallbackFree)) < 0) {
5657         VIR_FREE(cbdata);
5658         goto cleanup;
5659     }
5660 
5661  cleanup:
5662     remoteDriverUnlock(priv);
5663     return ret;
5664 }
5665 
5666 
5667 static int
remoteStreamEventUpdateCallback(virStreamPtr st,int events)5668 remoteStreamEventUpdateCallback(virStreamPtr st,
5669                                 int events)
5670 {
5671     struct private_data *priv = st->conn->privateData;
5672     virNetClientStream *privst = st->privateData;
5673     int ret = -1;
5674 
5675     remoteDriverLock(priv);
5676 
5677     ret = virNetClientStreamEventUpdateCallback(privst, events);
5678 
5679     remoteDriverUnlock(priv);
5680     return ret;
5681 }
5682 
5683 
5684 static int
remoteStreamEventRemoveCallback(virStreamPtr st)5685 remoteStreamEventRemoveCallback(virStreamPtr st)
5686 {
5687     struct private_data *priv = st->conn->privateData;
5688     virNetClientStream *privst = st->privateData;
5689     int ret = -1;
5690 
5691     remoteDriverLock(priv);
5692 
5693     ret = virNetClientStreamEventRemoveCallback(privst);
5694 
5695     remoteDriverUnlock(priv);
5696     return ret;
5697 }
5698 
5699 
5700 static int
remoteStreamCloseInt(virStreamPtr st,bool streamAbort)5701 remoteStreamCloseInt(virStreamPtr st, bool streamAbort)
5702 {
5703     struct private_data *priv = st->conn->privateData;
5704     virNetClientStream *privst = st->privateData;
5705     int ret = -1;
5706 
5707     remoteDriverLock(priv);
5708 
5709     priv->localUses++;
5710     remoteDriverUnlock(priv);
5711 
5712     ret = virNetClientStreamSendPacket(privst,
5713                                        priv->client,
5714                                        streamAbort ? VIR_NET_ERROR : VIR_NET_OK,
5715                                        NULL,
5716                                        0);
5717 
5718     remoteDriverLock(priv);
5719     priv->localUses--;
5720 
5721     virNetClientRemoveStream(priv->client, privst);
5722 
5723     remoteDriverUnlock(priv);
5724     return ret;
5725 }
5726 
5727 
5728 static int
remoteStreamFinish(virStreamPtr st)5729 remoteStreamFinish(virStreamPtr st)
5730 {
5731     return remoteStreamCloseInt(st, false);
5732 }
5733 
5734 
5735 static int
remoteStreamAbort(virStreamPtr st)5736 remoteStreamAbort(virStreamPtr st)
5737 {
5738     return remoteStreamCloseInt(st, true);
5739 }
5740 
5741 
5742 static virStreamDriver remoteStreamDrv = {
5743     .streamRecv = remoteStreamRecv,
5744     .streamRecvFlags = remoteStreamRecvFlags,
5745     .streamSend = remoteStreamSend,
5746     .streamSendHole = remoteStreamSendHole,
5747     .streamRecvHole = remoteStreamRecvHole,
5748     .streamFinish = remoteStreamFinish,
5749     .streamAbort = remoteStreamAbort,
5750     .streamEventAddCallback = remoteStreamEventAddCallback,
5751     .streamEventUpdateCallback = remoteStreamEventUpdateCallback,
5752     .streamEventRemoveCallback = remoteStreamEventRemoveCallback,
5753 };
5754 
5755 
5756 static int
remoteConnectDomainEventRegisterAny(virConnectPtr conn,virDomainPtr dom,int eventID,virConnectDomainEventGenericCallback callback,void * opaque,virFreeCallback freecb)5757 remoteConnectDomainEventRegisterAny(virConnectPtr conn,
5758                                     virDomainPtr dom,
5759                                     int eventID,
5760                                     virConnectDomainEventGenericCallback callback,
5761                                     void *opaque,
5762                                     virFreeCallback freecb)
5763 {
5764     int rv = -1;
5765     struct private_data *priv = conn->privateData;
5766     int callbackID;
5767     int count;
5768     remote_nonnull_domain domain;
5769 
5770     remoteDriverLock(priv);
5771 
5772     if ((count = virDomainEventStateRegisterClient(conn, priv->eventState,
5773                                                    dom, eventID, callback,
5774                                                    opaque, freecb, false,
5775                                                    &callbackID,
5776                                                    priv->serverEventFilter)) < 0)
5777         goto done;
5778 
5779     /* If this is the first callback for this eventID, we need to enable
5780      * events on the server */
5781     if (count == 1) {
5782         if (priv->serverEventFilter) {
5783             remote_connect_domain_event_callback_register_any_args args;
5784             remote_connect_domain_event_callback_register_any_ret ret;
5785 
5786             args.eventID = eventID;
5787             if (dom) {
5788                 make_nonnull_domain(&domain, dom);
5789                 args.dom = &domain;
5790             } else {
5791                 args.dom = NULL;
5792             }
5793 
5794             memset(&ret, 0, sizeof(ret));
5795             if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_REGISTER_ANY,
5796                      (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_args, (char *) &args,
5797                      (xdrproc_t) xdr_remote_connect_domain_event_callback_register_any_ret, (char *) &ret) == -1) {
5798                 virObjectEventStateDeregisterID(conn, priv->eventState,
5799                                                 callbackID, false);
5800                 goto done;
5801             }
5802             virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
5803                                          ret.callbackID);
5804         } else {
5805             remote_connect_domain_event_register_any_args args;
5806 
5807             args.eventID = eventID;
5808 
5809             if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER_ANY,
5810                      (xdrproc_t) xdr_remote_connect_domain_event_register_any_args, (char *) &args,
5811                      (xdrproc_t) xdr_void, (char *)NULL) == -1) {
5812                 virObjectEventStateDeregisterID(conn, priv->eventState,
5813                                                 callbackID, false);
5814                 goto done;
5815             }
5816         }
5817     }
5818 
5819     rv = callbackID;
5820 
5821  done:
5822     remoteDriverUnlock(priv);
5823     return rv;
5824 }
5825 
5826 
5827 static int
remoteConnectDomainEventDeregisterAny(virConnectPtr conn,int callbackID)5828 remoteConnectDomainEventDeregisterAny(virConnectPtr conn,
5829                                       int callbackID)
5830 {
5831     struct private_data *priv = conn->privateData;
5832     int rv = -1;
5833     int eventID;
5834     int remoteID;
5835     int count;
5836 
5837     remoteDriverLock(priv);
5838 
5839     if ((eventID = virObjectEventStateEventID(conn, priv->eventState,
5840                                               callbackID, &remoteID)) < 0)
5841         goto done;
5842 
5843     if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
5844                                                  callbackID, true)) < 0)
5845         goto done;
5846 
5847     /* If that was the last callback for this eventID, we need to disable
5848      * events on the server */
5849     if (count == 0) {
5850         if (priv->serverEventFilter) {
5851             remote_connect_domain_event_callback_deregister_any_args args;
5852 
5853             args.callbackID = remoteID;
5854 
5855             if (call(conn, priv, 0,
5856                      REMOTE_PROC_CONNECT_DOMAIN_EVENT_CALLBACK_DEREGISTER_ANY,
5857                      (xdrproc_t) xdr_remote_connect_domain_event_callback_deregister_any_args, (char *) &args,
5858                      (xdrproc_t) xdr_void, (char *) NULL) == -1)
5859                 goto done;
5860         } else {
5861             remote_connect_domain_event_deregister_any_args args;
5862 
5863             args.eventID = eventID;
5864 
5865             if (call(conn, priv, 0, REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER_ANY,
5866                      (xdrproc_t) xdr_remote_connect_domain_event_deregister_any_args, (char *) &args,
5867                      (xdrproc_t) xdr_void, (char *) NULL) == -1)
5868                 goto done;
5869         }
5870     }
5871 
5872     rv = 0;
5873 
5874  done:
5875     remoteDriverUnlock(priv);
5876     return rv;
5877 }
5878 
5879 
5880 /*----------------------------------------------------------------------*/
5881 
5882 static int
remoteDomainQemuMonitorCommand(virDomainPtr domain,const char * cmd,char ** result,unsigned int flags)5883 remoteDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
5884                                char **result, unsigned int flags)
5885 {
5886     int rv = -1;
5887     qemu_domain_monitor_command_args args;
5888     qemu_domain_monitor_command_ret ret;
5889     struct private_data *priv = domain->conn->privateData;
5890 
5891     remoteDriverLock(priv);
5892 
5893     make_nonnull_domain(&args.dom, domain);
5894     args.cmd = (char *)cmd;
5895     args.flags = flags;
5896 
5897     memset(&ret, 0, sizeof(ret));
5898     if (call(domain->conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_DOMAIN_MONITOR_COMMAND,
5899              (xdrproc_t) xdr_qemu_domain_monitor_command_args, (char *) &args,
5900              (xdrproc_t) xdr_qemu_domain_monitor_command_ret, (char *) &ret) == -1)
5901         goto done;
5902 
5903     *result = g_strdup(ret.result);
5904 
5905     rv = 0;
5906 
5907     xdr_free((xdrproc_t) xdr_qemu_domain_monitor_command_ret, (char *) &ret);
5908 
5909  done:
5910     remoteDriverUnlock(priv);
5911     return rv;
5912 }
5913 
5914 
5915 static char *
remoteDomainMigrateBegin3(virDomainPtr domain,const char * xmlin,char ** cookieout,int * cookieoutlen,unsigned long flags,const char * dname,unsigned long resource)5916 remoteDomainMigrateBegin3(virDomainPtr domain,
5917                           const char *xmlin,
5918                           char **cookieout,
5919                           int *cookieoutlen,
5920                           unsigned long flags,
5921                           const char *dname,
5922                           unsigned long resource)
5923 {
5924     char *rv = NULL;
5925     remote_domain_migrate_begin3_args args;
5926     remote_domain_migrate_begin3_ret ret;
5927     struct private_data *priv = domain->conn->privateData;
5928 
5929     remoteDriverLock(priv);
5930 
5931     memset(&args, 0, sizeof(args));
5932     memset(&ret, 0, sizeof(ret));
5933 
5934     make_nonnull_domain(&args.dom, domain);
5935     args.xmlin = xmlin == NULL ? NULL : (char **) &xmlin;
5936     args.flags = flags;
5937     args.dname = dname == NULL ? NULL : (char **) &dname;
5938     args.resource = resource;
5939 
5940     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3,
5941              (xdrproc_t) xdr_remote_domain_migrate_begin3_args, (char *) &args,
5942              (xdrproc_t) xdr_remote_domain_migrate_begin3_ret, (char *) &ret) == -1)
5943         goto done;
5944 
5945     if (ret.cookie_out.cookie_out_len > 0) {
5946         if (!cookieout || !cookieoutlen) {
5947             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5948                            _("caller ignores cookieout or cookieoutlen"));
5949             goto error;
5950         }
5951         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
5952         *cookieoutlen = ret.cookie_out.cookie_out_len;
5953     }
5954 
5955     rv = ret.xml; /* caller frees */
5956 
5957  done:
5958     remoteDriverUnlock(priv);
5959     return rv;
5960 
5961  error:
5962     VIR_FREE(ret.cookie_out.cookie_out_val);
5963     goto done;
5964 }
5965 
5966 
5967 static int
remoteDomainMigratePrepare3(virConnectPtr dconn,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,const char * uri_in,char ** uri_out,unsigned long flags,const char * dname,unsigned long resource,const char * dom_xml)5968 remoteDomainMigratePrepare3(virConnectPtr dconn,
5969                             const char *cookiein,
5970                             int cookieinlen,
5971                             char **cookieout,
5972                             int *cookieoutlen,
5973                             const char *uri_in,
5974                             char **uri_out,
5975                             unsigned long flags,
5976                             const char *dname,
5977                             unsigned long resource,
5978                             const char *dom_xml)
5979 {
5980     int rv = -1;
5981     remote_domain_migrate_prepare3_args args;
5982     remote_domain_migrate_prepare3_ret ret;
5983     struct private_data *priv = dconn->privateData;
5984 
5985     remoteDriverLock(priv);
5986 
5987     memset(&args, 0, sizeof(args));
5988     memset(&ret, 0, sizeof(ret));
5989 
5990     args.cookie_in.cookie_in_val = (char *)cookiein;
5991     args.cookie_in.cookie_in_len = cookieinlen;
5992     args.uri_in = uri_in == NULL ? NULL : (char **) &uri_in;
5993     args.flags = flags;
5994     args.dname = dname == NULL ? NULL : (char **) &dname;
5995     args.resource = resource;
5996     args.dom_xml = (char *) dom_xml;
5997 
5998     memset(&ret, 0, sizeof(ret));
5999     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3,
6000              (xdrproc_t) xdr_remote_domain_migrate_prepare3_args, (char *) &args,
6001              (xdrproc_t) xdr_remote_domain_migrate_prepare3_ret, (char *) &ret) == -1)
6002         goto done;
6003 
6004     if (ret.cookie_out.cookie_out_len > 0) {
6005         if (!cookieout || !cookieoutlen) {
6006             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6007                            _("caller ignores cookieout or cookieoutlen"));
6008             goto error;
6009         }
6010         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
6011         *cookieoutlen = ret.cookie_out.cookie_out_len;
6012     }
6013     if (ret.uri_out) {
6014         if (!uri_out) {
6015             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6016                            _("caller ignores uri_out"));
6017             goto error;
6018         }
6019         *uri_out = *ret.uri_out; /* Caller frees. */
6020     }
6021 
6022     rv = 0;
6023 
6024  done:
6025     VIR_FREE(ret.uri_out);
6026     remoteDriverUnlock(priv);
6027     return rv;
6028  error:
6029     VIR_FREE(ret.cookie_out.cookie_out_val);
6030     if (ret.uri_out)
6031         VIR_FREE(*ret.uri_out);
6032     goto done;
6033 }
6034 
6035 
6036 static int
remoteDomainMigratePrepareTunnel3(virConnectPtr dconn,virStreamPtr st,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned long flags,const char * dname,unsigned long resource,const char * dom_xml)6037 remoteDomainMigratePrepareTunnel3(virConnectPtr dconn,
6038                                   virStreamPtr st,
6039                                   const char *cookiein,
6040                                   int cookieinlen,
6041                                   char **cookieout,
6042                                   int *cookieoutlen,
6043                                   unsigned long flags,
6044                                   const char *dname,
6045                                   unsigned long resource,
6046                                   const char *dom_xml)
6047 {
6048     struct private_data *priv = dconn->privateData;
6049     int rv = -1;
6050     remote_domain_migrate_prepare_tunnel3_args args;
6051     remote_domain_migrate_prepare_tunnel3_ret ret;
6052     virNetClientStream *netst;
6053 
6054     remoteDriverLock(priv);
6055 
6056     memset(&args, 0, sizeof(args));
6057     memset(&ret, 0, sizeof(ret));
6058 
6059     if (!(netst = virNetClientStreamNew(priv->remoteProgram,
6060                                         REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3,
6061                                         priv->counter,
6062                                         false)))
6063         goto done;
6064 
6065     if (virNetClientAddStream(priv->client, netst) < 0) {
6066         virObjectUnref(netst);
6067         goto done;
6068     }
6069 
6070     st->driver = &remoteStreamDrv;
6071     st->privateData = netst;
6072     st->ff = virObjectFreeCallback;
6073 
6074     args.cookie_in.cookie_in_val = (char *)cookiein;
6075     args.cookie_in.cookie_in_len = cookieinlen;
6076     args.flags = flags;
6077     args.dname = dname == NULL ? NULL : (char **) &dname;
6078     args.resource = resource;
6079     args.dom_xml = (char *) dom_xml;
6080 
6081     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3,
6082              (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_args, (char *) &args,
6083              (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_ret, (char *) &ret) == -1) {
6084         virNetClientRemoveStream(priv->client, netst);
6085         virObjectUnref(netst);
6086         goto done;
6087     }
6088 
6089     if (ret.cookie_out.cookie_out_len > 0) {
6090         if (!cookieout || !cookieoutlen) {
6091             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6092                            _("caller ignores cookieout or cookieoutlen"));
6093             goto error;
6094         }
6095         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
6096         *cookieoutlen = ret.cookie_out.cookie_out_len;
6097     }
6098 
6099     rv = 0;
6100 
6101  done:
6102     remoteDriverUnlock(priv);
6103     return rv;
6104 
6105  error:
6106     VIR_FREE(ret.cookie_out.cookie_out_val);
6107     goto done;
6108 }
6109 
6110 
6111 static int
remoteDomainMigratePerform3(virDomainPtr dom,const char * xmlin,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,const char * dconnuri,const char * uri,unsigned long flags,const char * dname,unsigned long resource)6112 remoteDomainMigratePerform3(virDomainPtr dom,
6113                             const char *xmlin,
6114                             const char *cookiein,
6115                             int cookieinlen,
6116                             char **cookieout,
6117                             int *cookieoutlen,
6118                             const char *dconnuri,
6119                             const char *uri,
6120                             unsigned long flags,
6121                             const char *dname,
6122                             unsigned long resource)
6123 {
6124     int rv = -1;
6125     remote_domain_migrate_perform3_args args;
6126     remote_domain_migrate_perform3_ret ret;
6127     struct private_data *priv = dom->conn->privateData;
6128 
6129     remoteDriverLock(priv);
6130 
6131     memset(&args, 0, sizeof(args));
6132     memset(&ret, 0, sizeof(ret));
6133 
6134     make_nonnull_domain(&args.dom, dom);
6135 
6136     args.xmlin = xmlin == NULL ? NULL : (char **) &xmlin;
6137     args.cookie_in.cookie_in_val = (char *)cookiein;
6138     args.cookie_in.cookie_in_len = cookieinlen;
6139     args.flags = flags;
6140     args.dname = dname == NULL ? NULL : (char **) &dname;
6141     args.uri = uri == NULL ? NULL : (char **) &uri;
6142     args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri;
6143     args.resource = resource;
6144 
6145     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3,
6146              (xdrproc_t) xdr_remote_domain_migrate_perform3_args, (char *) &args,
6147              (xdrproc_t) xdr_remote_domain_migrate_perform3_ret, (char *) &ret) == -1)
6148         goto done;
6149 
6150     if (ret.cookie_out.cookie_out_len > 0) {
6151         if (!cookieout || !cookieoutlen) {
6152             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6153                            _("caller ignores cookieout or cookieoutlen"));
6154             goto error;
6155         }
6156         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
6157         *cookieoutlen = ret.cookie_out.cookie_out_len;
6158     }
6159 
6160     rv = 0;
6161 
6162  done:
6163     remoteDriverUnlock(priv);
6164     return rv;
6165 
6166  error:
6167     VIR_FREE(ret.cookie_out.cookie_out_val);
6168     goto done;
6169 }
6170 
6171 
6172 static virDomainPtr
remoteDomainMigrateFinish3(virConnectPtr dconn,const char * dname,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,const char * dconnuri,const char * uri,unsigned long flags,int cancelled)6173 remoteDomainMigrateFinish3(virConnectPtr dconn,
6174                            const char *dname,
6175                            const char *cookiein,
6176                            int cookieinlen,
6177                            char **cookieout,
6178                            int *cookieoutlen,
6179                            const char *dconnuri,
6180                            const char *uri,
6181                            unsigned long flags,
6182                            int cancelled)
6183 {
6184     remote_domain_migrate_finish3_args args;
6185     remote_domain_migrate_finish3_ret ret;
6186     struct private_data *priv = dconn->privateData;
6187     virDomainPtr rv = NULL;
6188 
6189     remoteDriverLock(priv);
6190 
6191     memset(&args, 0, sizeof(args));
6192     memset(&ret, 0, sizeof(ret));
6193 
6194     args.cookie_in.cookie_in_val = (char *)cookiein;
6195     args.cookie_in.cookie_in_len = cookieinlen;
6196     args.dname = (char *) dname;
6197     args.uri = uri == NULL ? NULL : (char **) &uri;
6198     args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri;
6199     args.flags = flags;
6200     args.cancelled = cancelled;
6201 
6202     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH3,
6203              (xdrproc_t) xdr_remote_domain_migrate_finish3_args, (char *) &args,
6204              (xdrproc_t) xdr_remote_domain_migrate_finish3_ret, (char *) &ret) == -1)
6205         goto done;
6206 
6207     rv = get_nonnull_domain(dconn, ret.dom);
6208 
6209     if (ret.cookie_out.cookie_out_len > 0) {
6210         if (!cookieout || !cookieoutlen) {
6211             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6212                            _("caller ignores cookieout or cookieoutlen"));
6213             goto error;
6214         }
6215         *cookieout = g_steal_pointer(&ret.cookie_out.cookie_out_val); /* Caller frees. */
6216         *cookieoutlen = ret.cookie_out.cookie_out_len;
6217         ret.cookie_out.cookie_out_len = 0;
6218     }
6219 
6220     xdr_free((xdrproc_t) &xdr_remote_domain_migrate_finish3_ret, (char *) &ret);
6221 
6222  done:
6223     remoteDriverUnlock(priv);
6224     return rv;
6225 
6226  error:
6227     VIR_FREE(ret.cookie_out.cookie_out_val);
6228     goto done;
6229 }
6230 
6231 
6232 static int
remoteDomainMigrateConfirm3(virDomainPtr domain,const char * cookiein,int cookieinlen,unsigned long flags,int cancelled)6233 remoteDomainMigrateConfirm3(virDomainPtr domain,
6234                             const char *cookiein,
6235                             int cookieinlen,
6236                             unsigned long flags,
6237                             int cancelled)
6238 {
6239     int rv = -1;
6240     remote_domain_migrate_confirm3_args args;
6241     struct private_data *priv = domain->conn->privateData;
6242 
6243     remoteDriverLock(priv);
6244 
6245     memset(&args, 0, sizeof(args));
6246 
6247     make_nonnull_domain(&args.dom, domain);
6248     args.cookie_in.cookie_in_len = cookieinlen;
6249     args.cookie_in.cookie_in_val = (char *) cookiein;
6250     args.flags = flags;
6251     args.cancelled = cancelled;
6252 
6253     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3,
6254              (xdrproc_t) xdr_remote_domain_migrate_confirm3_args, (char *) &args,
6255              (xdrproc_t) xdr_void, (char *) NULL) == -1)
6256         goto done;
6257 
6258     rv = 0;
6259 
6260  done:
6261     remoteDriverUnlock(priv);
6262     return rv;
6263 }
6264 
6265 
6266 static int
remoteConnectGetCPUModelNames(virConnectPtr conn,const char * arch,char *** models,unsigned int flags)6267 remoteConnectGetCPUModelNames(virConnectPtr conn,
6268                               const char *arch,
6269                               char ***models,
6270                               unsigned int flags)
6271 {
6272     int rv = -1;
6273     size_t i;
6274     g_auto(GStrv) retmodels = NULL;
6275     remote_connect_get_cpu_model_names_args args;
6276     remote_connect_get_cpu_model_names_ret ret;
6277 
6278     struct private_data *priv = conn->privateData;
6279 
6280     remoteDriverLock(priv);
6281 
6282     args.arch = (char *) arch;
6283     args.need_results = !!models;
6284     args.flags = flags;
6285 
6286     memset(&ret, 0, sizeof(ret));
6287     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_CPU_MODEL_NAMES,
6288              (xdrproc_t) xdr_remote_connect_get_cpu_model_names_args,
6289              (char *) &args,
6290              (xdrproc_t) xdr_remote_connect_get_cpu_model_names_ret,
6291              (char *) &ret) < 0)
6292         goto done;
6293 
6294     /* Check the length of the returned list carefully. */
6295     if (ret.models.models_len > REMOTE_CONNECT_CPU_MODELS_MAX) {
6296         virReportError(VIR_ERR_RPC,
6297                        _("Too many model names '%d' for limit '%d'"),
6298                        ret.models.models_len,
6299                        REMOTE_CONNECT_CPU_MODELS_MAX);
6300         goto cleanup;
6301     }
6302 
6303     if (models) {
6304         retmodels = g_new0(char *, ret.models.models_len + 1);
6305 
6306         for (i = 0; i < ret.models.models_len; i++) {
6307             retmodels[i] = g_steal_pointer(&ret.models.models_val[i]);
6308         }
6309         *models = g_steal_pointer(&retmodels);
6310     }
6311 
6312     rv = ret.ret;
6313 
6314  cleanup:
6315     xdr_free((xdrproc_t) xdr_remote_connect_get_cpu_model_names_ret, (char *) &ret);
6316 
6317  done:
6318     remoteDriverUnlock(priv);
6319     return rv;
6320 }
6321 
6322 
6323 static int
remoteDomainOpenGraphics(virDomainPtr dom,unsigned int idx,int fd,unsigned int flags)6324 remoteDomainOpenGraphics(virDomainPtr dom,
6325                          unsigned int idx,
6326                          int fd,
6327                          unsigned int flags)
6328 {
6329     int rv = -1;
6330     remote_domain_open_graphics_args args;
6331     struct private_data *priv = dom->conn->privateData;
6332     int fdin[] = { fd };
6333     size_t fdinlen = G_N_ELEMENTS(fdin);
6334 
6335     remoteDriverLock(priv);
6336 
6337     make_nonnull_domain(&args.dom, dom);
6338     args.idx = idx;
6339     args.flags = flags;
6340 
6341     if (callFull(dom->conn, priv, 0,
6342                  fdin, fdinlen,
6343                  NULL, NULL,
6344                  REMOTE_PROC_DOMAIN_OPEN_GRAPHICS,
6345                  (xdrproc_t) xdr_remote_domain_open_graphics_args, (char *) &args,
6346                  (xdrproc_t) xdr_void, NULL) == -1)
6347         goto done;
6348 
6349     rv = 0;
6350 
6351  done:
6352     remoteDriverUnlock(priv);
6353 
6354     return rv;
6355 }
6356 
6357 
6358 static int
remoteDomainOpenGraphicsFD(virDomainPtr dom,unsigned int idx,unsigned int flags)6359 remoteDomainOpenGraphicsFD(virDomainPtr dom,
6360                            unsigned int idx,
6361                            unsigned int flags)
6362 {
6363     int rv = -1;
6364     remote_domain_open_graphics_fd_args args;
6365     struct private_data *priv = dom->conn->privateData;
6366     int *fdout = NULL;
6367     size_t fdoutlen = 0;
6368 
6369     remoteDriverLock(priv);
6370 
6371     make_nonnull_domain(&args.dom, dom);
6372     args.idx = idx;
6373     args.flags = flags;
6374 
6375     if (callFull(dom->conn, priv, 0,
6376                  NULL, 0,
6377                  &fdout, &fdoutlen,
6378                  REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD,
6379                  (xdrproc_t) xdr_remote_domain_open_graphics_fd_args, (char *) &args,
6380                  (xdrproc_t) xdr_void, NULL) == -1)
6381         goto done;
6382 
6383     if (fdoutlen != 1) {
6384         if (fdoutlen) {
6385             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6386                            _("too many file descriptors received"));
6387             while (fdoutlen)
6388                 VIR_FORCE_CLOSE(fdout[--fdoutlen]);
6389         } else {
6390             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6391                            _("no file descriptor received"));
6392         }
6393         goto done;
6394     }
6395     rv = fdout[0];
6396 
6397  done:
6398     VIR_FREE(fdout);
6399     remoteDriverUnlock(priv);
6400 
6401     return rv;
6402 }
6403 
6404 
6405 static int
remoteConnectSetKeepAlive(virConnectPtr conn,int interval,unsigned int count)6406 remoteConnectSetKeepAlive(virConnectPtr conn, int interval, unsigned int count)
6407 {
6408     struct private_data *priv = conn->privateData;
6409     int ret = -1;
6410 
6411     remoteDriverLock(priv);
6412     if (!virNetClientKeepAliveIsSupported(priv->client)) {
6413         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6414                        _("the caller doesn't support keepalive protocol;"
6415                          " perhaps it's missing event loop implementation"));
6416         goto cleanup;
6417     }
6418 
6419     if (!priv->serverKeepAlive) {
6420         ret = 1;
6421         goto cleanup;
6422     }
6423 
6424     if (interval > 0) {
6425         ret = virNetClientKeepAliveStart(priv->client, interval, count);
6426     } else {
6427         virNetClientKeepAliveStop(priv->client);
6428         ret = 0;
6429     }
6430 
6431  cleanup:
6432     remoteDriverUnlock(priv);
6433     return ret;
6434 }
6435 
6436 
6437 static int
remoteConnectIsAlive(virConnectPtr conn)6438 remoteConnectIsAlive(virConnectPtr conn)
6439 {
6440     struct private_data *priv = conn->privateData;
6441     bool ret;
6442 
6443     remoteDriverLock(priv);
6444     ret = virNetClientIsOpen(priv->client);
6445     remoteDriverUnlock(priv);
6446 
6447     if (ret)
6448         return 1;
6449     else
6450         return 0;
6451 }
6452 
6453 
6454 static int
remoteDomainGetDiskErrors(virDomainPtr dom,virDomainDiskErrorPtr errors,unsigned int maxerrors,unsigned int flags)6455 remoteDomainGetDiskErrors(virDomainPtr dom,
6456                           virDomainDiskErrorPtr errors,
6457                           unsigned int maxerrors,
6458                           unsigned int flags)
6459 {
6460     int rv = -1;
6461     struct private_data *priv = dom->conn->privateData;
6462     remote_domain_get_disk_errors_args args;
6463     remote_domain_get_disk_errors_ret ret;
6464 
6465     remoteDriverLock(priv);
6466 
6467     make_nonnull_domain(&args.dom, dom);
6468     args.maxerrors = maxerrors;
6469     args.flags = flags;
6470 
6471     memset(&ret, 0, sizeof(ret));
6472 
6473     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_DISK_ERRORS,
6474              (xdrproc_t) xdr_remote_domain_get_disk_errors_args,
6475              (char *) &args,
6476              (xdrproc_t) xdr_remote_domain_get_disk_errors_ret,
6477              (char *) &ret) == -1)
6478         goto done;
6479 
6480     if (remoteDeserializeDomainDiskErrors(ret.errors.errors_val,
6481                                           ret.errors.errors_len,
6482                                           REMOTE_DOMAIN_DISK_ERRORS_MAX,
6483                                           errors,
6484                                           maxerrors) < 0)
6485         goto cleanup;
6486 
6487     rv = ret.nerrors;
6488 
6489  cleanup:
6490     xdr_free((xdrproc_t) xdr_remote_domain_get_disk_errors_ret, (char *) &ret);
6491 
6492  done:
6493     remoteDriverUnlock(priv);
6494     return rv;
6495 }
6496 
6497 #include "remote_client_bodies.h"
6498 #include "lxc_client_bodies.h"
6499 #include "qemu_client_bodies.h"
6500 
6501 /*
6502  * Serial a set of arguments into a method call message,
6503  * send that to the server and wait for reply
6504  */
6505 static int
callFull(virConnectPtr conn G_GNUC_UNUSED,struct private_data * priv,unsigned int flags,int * fdin,size_t fdinlen,int ** fdout,size_t * fdoutlen,int proc_nr,xdrproc_t args_filter,char * args,xdrproc_t ret_filter,char * ret)6506 callFull(virConnectPtr conn G_GNUC_UNUSED,
6507          struct private_data *priv,
6508          unsigned int flags,
6509          int *fdin,
6510          size_t fdinlen,
6511          int **fdout,
6512          size_t *fdoutlen,
6513          int proc_nr,
6514          xdrproc_t args_filter, char *args,
6515          xdrproc_t ret_filter, char *ret)
6516 {
6517     int rv;
6518     virNetClientProgram *prog;
6519     int counter = priv->counter++;
6520     virNetClient *client = priv->client;
6521     priv->localUses++;
6522 
6523     if (flags & REMOTE_CALL_QEMU)
6524         prog = priv->qemuProgram;
6525     else if (flags & REMOTE_CALL_LXC)
6526         prog = priv->lxcProgram;
6527     else
6528         prog = priv->remoteProgram;
6529 
6530     /* Unlock, so that if we get any async events/stream data
6531      * while processing the RPC, we don't deadlock when our
6532      * callbacks for those are invoked
6533      */
6534     remoteDriverUnlock(priv);
6535     rv = virNetClientProgramCall(prog,
6536                                  client,
6537                                  counter,
6538                                  proc_nr,
6539                                  fdinlen, fdin,
6540                                  fdoutlen, fdout,
6541                                  args_filter, args,
6542                                  ret_filter, ret);
6543     remoteDriverLock(priv);
6544     priv->localUses--;
6545 
6546     return rv;
6547 }
6548 
6549 static int
call(virConnectPtr conn,struct private_data * priv,unsigned int flags,int proc_nr,xdrproc_t args_filter,char * args,xdrproc_t ret_filter,char * ret)6550 call(virConnectPtr conn,
6551      struct private_data *priv,
6552      unsigned int flags,
6553      int proc_nr,
6554      xdrproc_t args_filter, char *args,
6555      xdrproc_t ret_filter, char *ret)
6556 {
6557     return callFull(conn, priv, flags,
6558                     NULL, 0,
6559                     NULL, NULL,
6560                     proc_nr,
6561                     args_filter, args,
6562                     ret_filter, ret);
6563 }
6564 
6565 
6566 static int
remoteDomainGetInterfaceParameters(virDomainPtr domain,const char * device,virTypedParameterPtr params,int * nparams,unsigned int flags)6567 remoteDomainGetInterfaceParameters(virDomainPtr domain,
6568                                    const char *device,
6569                                    virTypedParameterPtr params, int *nparams,
6570                                    unsigned int flags)
6571 {
6572     int rv = -1;
6573     remote_domain_get_interface_parameters_args args;
6574     remote_domain_get_interface_parameters_ret ret;
6575     struct private_data *priv = domain->conn->privateData;
6576 
6577     remoteDriverLock(priv);
6578 
6579     make_nonnull_domain(&args.dom, domain);
6580     args.device = (char *)device;
6581     args.nparams = *nparams;
6582     args.flags = flags;
6583 
6584     memset(&ret, 0, sizeof(ret));
6585     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS,
6586              (xdrproc_t) xdr_remote_domain_get_interface_parameters_args, (char *) &args,
6587              (xdrproc_t) xdr_remote_domain_get_interface_parameters_ret, (char *) &ret) == -1)
6588         goto done;
6589 
6590     /* Handle the case when the caller does not know the number of parameters
6591      * and is asking for the number of parameters supported
6592      */
6593     if (*nparams == 0) {
6594         *nparams = ret.nparams;
6595         rv = 0;
6596         goto cleanup;
6597     }
6598 
6599     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
6600                                   ret.params.params_len,
6601                                   REMOTE_DOMAIN_INTERFACE_PARAMETERS_MAX,
6602                                   &params,
6603                                   nparams) < 0)
6604         goto cleanup;
6605 
6606     rv = 0;
6607 
6608  cleanup:
6609     xdr_free((xdrproc_t) xdr_remote_domain_get_interface_parameters_ret,
6610              (char *) &ret);
6611  done:
6612     remoteDriverUnlock(priv);
6613     return rv;
6614 }
6615 
6616 
6617 static int
remoteNodeGetMemoryParameters(virConnectPtr conn,virTypedParameterPtr params,int * nparams,unsigned int flags)6618 remoteNodeGetMemoryParameters(virConnectPtr conn,
6619                               virTypedParameterPtr params,
6620                               int *nparams,
6621                               unsigned int flags)
6622 {
6623     int rv = -1;
6624     remote_node_get_memory_parameters_args args;
6625     remote_node_get_memory_parameters_ret ret;
6626     struct private_data *priv = conn->privateData;
6627 
6628     remoteDriverLock(priv);
6629 
6630     args.nparams = *nparams;
6631     args.flags = flags;
6632 
6633     memset(&ret, 0, sizeof(ret));
6634     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_MEMORY_PARAMETERS,
6635              (xdrproc_t) xdr_remote_node_get_memory_parameters_args, (char *) &args,
6636              (xdrproc_t) xdr_remote_node_get_memory_parameters_ret, (char *) &ret) == -1)
6637         goto done;
6638 
6639     /* Handle the case when the caller does not know the number of parameters
6640      * and is asking for the number of parameters supported
6641      */
6642     if (*nparams == 0) {
6643         *nparams = ret.nparams;
6644         rv = 0;
6645         goto cleanup;
6646     }
6647 
6648     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
6649                                   ret.params.params_len,
6650                                   REMOTE_NODE_MEMORY_PARAMETERS_MAX,
6651                                   &params,
6652                                   nparams) < 0)
6653         goto cleanup;
6654 
6655     rv = 0;
6656 
6657  cleanup:
6658     xdr_free((xdrproc_t) xdr_remote_node_get_memory_parameters_ret,
6659              (char *) &ret);
6660  done:
6661     remoteDriverUnlock(priv);
6662     return rv;
6663 }
6664 
6665 
6666 static int
remoteNodeGetSEVInfo(virConnectPtr conn,virTypedParameterPtr * params,int * nparams,unsigned int flags)6667 remoteNodeGetSEVInfo(virConnectPtr conn,
6668                      virTypedParameterPtr *params,
6669                      int *nparams,
6670                      unsigned int flags)
6671 {
6672     int rv = -1;
6673     remote_node_get_sev_info_args args;
6674     remote_node_get_sev_info_ret ret;
6675     struct private_data *priv = conn->privateData;
6676 
6677     remoteDriverLock(priv);
6678 
6679     args.flags = flags;
6680 
6681     memset(&ret, 0, sizeof(ret));
6682     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_SEV_INFO,
6683              (xdrproc_t) xdr_remote_node_get_sev_info_args, (char *) &args,
6684              (xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret) == -1)
6685         goto done;
6686 
6687     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
6688                                   ret.params.params_len,
6689                                   REMOTE_NODE_SEV_INFO_MAX,
6690                                   params,
6691                                   nparams) < 0)
6692         goto cleanup;
6693 
6694     rv = 0;
6695 
6696  cleanup:
6697     xdr_free((xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret);
6698  done:
6699     remoteDriverUnlock(priv);
6700     return rv;
6701 }
6702 
6703 
6704 static int
remoteNodeGetCPUMap(virConnectPtr conn,unsigned char ** cpumap,unsigned int * online,unsigned int flags)6705 remoteNodeGetCPUMap(virConnectPtr conn,
6706                     unsigned char **cpumap,
6707                     unsigned int *online,
6708                     unsigned int flags)
6709 {
6710     int rv = -1;
6711     remote_node_get_cpu_map_args args;
6712     remote_node_get_cpu_map_ret ret;
6713     struct private_data *priv = conn->privateData;
6714 
6715     remoteDriverLock(priv);
6716 
6717     args.need_map = !!cpumap;
6718     args.need_online = !!online;
6719     args.flags = flags;
6720 
6721     memset(&ret, 0, sizeof(ret));
6722     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_CPU_MAP,
6723              (xdrproc_t) xdr_remote_node_get_cpu_map_args,
6724              (char *) &args,
6725              (xdrproc_t) xdr_remote_node_get_cpu_map_ret,
6726              (char *) &ret) == -1)
6727         goto done;
6728 
6729     if (ret.ret < 0)
6730         goto cleanup;
6731 
6732     if (cpumap) {
6733         *cpumap = g_new0(unsigned char, ret.cpumap.cpumap_len);
6734         memcpy(*cpumap, ret.cpumap.cpumap_val, ret.cpumap.cpumap_len);
6735     }
6736 
6737     if (online)
6738         *online = ret.online;
6739 
6740     rv = ret.ret;
6741 
6742  cleanup:
6743     xdr_free((xdrproc_t) xdr_remote_node_get_cpu_map_ret, (char *) &ret);
6744  done:
6745     remoteDriverUnlock(priv);
6746     return rv;
6747 }
6748 
6749 
6750 static int
remoteDomainLxcOpenNamespace(virDomainPtr domain,int ** fdlist,unsigned int flags)6751 remoteDomainLxcOpenNamespace(virDomainPtr domain,
6752                              int **fdlist,
6753                              unsigned int flags)
6754 {
6755     int rv = -1;
6756     lxc_domain_open_namespace_args args;
6757     struct private_data *priv = domain->conn->privateData;
6758     size_t nfds = 0;
6759 
6760     remoteDriverLock(priv);
6761 
6762     make_nonnull_domain(&args.dom, domain);
6763     args.flags = flags;
6764 
6765     *fdlist = NULL;
6766 
6767     if (callFull(domain->conn, priv, REMOTE_CALL_LXC,
6768                  NULL, 0,
6769                  fdlist, &nfds,
6770                  LXC_PROC_DOMAIN_OPEN_NAMESPACE,
6771                  (xdrproc_t) xdr_lxc_domain_open_namespace_args, (char *) &args,
6772                  (xdrproc_t) xdr_void, NULL) == -1)
6773         goto done;
6774 
6775     rv = nfds;
6776 
6777  done:
6778     remoteDriverUnlock(priv);
6779     return rv;
6780 }
6781 
6782 static int
remoteDomainGetJobStats(virDomainPtr domain,int * type,virTypedParameterPtr * params,int * nparams,unsigned int flags)6783 remoteDomainGetJobStats(virDomainPtr domain,
6784                         int *type,
6785                         virTypedParameterPtr *params,
6786                         int *nparams,
6787                         unsigned int flags)
6788 {
6789     int rv = -1;
6790     remote_domain_get_job_stats_args args;
6791     remote_domain_get_job_stats_ret ret;
6792     struct private_data *priv = domain->conn->privateData;
6793 
6794     remoteDriverLock(priv);
6795 
6796     make_nonnull_domain(&args.dom, domain);
6797     args.flags = flags;
6798 
6799     memset(&ret, 0, sizeof(ret));
6800     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_JOB_STATS,
6801              (xdrproc_t) xdr_remote_domain_get_job_stats_args, (char *) &args,
6802              (xdrproc_t) xdr_remote_domain_get_job_stats_ret, (char *) &ret) == -1)
6803         goto done;
6804 
6805     *type = ret.type;
6806 
6807     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
6808                                   ret.params.params_len,
6809                                   REMOTE_DOMAIN_JOB_STATS_MAX,
6810                                   params, nparams) < 0)
6811         goto cleanup;
6812 
6813     rv = 0;
6814 
6815  cleanup:
6816     xdr_free((xdrproc_t) xdr_remote_domain_get_job_stats_ret,
6817              (char *) &ret);
6818  done:
6819     remoteDriverUnlock(priv);
6820     return rv;
6821 }
6822 
6823 
6824 static char *
remoteDomainMigrateBegin3Params(virDomainPtr domain,virTypedParameterPtr params,int nparams,char ** cookieout,int * cookieoutlen,unsigned int flags)6825 remoteDomainMigrateBegin3Params(virDomainPtr domain,
6826                                 virTypedParameterPtr params,
6827                                 int nparams,
6828                                 char **cookieout,
6829                                 int *cookieoutlen,
6830                                 unsigned int flags)
6831 {
6832     char *rv = NULL;
6833     remote_domain_migrate_begin3_params_args args;
6834     remote_domain_migrate_begin3_params_ret ret;
6835     struct private_data *priv = domain->conn->privateData;
6836 
6837     remoteDriverLock(priv);
6838 
6839     memset(&args, 0, sizeof(args));
6840     memset(&ret, 0, sizeof(ret));
6841 
6842     make_nonnull_domain(&args.dom, domain);
6843     args.flags = flags;
6844 
6845     if (virTypedParamsSerialize(params, nparams,
6846                                 REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX,
6847                                 (struct _virTypedParameterRemote **) &args.params.params_val,
6848                                 &args.params.params_len,
6849                                 VIR_TYPED_PARAM_STRING_OKAY) < 0) {
6850         xdr_free((xdrproc_t) xdr_remote_domain_migrate_begin3_params_args,
6851                  (char *) &args);
6852         goto cleanup;
6853     }
6854 
6855     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3_PARAMS,
6856              (xdrproc_t) xdr_remote_domain_migrate_begin3_params_args,
6857              (char *) &args,
6858              (xdrproc_t) xdr_remote_domain_migrate_begin3_params_ret,
6859              (char *) &ret) == -1)
6860         goto cleanup;
6861 
6862     if (ret.cookie_out.cookie_out_len > 0) {
6863         if (!cookieout || !cookieoutlen) {
6864             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6865                            _("caller ignores cookieout or cookieoutlen"));
6866             goto error;
6867         }
6868         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
6869         *cookieoutlen = ret.cookie_out.cookie_out_len;
6870     }
6871 
6872     rv = ret.xml; /* caller frees */
6873 
6874  cleanup:
6875     virTypedParamsRemoteFree((struct _virTypedParameterRemote *) args.params.params_val,
6876                              args.params.params_len);
6877     remoteDriverUnlock(priv);
6878     return rv;
6879 
6880  error:
6881     VIR_FREE(ret.cookie_out.cookie_out_val);
6882     goto cleanup;
6883 }
6884 
6885 
6886 static int
remoteDomainMigratePrepare3Params(virConnectPtr dconn,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,char ** uri_out,unsigned int flags)6887 remoteDomainMigratePrepare3Params(virConnectPtr dconn,
6888                                   virTypedParameterPtr params,
6889                                   int nparams,
6890                                   const char *cookiein,
6891                                   int cookieinlen,
6892                                   char **cookieout,
6893                                   int *cookieoutlen,
6894                                   char **uri_out,
6895                                   unsigned int flags)
6896 {
6897     int rv = -1;
6898     remote_domain_migrate_prepare3_params_args args;
6899     remote_domain_migrate_prepare3_params_ret ret;
6900     struct private_data *priv = dconn->privateData;
6901 
6902     remoteDriverLock(priv);
6903 
6904     memset(&args, 0, sizeof(args));
6905     memset(&ret, 0, sizeof(ret));
6906 
6907     if (virTypedParamsSerialize(params, nparams,
6908                                 REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX,
6909                                 (struct _virTypedParameterRemote **) &args.params.params_val,
6910                                 &args.params.params_len,
6911                                 VIR_TYPED_PARAM_STRING_OKAY) < 0) {
6912         xdr_free((xdrproc_t) xdr_remote_domain_migrate_prepare3_params_args,
6913                  (char *) &args);
6914         goto cleanup;
6915     }
6916 
6917     args.cookie_in.cookie_in_val = (char *)cookiein;
6918     args.cookie_in.cookie_in_len = cookieinlen;
6919     args.flags = flags;
6920 
6921     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3_PARAMS,
6922              (xdrproc_t) xdr_remote_domain_migrate_prepare3_params_args,
6923              (char *) &args,
6924              (xdrproc_t) xdr_remote_domain_migrate_prepare3_params_ret,
6925              (char *) &ret) == -1)
6926         goto cleanup;
6927 
6928     if (ret.cookie_out.cookie_out_len > 0) {
6929         if (!cookieout || !cookieoutlen) {
6930             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6931                            _("caller ignores cookieout or cookieoutlen"));
6932             goto error;
6933         }
6934         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
6935         *cookieoutlen = ret.cookie_out.cookie_out_len;
6936     }
6937     if (ret.uri_out) {
6938         if (!uri_out) {
6939             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6940                            _("caller ignores uri_out"));
6941             goto error;
6942         }
6943         *uri_out = *ret.uri_out; /* Caller frees. */
6944     }
6945 
6946     rv = 0;
6947 
6948  cleanup:
6949     virTypedParamsRemoteFree((struct _virTypedParameterRemote *) args.params.params_val,
6950                              args.params.params_len);
6951     VIR_FREE(ret.uri_out);
6952     remoteDriverUnlock(priv);
6953     return rv;
6954 
6955  error:
6956     VIR_FREE(ret.cookie_out.cookie_out_val);
6957     if (ret.uri_out)
6958         VIR_FREE(*ret.uri_out);
6959     goto cleanup;
6960 }
6961 
6962 
6963 static int
remoteDomainMigratePrepareTunnel3Params(virConnectPtr dconn,virStreamPtr st,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned int flags)6964 remoteDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
6965                                         virStreamPtr st,
6966                                         virTypedParameterPtr params,
6967                                         int nparams,
6968                                         const char *cookiein,
6969                                         int cookieinlen,
6970                                         char **cookieout,
6971                                         int *cookieoutlen,
6972                                         unsigned int flags)
6973 {
6974     struct private_data *priv = dconn->privateData;
6975     int rv = -1;
6976     remote_domain_migrate_prepare_tunnel3_params_args args;
6977     remote_domain_migrate_prepare_tunnel3_params_ret ret;
6978     virNetClientStream *netst;
6979 
6980     remoteDriverLock(priv);
6981 
6982     memset(&args, 0, sizeof(args));
6983     memset(&ret, 0, sizeof(ret));
6984 
6985     args.cookie_in.cookie_in_val = (char *)cookiein;
6986     args.cookie_in.cookie_in_len = cookieinlen;
6987     args.flags = flags;
6988 
6989     if (virTypedParamsSerialize(params, nparams,
6990                                 REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX,
6991                                 (struct _virTypedParameterRemote **) &args.params.params_val,
6992                                 &args.params.params_len,
6993                                 VIR_TYPED_PARAM_STRING_OKAY) < 0) {
6994         xdr_free((xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_params_args,
6995                  (char *) &args);
6996         goto cleanup;
6997     }
6998 
6999     if (!(netst = virNetClientStreamNew(priv->remoteProgram,
7000                                         REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3_PARAMS,
7001                                         priv->counter,
7002                                         false)))
7003         goto cleanup;
7004 
7005     if (virNetClientAddStream(priv->client, netst) < 0) {
7006         virObjectUnref(netst);
7007         goto cleanup;
7008     }
7009 
7010     st->driver = &remoteStreamDrv;
7011     st->privateData = netst;
7012     st->ff = virObjectFreeCallback;
7013 
7014     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3_PARAMS,
7015              (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_params_args,
7016              (char *) &args,
7017              (xdrproc_t) xdr_remote_domain_migrate_prepare_tunnel3_params_ret,
7018              (char *) &ret) == -1) {
7019         virNetClientRemoveStream(priv->client, netst);
7020         virObjectUnref(netst);
7021         goto cleanup;
7022     }
7023 
7024     if (ret.cookie_out.cookie_out_len > 0) {
7025         if (!cookieout || !cookieoutlen) {
7026             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7027                            _("caller ignores cookieout or cookieoutlen"));
7028             goto error;
7029         }
7030         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
7031         *cookieoutlen = ret.cookie_out.cookie_out_len;
7032     }
7033 
7034     rv = 0;
7035 
7036  cleanup:
7037     virTypedParamsRemoteFree((struct _virTypedParameterRemote *) args.params.params_val,
7038                              args.params.params_len);
7039     remoteDriverUnlock(priv);
7040     return rv;
7041 
7042  error:
7043     VIR_FREE(ret.cookie_out.cookie_out_val);
7044     goto cleanup;
7045 }
7046 
7047 
7048 static int
remoteDomainMigratePerform3Params(virDomainPtr dom,const char * dconnuri,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned int flags)7049 remoteDomainMigratePerform3Params(virDomainPtr dom,
7050                                   const char *dconnuri,
7051                                   virTypedParameterPtr params,
7052                                   int nparams,
7053                                   const char *cookiein,
7054                                   int cookieinlen,
7055                                   char **cookieout,
7056                                   int *cookieoutlen,
7057                                   unsigned int flags)
7058 {
7059     int rv = -1;
7060     remote_domain_migrate_perform3_params_args args;
7061     remote_domain_migrate_perform3_params_ret ret;
7062     struct private_data *priv = dom->conn->privateData;
7063 
7064     remoteDriverLock(priv);
7065 
7066     memset(&args, 0, sizeof(args));
7067     memset(&ret, 0, sizeof(ret));
7068 
7069     make_nonnull_domain(&args.dom, dom);
7070     args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri;
7071     args.cookie_in.cookie_in_val = (char *)cookiein;
7072     args.cookie_in.cookie_in_len = cookieinlen;
7073     args.flags = flags;
7074 
7075     if (virTypedParamsSerialize(params, nparams,
7076                                 REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX,
7077                                 (struct _virTypedParameterRemote **) &args.params.params_val,
7078                                 &args.params.params_len,
7079                                 VIR_TYPED_PARAM_STRING_OKAY) < 0) {
7080         xdr_free((xdrproc_t) xdr_remote_domain_migrate_perform3_params_args,
7081                  (char *) &args);
7082         goto cleanup;
7083     }
7084 
7085     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3_PARAMS,
7086              (xdrproc_t) xdr_remote_domain_migrate_perform3_params_args,
7087              (char *) &args,
7088              (xdrproc_t) xdr_remote_domain_migrate_perform3_params_ret,
7089              (char *) &ret) == -1)
7090         goto cleanup;
7091 
7092     if (ret.cookie_out.cookie_out_len > 0) {
7093         if (!cookieout || !cookieoutlen) {
7094             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7095                            _("caller ignores cookieout or cookieoutlen"));
7096             goto error;
7097         }
7098         *cookieout = ret.cookie_out.cookie_out_val; /* Caller frees. */
7099         *cookieoutlen = ret.cookie_out.cookie_out_len;
7100     }
7101 
7102     rv = 0;
7103 
7104  cleanup:
7105     virTypedParamsRemoteFree((struct _virTypedParameterRemote *) args.params.params_val,
7106                              args.params.params_len);
7107     remoteDriverUnlock(priv);
7108     return rv;
7109 
7110  error:
7111     VIR_FREE(ret.cookie_out.cookie_out_val);
7112     goto cleanup;
7113 }
7114 
7115 
7116 static virDomainPtr
remoteDomainMigrateFinish3Params(virConnectPtr dconn,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,char ** cookieout,int * cookieoutlen,unsigned int flags,int cancelled)7117 remoteDomainMigrateFinish3Params(virConnectPtr dconn,
7118                                  virTypedParameterPtr params,
7119                                  int nparams,
7120                                  const char *cookiein,
7121                                  int cookieinlen,
7122                                  char **cookieout,
7123                                  int *cookieoutlen,
7124                                  unsigned int flags,
7125                                  int cancelled)
7126 {
7127     remote_domain_migrate_finish3_params_args args;
7128     remote_domain_migrate_finish3_params_ret ret;
7129     struct private_data *priv = dconn->privateData;
7130     virDomainPtr rv = NULL;
7131 
7132     remoteDriverLock(priv);
7133 
7134     memset(&args, 0, sizeof(args));
7135     memset(&ret, 0, sizeof(ret));
7136 
7137     args.cookie_in.cookie_in_val = (char *)cookiein;
7138     args.cookie_in.cookie_in_len = cookieinlen;
7139     args.flags = flags;
7140     args.cancelled = cancelled;
7141 
7142     if (virTypedParamsSerialize(params, nparams,
7143                                 REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX,
7144                                 (struct _virTypedParameterRemote **) &args.params.params_val,
7145                                 &args.params.params_len,
7146                                 VIR_TYPED_PARAM_STRING_OKAY) < 0) {
7147         xdr_free((xdrproc_t) xdr_remote_domain_migrate_finish3_params_args,
7148                  (char *) &args);
7149         goto cleanup;
7150     }
7151 
7152     if (call(dconn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_FINISH3_PARAMS,
7153              (xdrproc_t) xdr_remote_domain_migrate_finish3_params_args,
7154              (char *) &args,
7155              (xdrproc_t) xdr_remote_domain_migrate_finish3_params_ret,
7156              (char *) &ret) == -1)
7157         goto cleanup;
7158 
7159     rv = get_nonnull_domain(dconn, ret.dom);
7160 
7161     if (ret.cookie_out.cookie_out_len > 0) {
7162         if (!cookieout || !cookieoutlen) {
7163             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7164                            _("caller ignores cookieout or cookieoutlen"));
7165             goto error;
7166         }
7167         *cookieout = g_steal_pointer(&ret.cookie_out.cookie_out_val); /* Caller frees. */
7168         *cookieoutlen = ret.cookie_out.cookie_out_len;
7169         ret.cookie_out.cookie_out_len = 0;
7170     }
7171 
7172     xdr_free((xdrproc_t) &xdr_remote_domain_migrate_finish3_params_ret,
7173              (char *) &ret);
7174 
7175  cleanup:
7176     virTypedParamsRemoteFree((struct _virTypedParameterRemote *) args.params.params_val,
7177                              args.params.params_len);
7178     remoteDriverUnlock(priv);
7179     return rv;
7180 
7181  error:
7182     VIR_FREE(ret.cookie_out.cookie_out_val);
7183     goto cleanup;
7184 }
7185 
7186 
7187 static int
remoteDomainMigrateConfirm3Params(virDomainPtr domain,virTypedParameterPtr params,int nparams,const char * cookiein,int cookieinlen,unsigned int flags,int cancelled)7188 remoteDomainMigrateConfirm3Params(virDomainPtr domain,
7189                                   virTypedParameterPtr params,
7190                                   int nparams,
7191                                   const char *cookiein,
7192                                   int cookieinlen,
7193                                   unsigned int flags,
7194                                   int cancelled)
7195 {
7196     int rv = -1;
7197     remote_domain_migrate_confirm3_params_args args;
7198     struct private_data *priv = domain->conn->privateData;
7199 
7200     remoteDriverLock(priv);
7201 
7202     memset(&args, 0, sizeof(args));
7203 
7204     make_nonnull_domain(&args.dom, domain);
7205     args.cookie_in.cookie_in_len = cookieinlen;
7206     args.cookie_in.cookie_in_val = (char *) cookiein;
7207     args.flags = flags;
7208     args.cancelled = cancelled;
7209 
7210     if (virTypedParamsSerialize(params, nparams,
7211                                 REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX,
7212                                 (struct _virTypedParameterRemote **) &args.params.params_val,
7213                                 &args.params.params_len,
7214                                 VIR_TYPED_PARAM_STRING_OKAY) < 0) {
7215         xdr_free((xdrproc_t) xdr_remote_domain_migrate_confirm3_params_args,
7216                  (char *) &args);
7217         goto cleanup;
7218     }
7219 
7220     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3_PARAMS,
7221              (xdrproc_t) xdr_remote_domain_migrate_confirm3_params_args,
7222              (char *) &args, (xdrproc_t) xdr_void, (char *) NULL) == -1)
7223         goto cleanup;
7224 
7225     rv = 0;
7226 
7227  cleanup:
7228     virTypedParamsRemoteFree((struct _virTypedParameterRemote *) args.params.params_val,
7229                              args.params.params_len);
7230     remoteDriverUnlock(priv);
7231     return rv;
7232 }
7233 
7234 
7235 static virDomainPtr
remoteDomainCreateXMLWithFiles(virConnectPtr conn,const char * xml_desc,unsigned int nfiles,int * files,unsigned int flags)7236 remoteDomainCreateXMLWithFiles(virConnectPtr conn, const char *xml_desc,
7237                                unsigned int nfiles, int *files, unsigned int flags)
7238 {
7239     virDomainPtr rv = NULL;
7240     struct private_data *priv = conn->privateData;
7241     remote_domain_create_xml_with_files_args args;
7242     remote_domain_create_xml_with_files_ret ret;
7243 
7244     remoteDriverLock(priv);
7245 
7246     args.xml_desc = (char *)xml_desc;
7247     args.flags = flags;
7248 
7249     memset(&ret, 0, sizeof(ret));
7250 
7251     if (callFull(conn, priv, 0,
7252                  files, nfiles,
7253                  NULL, NULL,
7254                  REMOTE_PROC_DOMAIN_CREATE_XML_WITH_FILES,
7255                  (xdrproc_t)xdr_remote_domain_create_xml_with_files_args, (char *)&args,
7256                  (xdrproc_t)xdr_remote_domain_create_xml_with_files_ret, (char *)&ret) == -1) {
7257         goto done;
7258     }
7259 
7260     rv = get_nonnull_domain(conn, ret.dom);
7261     xdr_free((xdrproc_t)xdr_remote_domain_create_xml_with_files_ret, (char *)&ret);
7262 
7263  done:
7264     remoteDriverUnlock(priv);
7265     return rv;
7266 }
7267 
7268 
7269 static int
remoteDomainCreateWithFiles(virDomainPtr dom,unsigned int nfiles,int * files,unsigned int flags)7270 remoteDomainCreateWithFiles(virDomainPtr dom,
7271                             unsigned int nfiles, int *files,
7272                             unsigned int flags)
7273 {
7274     int rv = -1;
7275     struct private_data *priv = dom->conn->privateData;
7276     remote_domain_create_with_files_args args;
7277     remote_domain_create_with_files_ret ret;
7278 
7279     remoteDriverLock(priv);
7280 
7281     make_nonnull_domain(&args.dom, dom);
7282     args.flags = flags;
7283 
7284     memset(&ret, 0, sizeof(ret));
7285 
7286     if (callFull(dom->conn, priv, 0,
7287                  files, nfiles,
7288                  NULL, NULL,
7289                  REMOTE_PROC_DOMAIN_CREATE_WITH_FILES,
7290                  (xdrproc_t)xdr_remote_domain_create_with_files_args, (char *)&args,
7291                  (xdrproc_t)xdr_remote_domain_create_with_files_ret, (char *)&ret) == -1) {
7292         goto done;
7293     }
7294 
7295     dom->id = ret.dom.id;
7296     xdr_free((xdrproc_t) &xdr_remote_domain_create_with_files_ret, (char *) &ret);
7297     rv = 0;
7298 
7299  done:
7300     remoteDriverUnlock(priv);
7301     return rv;
7302 }
7303 
7304 static int
remoteDomainGetTime(virDomainPtr dom,long long * seconds,unsigned int * nseconds,unsigned int flags)7305 remoteDomainGetTime(virDomainPtr dom,
7306                     long long *seconds,
7307                     unsigned int *nseconds,
7308                     unsigned int flags)
7309 {
7310     int rv = -1;
7311     struct private_data *priv = dom->conn->privateData;
7312     remote_domain_get_time_args args;
7313     remote_domain_get_time_ret ret;
7314 
7315     remoteDriverLock(priv);
7316 
7317     make_nonnull_domain(&args.dom, dom);
7318     args.flags = flags;
7319 
7320     *seconds = *nseconds = 0;
7321 
7322     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_TIME,
7323              (xdrproc_t) xdr_remote_domain_get_time_args, (char *) &args,
7324              (xdrproc_t) xdr_remote_domain_get_time_ret, (char *) &ret) == -1)
7325         goto cleanup;
7326 
7327     *seconds = ret.seconds;
7328     *nseconds = ret.nseconds;
7329     xdr_free((xdrproc_t) &xdr_remote_domain_get_time_ret, (char *) &ret);
7330     rv = 0;
7331 
7332  cleanup:
7333     remoteDriverUnlock(priv);
7334     return rv;
7335 }
7336 
7337 
7338 static int
remoteNodeGetFreePages(virConnectPtr conn,unsigned int npages,unsigned int * pages,int startCell,unsigned int cellCount,unsigned long long * counts,unsigned int flags)7339 remoteNodeGetFreePages(virConnectPtr conn,
7340                        unsigned int npages,
7341                        unsigned int *pages,
7342                        int startCell,
7343                        unsigned int cellCount,
7344                        unsigned long long *counts,
7345                        unsigned int flags)
7346 {
7347     int rv = -1;
7348     remote_node_get_free_pages_args args;
7349     remote_node_get_free_pages_ret ret;
7350     struct private_data *priv = conn->privateData;
7351 
7352     remoteDriverLock(priv);
7353 
7354     if (npages * cellCount > REMOTE_NODE_MAX_CELLS) {
7355         virReportError(VIR_ERR_RPC,
7356                        _("too many NUMA cells: %d > %d"),
7357                        npages * cellCount, REMOTE_NODE_MAX_CELLS);
7358         goto done;
7359     }
7360 
7361     args.pages.pages_val = (u_int *) pages;
7362     args.pages.pages_len = npages;
7363     args.startCell = startCell;
7364     args.cellCount = cellCount;
7365     args.flags = flags;
7366 
7367     memset(&ret, 0, sizeof(ret));
7368     if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_FREE_PAGES,
7369              (xdrproc_t) xdr_remote_node_get_free_pages_args, (char *)&args,
7370              (xdrproc_t) xdr_remote_node_get_free_pages_ret, (char *)&ret) == -1)
7371         goto done;
7372 
7373     memcpy(counts, ret.counts.counts_val, ret.counts.counts_len * sizeof(*counts));
7374 
7375     xdr_free((xdrproc_t) xdr_remote_node_get_free_pages_ret, (char *) &ret);
7376 
7377     rv = ret.counts.counts_len;
7378 
7379  done:
7380     remoteDriverUnlock(priv);
7381     return rv;
7382 }
7383 
7384 
7385 /* Copy contents of remote_network_dhcp_lease to virNetworkDHCPLeasePtr */
7386 static int
remoteSerializeDHCPLease(virNetworkDHCPLeasePtr lease_dst,remote_network_dhcp_lease * lease_src)7387 remoteSerializeDHCPLease(virNetworkDHCPLeasePtr lease_dst, remote_network_dhcp_lease *lease_src)
7388 {
7389     lease_dst->expirytime = lease_src->expirytime;
7390     lease_dst->type = lease_src->type;
7391     lease_dst->prefix = lease_src->prefix;
7392 
7393     lease_dst->iface = g_strdup(lease_src->iface);
7394 
7395     lease_dst->ipaddr = g_strdup(lease_src->ipaddr);
7396 
7397     if (lease_src->mac) {
7398         lease_dst->mac = g_strdup(*lease_src->mac);
7399     } else {
7400         lease_src->mac = NULL;
7401     }
7402 
7403     if (lease_src->iaid) {
7404         lease_dst->iaid = g_strdup(*lease_src->iaid);
7405     } else {
7406         lease_src->iaid = NULL;
7407     }
7408 
7409     if (lease_src->hostname) {
7410         lease_dst->hostname = g_strdup(*lease_src->hostname);
7411     } else {
7412         lease_src->hostname = NULL;
7413     }
7414 
7415     if (lease_src->clientid) {
7416         lease_dst->clientid = g_strdup(*lease_src->clientid);
7417     } else {
7418         lease_src->clientid = NULL;
7419     }
7420 
7421     return 0;
7422 }
7423 
7424 
7425 static int
remoteNetworkGetDHCPLeases(virNetworkPtr net,const char * mac,virNetworkDHCPLeasePtr ** leases,unsigned int flags)7426 remoteNetworkGetDHCPLeases(virNetworkPtr net,
7427                            const char *mac,
7428                            virNetworkDHCPLeasePtr **leases,
7429                            unsigned int flags)
7430 {
7431     int rv = -1;
7432     size_t i;
7433     struct private_data *priv = net->conn->privateData;
7434     remote_network_get_dhcp_leases_args args;
7435     remote_network_get_dhcp_leases_ret ret;
7436 
7437     virNetworkDHCPLeasePtr *leases_ret = NULL;
7438     remoteDriverLock(priv);
7439 
7440     make_nonnull_network(&args.net, net);
7441     args.mac = mac ? (char **) &mac : NULL;
7442     args.flags = flags;
7443     args.need_results = !!leases;
7444 
7445     memset(&ret, 0, sizeof(ret));
7446 
7447     if (call(net->conn, priv, 0, REMOTE_PROC_NETWORK_GET_DHCP_LEASES,
7448              (xdrproc_t)xdr_remote_network_get_dhcp_leases_args, (char *)&args,
7449              (xdrproc_t)xdr_remote_network_get_dhcp_leases_ret, (char *)&ret) == -1)
7450         goto done;
7451 
7452     if (ret.leases.leases_len > REMOTE_NETWORK_DHCP_LEASES_MAX) {
7453         virReportError(VIR_ERR_INTERNAL_ERROR,
7454                        _("Number of leases is %d, which exceeds max limit: %d"),
7455                        ret.leases.leases_len, REMOTE_NETWORK_DHCP_LEASES_MAX);
7456         goto cleanup;
7457     }
7458 
7459     if (leases) {
7460         if (ret.leases.leases_len)
7461             leases_ret = g_new0(virNetworkDHCPLeasePtr, ret.leases.leases_len + 1);
7462 
7463         for (i = 0; i < ret.leases.leases_len; i++) {
7464             leases_ret[i] = g_new0(virNetworkDHCPLease, 1);
7465 
7466             if (remoteSerializeDHCPLease(leases_ret[i], &ret.leases.leases_val[i]) < 0)
7467                 goto cleanup;
7468         }
7469 
7470         *leases = g_steal_pointer(&leases_ret);
7471     }
7472 
7473     rv = ret.ret;
7474 
7475  cleanup:
7476     if (leases_ret) {
7477         for (i = 0; i < ret.leases.leases_len; i++)
7478             virNetworkDHCPLeaseFree(leases_ret[i]);
7479         VIR_FREE(leases_ret);
7480     }
7481     xdr_free((xdrproc_t)xdr_remote_network_get_dhcp_leases_ret,
7482              (char *) &ret);
7483 
7484  done:
7485     remoteDriverUnlock(priv);
7486     return rv;
7487 }
7488 
7489 
7490 static int
remoteConnectGetAllDomainStats(virConnectPtr conn,virDomainPtr * doms,unsigned int ndoms,unsigned int stats,virDomainStatsRecordPtr ** retStats,unsigned int flags)7491 remoteConnectGetAllDomainStats(virConnectPtr conn,
7492                                virDomainPtr *doms,
7493                                unsigned int ndoms,
7494                                unsigned int stats,
7495                                virDomainStatsRecordPtr **retStats,
7496                                unsigned int flags)
7497 {
7498     struct private_data *priv = conn->privateData;
7499     int rv = -1;
7500     size_t i;
7501     remote_connect_get_all_domain_stats_args args;
7502     remote_connect_get_all_domain_stats_ret ret;
7503     virDomainStatsRecordPtr elem = NULL;
7504     virDomainStatsRecordPtr *tmpret = NULL;
7505 
7506     memset(&args, 0, sizeof(args));
7507 
7508     if (ndoms) {
7509         args.doms.doms_val = g_new0(remote_nonnull_domain, ndoms);
7510 
7511         for (i = 0; i < ndoms; i++)
7512             make_nonnull_domain(args.doms.doms_val + i, doms[i]);
7513     }
7514     args.doms.doms_len = ndoms;
7515 
7516     args.stats = stats;
7517     args.flags = flags;
7518 
7519     memset(&ret, 0, sizeof(ret));
7520 
7521     remoteDriverLock(priv);
7522     if (call(conn, priv, 0, REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS,
7523              (xdrproc_t)xdr_remote_connect_get_all_domain_stats_args, (char *)&args,
7524              (xdrproc_t)xdr_remote_connect_get_all_domain_stats_ret, (char *)&ret) == -1) {
7525         remoteDriverUnlock(priv);
7526         goto cleanup;
7527     }
7528     remoteDriverUnlock(priv);
7529 
7530     if (ret.retStats.retStats_len > REMOTE_DOMAIN_LIST_MAX) {
7531         virReportError(VIR_ERR_INTERNAL_ERROR,
7532                        _("Number of stats entries is %d, which exceeds max limit: %d"),
7533                        ret.retStats.retStats_len, REMOTE_DOMAIN_LIST_MAX);
7534         goto cleanup;
7535     }
7536 
7537     *retStats = NULL;
7538 
7539     tmpret = g_new0(virDomainStatsRecordPtr, ret.retStats.retStats_len + 1);
7540 
7541     for (i = 0; i < ret.retStats.retStats_len; i++) {
7542         remote_domain_stats_record *rec = ret.retStats.retStats_val + i;
7543 
7544         elem = g_new0(virDomainStatsRecord, 1);
7545 
7546         if (!(elem->dom = get_nonnull_domain(conn, rec->dom)))
7547             goto cleanup;
7548 
7549         if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) rec->params.params_val,
7550                                       rec->params.params_len,
7551                                       REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX,
7552                                       &elem->params,
7553                                       &elem->nparams))
7554             goto cleanup;
7555 
7556         tmpret[i] = g_steal_pointer(&elem);
7557     }
7558 
7559     *retStats = g_steal_pointer(&tmpret);
7560     rv = ret.retStats.retStats_len;
7561 
7562  cleanup:
7563     if (elem) {
7564         virObjectUnref(elem->dom);
7565         VIR_FREE(elem);
7566     }
7567     virDomainStatsRecordListFree(tmpret);
7568     VIR_FREE(args.doms.doms_val);
7569     xdr_free((xdrproc_t)xdr_remote_connect_get_all_domain_stats_ret,
7570              (char *) &ret);
7571 
7572     return rv;
7573 }
7574 
7575 
7576 static int
remoteNodeAllocPages(virConnectPtr conn,unsigned int npages,unsigned int * pageSizes,unsigned long long * pageCounts,int startCell,unsigned int cellCount,unsigned int flags)7577 remoteNodeAllocPages(virConnectPtr conn,
7578                      unsigned int npages,
7579                      unsigned int *pageSizes,
7580                      unsigned long long *pageCounts,
7581                      int startCell,
7582                      unsigned int cellCount,
7583                      unsigned int flags)
7584 {
7585     int rv = -1;
7586     remote_node_alloc_pages_args args;
7587     remote_node_alloc_pages_ret ret;
7588     struct private_data *priv = conn->privateData;
7589 
7590     remoteDriverLock(priv);
7591 
7592     if (npages > REMOTE_NODE_MAX_CELLS) {
7593         virReportError(VIR_ERR_RPC,
7594                        _("too many NUMA cells: %d > %d"),
7595                        npages, REMOTE_NODE_MAX_CELLS);
7596         goto done;
7597     }
7598 
7599     args.pageSizes.pageSizes_val = (u_int *) pageSizes;
7600     args.pageSizes.pageSizes_len = npages;
7601     args.pageCounts.pageCounts_val = (uint64_t *) pageCounts;
7602     args.pageCounts.pageCounts_len = npages;
7603     args.startCell = startCell;
7604     args.cellCount = cellCount;
7605     args.flags = flags;
7606 
7607     memset(&ret, 0, sizeof(ret));
7608     if (call(conn, priv, 0, REMOTE_PROC_NODE_ALLOC_PAGES,
7609              (xdrproc_t) xdr_remote_node_alloc_pages_args, (char *) &args,
7610              (xdrproc_t) xdr_remote_node_alloc_pages_ret, (char *) &ret) == -1)
7611         goto done;
7612 
7613     rv = ret.ret;
7614 
7615  done:
7616     remoteDriverUnlock(priv);
7617     return rv;
7618 }
7619 
7620 
7621 static int
remoteDomainGetFSInfo(virDomainPtr dom,virDomainFSInfoPtr ** info,unsigned int flags)7622 remoteDomainGetFSInfo(virDomainPtr dom,
7623                       virDomainFSInfoPtr **info,
7624                       unsigned int flags)
7625 {
7626     int rv = -1;
7627     size_t i, j, len;
7628     struct private_data *priv = dom->conn->privateData;
7629     remote_domain_get_fsinfo_args args;
7630     remote_domain_get_fsinfo_ret ret;
7631     remote_domain_fsinfo *src;
7632 
7633     remoteDriverLock(priv);
7634 
7635     make_nonnull_domain(&args.dom, dom);
7636 
7637     args.flags = flags;
7638 
7639     memset(&ret, 0, sizeof(ret));
7640 
7641     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_FSINFO,
7642              (xdrproc_t)xdr_remote_domain_get_fsinfo_args, (char *)&args,
7643              (xdrproc_t)xdr_remote_domain_get_fsinfo_ret, (char *)&ret) == -1)
7644         goto done;
7645 
7646     if (ret.info.info_len > REMOTE_DOMAIN_FSINFO_MAX) {
7647         virReportError(VIR_ERR_INTERNAL_ERROR,
7648                        _("Too many mountpoints in fsinfo: %d for limit %d"),
7649                        ret.info.info_len, REMOTE_DOMAIN_FSINFO_MAX);
7650         goto cleanup;
7651     }
7652 
7653     if (info) {
7654         virDomainFSInfoPtr *info_ret = NULL;
7655 
7656         if (!ret.info.info_len) {
7657             *info = NULL;
7658             rv = ret.ret;
7659             goto cleanup;
7660         }
7661 
7662         info_ret = g_new0(virDomainFSInfoPtr, ret.info.info_len);
7663 
7664         for (i = 0; i < ret.info.info_len; i++) {
7665             src = &ret.info.info_val[i];
7666 
7667             info_ret[i] = g_new0(virDomainFSInfo, 1);
7668 
7669             info_ret[i]->mountpoint = g_strdup(src->mountpoint);
7670 
7671             info_ret[i]->name = g_strdup(src->name);
7672 
7673             info_ret[i]->fstype = g_strdup(src->fstype);
7674 
7675             len = src->dev_aliases.dev_aliases_len;
7676             info_ret[i]->ndevAlias = len;
7677             if (len)
7678                 info_ret[i]->devAlias = g_new0(char *, len);
7679 
7680             for (j = 0; j < len; j++)
7681                 info_ret[i]->devAlias[j] = g_strdup(src->dev_aliases.dev_aliases_val[j]);
7682         }
7683 
7684         *info = info_ret;
7685     }
7686 
7687     rv = ret.ret;
7688 
7689  cleanup:
7690     xdr_free((xdrproc_t)xdr_remote_domain_get_fsinfo_ret,
7691              (char *) &ret);
7692 
7693  done:
7694     remoteDriverUnlock(priv);
7695     return rv;
7696 }
7697 
7698 
7699 static int
remoteDomainInterfaceAddresses(virDomainPtr dom,virDomainInterfacePtr ** ifaces,unsigned int source,unsigned int flags)7700 remoteDomainInterfaceAddresses(virDomainPtr dom,
7701                                virDomainInterfacePtr **ifaces,
7702                                unsigned int source,
7703                                unsigned int flags)
7704 {
7705     int rv = -1;
7706     size_t i, j;
7707 
7708     virDomainInterfacePtr *ifaces_ret = NULL;
7709     remote_domain_interface_addresses_args args;
7710     remote_domain_interface_addresses_ret ret;
7711 
7712     struct private_data *priv = dom->conn->privateData;
7713 
7714     args.source = source;
7715     args.flags = flags;
7716     make_nonnull_domain(&args.dom, dom);
7717 
7718     remoteDriverLock(priv);
7719 
7720     memset(&ret, 0, sizeof(ret));
7721 
7722     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_INTERFACE_ADDRESSES,
7723              (xdrproc_t)xdr_remote_domain_interface_addresses_args,
7724              (char *)&args,
7725              (xdrproc_t)xdr_remote_domain_interface_addresses_ret,
7726              (char *)&ret) == -1) {
7727         goto done;
7728     }
7729 
7730     if (ret.ifaces.ifaces_len > REMOTE_DOMAIN_INTERFACE_MAX) {
7731         virReportError(VIR_ERR_INTERNAL_ERROR,
7732                        _("Number of interfaces, %d exceeds the max limit: %d"),
7733                        ret.ifaces.ifaces_len, REMOTE_DOMAIN_INTERFACE_MAX);
7734         goto cleanup;
7735     }
7736 
7737     if (ret.ifaces.ifaces_len)
7738         ifaces_ret = g_new0(virDomainInterfacePtr, ret.ifaces.ifaces_len);
7739 
7740     for (i = 0; i < ret.ifaces.ifaces_len; i++) {
7741         virDomainInterfacePtr iface;
7742         remote_domain_interface *iface_ret = &(ret.ifaces.ifaces_val[i]);
7743 
7744         ifaces_ret[i] = g_new0(virDomainInterface, 1);
7745 
7746         iface = ifaces_ret[i];
7747 
7748         iface->name = g_strdup(iface_ret->name);
7749 
7750         if (iface_ret->hwaddr)
7751             iface->hwaddr = g_strdup(*iface_ret->hwaddr);
7752 
7753         if (iface_ret->addrs.addrs_len > REMOTE_DOMAIN_IP_ADDR_MAX) {
7754             virReportError(VIR_ERR_INTERNAL_ERROR,
7755                            _("Number of interfaces, %d exceeds the max limit: %d"),
7756                            iface_ret->addrs.addrs_len, REMOTE_DOMAIN_IP_ADDR_MAX);
7757             goto cleanup;
7758         }
7759 
7760         iface->naddrs = iface_ret->addrs.addrs_len;
7761 
7762         if (iface->naddrs) {
7763             iface->addrs = g_new0(virDomainIPAddress, iface->naddrs);
7764 
7765            for (j = 0; j < iface->naddrs; j++) {
7766                 virDomainIPAddressPtr ip_addr = &(iface->addrs[j]);
7767                 remote_domain_ip_addr *ip_addr_ret =
7768                     &(iface_ret->addrs.addrs_val[j]);
7769 
7770                 ip_addr->addr = g_strdup(ip_addr_ret->addr);
7771 
7772                 ip_addr->prefix = ip_addr_ret->prefix;
7773                 ip_addr->type = ip_addr_ret->type;
7774             }
7775         }
7776     }
7777     *ifaces = g_steal_pointer(&ifaces_ret);
7778 
7779     rv = ret.ifaces.ifaces_len;
7780 
7781  cleanup:
7782     if (ifaces_ret) {
7783         for (i = 0; i < ret.ifaces.ifaces_len; i++)
7784             virDomainInterfaceFree(ifaces_ret[i]);
7785         VIR_FREE(ifaces_ret);
7786     }
7787     xdr_free((xdrproc_t)xdr_remote_domain_interface_addresses_ret,
7788              (char *) &ret);
7789  done:
7790     remoteDriverUnlock(priv);
7791     return rv;
7792 }
7793 
7794 static int
remoteConnectRegisterCloseCallback(virConnectPtr conn,virConnectCloseFunc cb,void * opaque,virFreeCallback freecb)7795 remoteConnectRegisterCloseCallback(virConnectPtr conn,
7796                                    virConnectCloseFunc cb,
7797                                    void *opaque,
7798                                    virFreeCallback freecb)
7799 {
7800     struct private_data *priv = conn->privateData;
7801     int ret = -1;
7802 
7803     remoteDriverLock(priv);
7804 
7805     if (virConnectCloseCallbackDataGetCallback(priv->closeCallback) != NULL) {
7806         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7807                        _("A close callback is already registered"));
7808         goto cleanup;
7809     }
7810 
7811     if (priv->serverCloseCallback &&
7812         call(conn, priv, 0, REMOTE_PROC_CONNECT_REGISTER_CLOSE_CALLBACK,
7813              (xdrproc_t) xdr_void, (char *) NULL,
7814              (xdrproc_t) xdr_void, (char *) NULL) == -1)
7815         goto cleanup;
7816 
7817     virConnectCloseCallbackDataRegister(priv->closeCallback, conn, cb,
7818                                         opaque, freecb);
7819     ret = 0;
7820 
7821  cleanup:
7822     remoteDriverUnlock(priv);
7823 
7824     return ret;
7825 }
7826 
7827 static int
remoteConnectUnregisterCloseCallback(virConnectPtr conn,virConnectCloseFunc cb)7828 remoteConnectUnregisterCloseCallback(virConnectPtr conn,
7829                                      virConnectCloseFunc cb)
7830 {
7831     struct private_data *priv = conn->privateData;
7832     int ret = -1;
7833 
7834     remoteDriverLock(priv);
7835 
7836     if (virConnectCloseCallbackDataGetCallback(priv->closeCallback) != cb) {
7837         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
7838                        _("A different callback was requested"));
7839         goto cleanup;
7840     }
7841 
7842     if (priv->serverCloseCallback &&
7843         call(conn, priv, 0, REMOTE_PROC_CONNECT_UNREGISTER_CLOSE_CALLBACK,
7844              (xdrproc_t) xdr_void, (char *) NULL,
7845              (xdrproc_t) xdr_void, (char *) NULL) == -1)
7846         goto cleanup;
7847 
7848     virConnectCloseCallbackDataUnregister(priv->closeCallback, cb);
7849     ret = 0;
7850 
7851  cleanup:
7852     remoteDriverUnlock(priv);
7853 
7854     return ret;
7855 }
7856 
7857 static int
remoteDomainRename(virDomainPtr dom,const char * new_name,unsigned int flags)7858 remoteDomainRename(virDomainPtr dom, const char *new_name, unsigned int flags)
7859 {
7860     int rv = -1;
7861     struct private_data *priv = dom->conn->privateData;
7862     remote_domain_rename_args args;
7863     remote_domain_rename_ret ret;
7864     char *tmp = NULL;
7865 
7866     tmp = g_strdup(new_name);
7867 
7868     remoteDriverLock(priv);
7869 
7870     make_nonnull_domain(&args.dom, dom);
7871     args.new_name = new_name ? (char **)&new_name : NULL;
7872     args.flags = flags;
7873 
7874     memset(&ret, 0, sizeof(ret));
7875 
7876     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_RENAME,
7877              (xdrproc_t)xdr_remote_domain_rename_args, (char *)&args,
7878              (xdrproc_t)xdr_remote_domain_rename_ret, (char *)&ret) == -1) {
7879         goto done;
7880     }
7881 
7882     rv = ret.retcode;
7883 
7884     if (rv == 0) {
7885         VIR_FREE(dom->name);
7886         dom->name = g_steal_pointer(&tmp);
7887     }
7888 
7889  done:
7890     remoteDriverUnlock(priv);
7891     VIR_FREE(tmp);
7892     return rv;
7893 }
7894 
7895 
7896 static int
remoteStorageVolGetInfoFlags(virStorageVolPtr vol,virStorageVolInfoPtr result,unsigned int flags)7897 remoteStorageVolGetInfoFlags(virStorageVolPtr vol,
7898                              virStorageVolInfoPtr result,
7899                              unsigned int flags)
7900 {
7901     int rv = -1;
7902     struct private_data *priv = vol->conn->privateData;
7903     remote_storage_vol_get_info_flags_args args;
7904     remote_storage_vol_get_info_flags_ret ret;
7905 
7906     remoteDriverLock(priv);
7907 
7908     make_nonnull_storage_vol(&args.vol, vol);
7909     args.flags = flags;
7910 
7911     memset(&ret, 0, sizeof(ret));
7912 
7913     if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_INFO_FLAGS,
7914              (xdrproc_t)xdr_remote_storage_vol_get_info_flags_args,
7915              (char *)&args,
7916              (xdrproc_t)xdr_remote_storage_vol_get_info_flags_ret,
7917              (char *)&ret) == -1) {
7918         goto done;
7919     }
7920 
7921     result->type = ret.type;
7922     result->capacity = ret.capacity;
7923     result->allocation = ret.allocation;
7924     rv = 0;
7925 
7926  done:
7927     remoteDriverUnlock(priv);
7928     return rv;
7929 }
7930 
7931 
7932 static int
remoteNetworkPortGetParameters(virNetworkPortPtr port,virTypedParameterPtr * params,int * nparams,unsigned int flags)7933 remoteNetworkPortGetParameters(virNetworkPortPtr port,
7934                                virTypedParameterPtr *params,
7935                                int *nparams,
7936                                unsigned int flags)
7937 {
7938     int rv = -1;
7939     struct private_data *priv = port->net->conn->privateData;
7940     remote_network_port_get_parameters_args args;
7941     remote_network_port_get_parameters_ret ret;
7942 
7943     remoteDriverLock(priv);
7944 
7945     make_nonnull_network_port(&args.port, port);
7946     args.flags = flags;
7947 
7948     memset(&ret, 0, sizeof(ret));
7949     if (call(port->net->conn, priv, 0, REMOTE_PROC_NETWORK_PORT_GET_PARAMETERS,
7950              (xdrproc_t) xdr_remote_network_port_get_parameters_args, (char *) &args,
7951              (xdrproc_t) xdr_remote_network_port_get_parameters_ret, (char *) &ret) == -1)
7952         goto done;
7953 
7954     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
7955                                   ret.params.params_len,
7956                                   REMOTE_NETWORK_PORT_PARAMETERS_MAX,
7957                                   params,
7958                                   nparams) < 0)
7959         goto cleanup;
7960 
7961     rv = 0;
7962 
7963  cleanup:
7964     xdr_free((xdrproc_t) xdr_remote_network_port_get_parameters_ret, (char *) &ret);
7965  done:
7966     remoteDriverUnlock(priv);
7967     return rv;
7968 }
7969 
7970 static int
remoteDomainGetGuestInfo(virDomainPtr dom,unsigned int types,virTypedParameterPtr * params,int * nparams,unsigned int flags)7971 remoteDomainGetGuestInfo(virDomainPtr dom,
7972                          unsigned int types,
7973                          virTypedParameterPtr *params,
7974                          int *nparams,
7975                          unsigned int flags)
7976 {
7977     int rv = -1;
7978     struct private_data *priv = dom->conn->privateData;
7979     remote_domain_get_guest_info_args args;
7980     remote_domain_get_guest_info_ret ret;
7981 
7982     remoteDriverLock(priv);
7983 
7984     make_nonnull_domain(&args.dom, dom);
7985 
7986     args.types = types;
7987     args.flags = flags;
7988 
7989     memset(&ret, 0, sizeof(ret));
7990 
7991     if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_GUEST_INFO,
7992              (xdrproc_t)xdr_remote_domain_get_guest_info_args, (char *)&args,
7993              (xdrproc_t)xdr_remote_domain_get_guest_info_ret, (char *)&ret) == -1)
7994         goto done;
7995 
7996     if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.params.params_val,
7997                                   ret.params.params_len,
7998                                   REMOTE_DOMAIN_GUEST_INFO_PARAMS_MAX,
7999                                   params,
8000                                   nparams) < 0)
8001         goto cleanup;
8002 
8003     rv = 0;
8004 
8005  cleanup:
8006     xdr_free((xdrproc_t)xdr_remote_domain_get_guest_info_ret,
8007              (char *) &ret);
8008 
8009  done:
8010     remoteDriverUnlock(priv);
8011     return rv;
8012 }
8013 
8014 static int
remoteDomainAuthorizedSSHKeysGet(virDomainPtr domain,const char * user,char *** keys,unsigned int flags)8015 remoteDomainAuthorizedSSHKeysGet(virDomainPtr domain,
8016                                  const char *user,
8017                                  char ***keys,
8018                                  unsigned int flags)
8019 {
8020     int rv = -1;
8021     size_t i;
8022     struct private_data *priv = domain->conn->privateData;
8023     remote_domain_authorized_ssh_keys_get_args args;
8024     remote_domain_authorized_ssh_keys_get_ret ret;
8025 
8026     remoteDriverLock(priv);
8027 
8028     make_nonnull_domain(&args.dom, domain);
8029     args.user = (char *) user;
8030     args.flags = flags;
8031     memset(&ret, 0, sizeof(ret));
8032 
8033     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_GET,
8034              (xdrproc_t) xdr_remote_domain_authorized_ssh_keys_get_args, (char *)&args,
8035              (xdrproc_t) xdr_remote_domain_authorized_ssh_keys_get_ret, (char *)&ret) == -1) {
8036         goto cleanup;
8037     }
8038 
8039     if (ret.keys.keys_len > REMOTE_DOMAIN_AUTHORIZED_SSH_KEYS_MAX) {
8040         virReportError(VIR_ERR_RPC, "%s",
8041                        _("remoteDomainAuthorizedSSHKeysGet: "
8042                          "returned number of keys exceeds limit"));
8043         goto cleanup;
8044     }
8045 
8046     *keys = g_new0(char *, ret.keys.keys_len + 1);
8047     for (i = 0; i < ret.keys.keys_len; i++)
8048         (*keys)[i] = g_strdup(ret.keys.keys_val[i]);
8049 
8050     rv = ret.keys.keys_len;
8051 
8052  cleanup:
8053     remoteDriverUnlock(priv);
8054     xdr_free((xdrproc_t)xdr_remote_domain_authorized_ssh_keys_get_ret,
8055              (char *) &ret);
8056     return rv;
8057 }
8058 
8059 static int
remoteDomainAuthorizedSSHKeysSet(virDomainPtr domain,const char * user,const char ** keys,unsigned int nkeys,unsigned int flags)8060 remoteDomainAuthorizedSSHKeysSet(virDomainPtr domain,
8061                                  const char *user,
8062                                  const char **keys,
8063                                  unsigned int nkeys,
8064                                  unsigned int flags)
8065 {
8066     int rv = -1;
8067     struct private_data *priv = domain->conn->privateData;
8068     remote_domain_authorized_ssh_keys_set_args args;
8069 
8070     remoteDriverLock(priv);
8071 
8072     if (nkeys > REMOTE_DOMAIN_AUTHORIZED_SSH_KEYS_MAX) {
8073         virReportError(VIR_ERR_RPC, "%s",
8074                        _("remoteDomainAuthorizedSSHKeysSet: "
8075                          "returned number of keys exceeds limit"));
8076         goto cleanup;
8077     }
8078 
8079     make_nonnull_domain(&args.dom, domain);
8080     args.user = (char *) user;
8081     args.keys.keys_len = nkeys;
8082     args.keys.keys_val = (char **) keys;
8083     args.flags = flags;
8084 
8085     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_AUTHORIZED_SSH_KEYS_SET,
8086              (xdrproc_t) xdr_remote_domain_authorized_ssh_keys_set_args, (char *)&args,
8087              (xdrproc_t) xdr_void, (char *) NULL) == -1) {
8088         goto cleanup;
8089     }
8090 
8091     rv = 0;
8092 
8093  cleanup:
8094     remoteDriverUnlock(priv);
8095     return rv;
8096 }
8097 
8098 
8099 static int
remoteDomainGetMessages(virDomainPtr domain,char *** msgs,unsigned int flags)8100 remoteDomainGetMessages(virDomainPtr domain,
8101                         char ***msgs,
8102                         unsigned int flags)
8103 {
8104     int rv = -1;
8105     size_t i;
8106     struct private_data *priv = domain->conn->privateData;
8107     remote_domain_get_messages_args args;
8108     remote_domain_get_messages_ret ret;
8109 
8110     remoteDriverLock(priv);
8111 
8112     make_nonnull_domain(&args.dom, domain);
8113     args.flags = flags;
8114     memset(&ret, 0, sizeof(ret));
8115 
8116     if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_MESSAGES,
8117              (xdrproc_t) xdr_remote_domain_get_messages_args, (char *)&args,
8118              (xdrproc_t) xdr_remote_domain_get_messages_ret, (char *)&ret) == -1) {
8119         goto cleanup;
8120     }
8121 
8122     if (ret.msgs.msgs_len > REMOTE_DOMAIN_MESSAGES_MAX) {
8123         virReportError(VIR_ERR_RPC, "%s",
8124                        _("remoteDomainGetMessages: "
8125                          "returned number of msgs exceeds limit"));
8126         goto cleanup;
8127     }
8128 
8129     *msgs = g_new0(char *, ret.msgs.msgs_len + 1);
8130     for (i = 0; i < ret.msgs.msgs_len; i++)
8131         (*msgs)[i] = g_strdup(ret.msgs.msgs_val[i]);
8132 
8133     rv = ret.msgs.msgs_len;
8134 
8135  cleanup:
8136     remoteDriverUnlock(priv);
8137     xdr_free((xdrproc_t)xdr_remote_domain_get_messages_ret,
8138              (char *) &ret);
8139     return rv;
8140 }
8141 
8142 /* get_nonnull_domain and get_nonnull_network turn an on-wire
8143  * (name, uuid) pair into virDomainPtr or virNetworkPtr object.
8144  * These can return NULL if underlying memory allocations fail,
8145  * but if they do then virterror_internal.has been set.
8146  */
8147 static virDomainPtr
get_nonnull_domain(virConnectPtr conn,remote_nonnull_domain domain)8148 get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain)
8149 {
8150     return virGetDomain(conn, domain.name, BAD_CAST domain.uuid, domain.id);
8151 }
8152 
8153 static virNetworkPtr
get_nonnull_network(virConnectPtr conn,remote_nonnull_network network)8154 get_nonnull_network(virConnectPtr conn, remote_nonnull_network network)
8155 {
8156     return virGetNetwork(conn, network.name, BAD_CAST network.uuid);
8157 }
8158 
8159 static virNetworkPortPtr
get_nonnull_network_port(virConnectPtr conn,remote_nonnull_network_port port)8160 get_nonnull_network_port(virConnectPtr conn, remote_nonnull_network_port port)
8161 {
8162     virNetworkPortPtr ret;
8163     virNetworkPtr net;
8164     net = virGetNetwork(conn, port.net.name, BAD_CAST port.net.uuid);
8165     if (!net)
8166         return NULL;
8167     ret = virGetNetworkPort(net, BAD_CAST port.uuid);
8168     virObjectUnref(net);
8169     return ret;
8170 }
8171 
8172 static virInterfacePtr
get_nonnull_interface(virConnectPtr conn,remote_nonnull_interface iface)8173 get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface)
8174 {
8175     return virGetInterface(conn, iface.name, iface.mac);
8176 }
8177 
8178 static virStoragePoolPtr
get_nonnull_storage_pool(virConnectPtr conn,remote_nonnull_storage_pool pool)8179 get_nonnull_storage_pool(virConnectPtr conn, remote_nonnull_storage_pool pool)
8180 {
8181     return virGetStoragePool(conn, pool.name, BAD_CAST pool.uuid,
8182                              NULL, NULL);
8183 }
8184 
8185 static virStorageVolPtr
get_nonnull_storage_vol(virConnectPtr conn,remote_nonnull_storage_vol vol)8186 get_nonnull_storage_vol(virConnectPtr conn, remote_nonnull_storage_vol vol)
8187 {
8188     return virGetStorageVol(conn, vol.pool, vol.name, vol.key,
8189                             NULL, NULL);
8190 }
8191 
8192 static virNodeDevicePtr
get_nonnull_node_device(virConnectPtr conn,remote_nonnull_node_device dev)8193 get_nonnull_node_device(virConnectPtr conn, remote_nonnull_node_device dev)
8194 {
8195     return virGetNodeDevice(conn, dev.name);
8196 }
8197 
8198 static virSecretPtr
get_nonnull_secret(virConnectPtr conn,remote_nonnull_secret secret)8199 get_nonnull_secret(virConnectPtr conn, remote_nonnull_secret secret)
8200 {
8201     return virGetSecret(conn, BAD_CAST secret.uuid, secret.usageType, secret.usageID);
8202 }
8203 
8204 static virNWFilterPtr
get_nonnull_nwfilter(virConnectPtr conn,remote_nonnull_nwfilter nwfilter)8205 get_nonnull_nwfilter(virConnectPtr conn, remote_nonnull_nwfilter nwfilter)
8206 {
8207     return virGetNWFilter(conn, nwfilter.name, BAD_CAST nwfilter.uuid);
8208 }
8209 
8210 static virNWFilterBindingPtr
get_nonnull_nwfilter_binding(virConnectPtr conn,remote_nonnull_nwfilter_binding binding)8211 get_nonnull_nwfilter_binding(virConnectPtr conn, remote_nonnull_nwfilter_binding binding)
8212 {
8213     return virGetNWFilterBinding(conn, binding.portdev, binding.filtername);
8214 }
8215 
8216 static virDomainCheckpointPtr
get_nonnull_domain_checkpoint(virDomainPtr domain,remote_nonnull_domain_checkpoint checkpoint)8217 get_nonnull_domain_checkpoint(virDomainPtr domain, remote_nonnull_domain_checkpoint checkpoint)
8218 {
8219     return virGetDomainCheckpoint(domain, checkpoint.name);
8220 }
8221 
8222 static virDomainSnapshotPtr
get_nonnull_domain_snapshot(virDomainPtr domain,remote_nonnull_domain_snapshot snapshot)8223 get_nonnull_domain_snapshot(virDomainPtr domain, remote_nonnull_domain_snapshot snapshot)
8224 {
8225     return virGetDomainSnapshot(domain, snapshot.name);
8226 }
8227 
8228 
8229 /* Make remote_nonnull_domain and remote_nonnull_network. */
8230 static void
make_nonnull_domain(remote_nonnull_domain * dom_dst,virDomainPtr dom_src)8231 make_nonnull_domain(remote_nonnull_domain *dom_dst, virDomainPtr dom_src)
8232 {
8233     dom_dst->id = dom_src->id;
8234     dom_dst->name = dom_src->name;
8235     memcpy(dom_dst->uuid, dom_src->uuid, VIR_UUID_BUFLEN);
8236 }
8237 
8238 static void
make_nonnull_network(remote_nonnull_network * net_dst,virNetworkPtr net_src)8239 make_nonnull_network(remote_nonnull_network *net_dst, virNetworkPtr net_src)
8240 {
8241     net_dst->name = net_src->name;
8242     memcpy(net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN);
8243 }
8244 
8245 static void
make_nonnull_network_port(remote_nonnull_network_port * port_dst,virNetworkPortPtr port_src)8246 make_nonnull_network_port(remote_nonnull_network_port *port_dst, virNetworkPortPtr port_src)
8247 {
8248     port_dst->net.name = port_src->net->name;
8249     memcpy(port_dst->net.uuid, port_src->net->uuid, VIR_UUID_BUFLEN);
8250     memcpy(port_dst->uuid, port_src->uuid, VIR_UUID_BUFLEN);
8251 }
8252 
8253 static void
make_nonnull_interface(remote_nonnull_interface * interface_dst,virInterfacePtr interface_src)8254 make_nonnull_interface(remote_nonnull_interface *interface_dst,
8255                         virInterfacePtr interface_src)
8256 {
8257     interface_dst->name = interface_src->name;
8258     interface_dst->mac = interface_src->mac;
8259 }
8260 
8261 static void
make_nonnull_storage_pool(remote_nonnull_storage_pool * pool_dst,virStoragePoolPtr pool_src)8262 make_nonnull_storage_pool(remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src)
8263 {
8264     pool_dst->name = pool_src->name;
8265     memcpy(pool_dst->uuid, pool_src->uuid, VIR_UUID_BUFLEN);
8266 }
8267 
8268 static void
make_nonnull_storage_vol(remote_nonnull_storage_vol * vol_dst,virStorageVolPtr vol_src)8269 make_nonnull_storage_vol(remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src)
8270 {
8271     vol_dst->pool = vol_src->pool;
8272     vol_dst->name = vol_src->name;
8273     vol_dst->key = vol_src->key;
8274 }
8275 
8276 static void
make_nonnull_secret(remote_nonnull_secret * secret_dst,virSecretPtr secret_src)8277 make_nonnull_secret(remote_nonnull_secret *secret_dst, virSecretPtr secret_src)
8278 {
8279     memcpy(secret_dst->uuid, secret_src->uuid, VIR_UUID_BUFLEN);
8280     secret_dst->usageType = secret_src->usageType;
8281     secret_dst->usageID = secret_src->usageID;
8282 }
8283 
8284 static void
make_nonnull_node_device(remote_nonnull_node_device * dev_dst,virNodeDevicePtr dev_src)8285 make_nonnull_node_device(remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src)
8286 {
8287     dev_dst->name = dev_src->name;
8288 }
8289 
8290 static void
make_nonnull_nwfilter(remote_nonnull_nwfilter * nwfilter_dst,virNWFilterPtr nwfilter_src)8291 make_nonnull_nwfilter(remote_nonnull_nwfilter *nwfilter_dst, virNWFilterPtr nwfilter_src)
8292 {
8293     nwfilter_dst->name = nwfilter_src->name;
8294     memcpy(nwfilter_dst->uuid, nwfilter_src->uuid, VIR_UUID_BUFLEN);
8295 }
8296 
8297 static void
make_nonnull_nwfilter_binding(remote_nonnull_nwfilter_binding * binding_dst,virNWFilterBindingPtr binding_src)8298 make_nonnull_nwfilter_binding(remote_nonnull_nwfilter_binding *binding_dst, virNWFilterBindingPtr binding_src)
8299 {
8300     binding_dst->portdev = binding_src->portdev;
8301     binding_dst->filtername = binding_src->filtername;
8302 }
8303 
8304 static void
make_nonnull_domain_checkpoint(remote_nonnull_domain_checkpoint * checkpoint_dst,virDomainCheckpointPtr checkpoint_src)8305 make_nonnull_domain_checkpoint(remote_nonnull_domain_checkpoint *checkpoint_dst, virDomainCheckpointPtr checkpoint_src)
8306 {
8307     checkpoint_dst->name = checkpoint_src->name;
8308     make_nonnull_domain(&checkpoint_dst->dom, checkpoint_src->domain);
8309 }
8310 
8311 static void
make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot * snapshot_dst,virDomainSnapshotPtr snapshot_src)8312 make_nonnull_domain_snapshot(remote_nonnull_domain_snapshot *snapshot_dst, virDomainSnapshotPtr snapshot_src)
8313 {
8314     snapshot_dst->name = snapshot_src->name;
8315     make_nonnull_domain(&snapshot_dst->dom, snapshot_src->domain);
8316 }
8317 
8318 /*----------------------------------------------------------------------*/
8319 
remoteVersion(void)8320 unsigned long remoteVersion(void)
8321 {
8322     return REMOTE_PROTOCOL_VERSION;
8323 }
8324 
8325 static virHypervisorDriver hypervisor_driver = {
8326     .name = "remote",
8327     .connectOpen = remoteConnectOpen, /* 0.3.0 */
8328     .connectClose = remoteConnectClose, /* 0.3.0 */
8329     .connectSetIdentity = remoteConnectSetIdentity, /* 5.8.0 */
8330     .connectSupportsFeature = remoteConnectSupportsFeature, /* 0.3.0 */
8331     .connectGetType = remoteConnectGetType, /* 0.3.0 */
8332     .connectGetVersion = remoteConnectGetVersion, /* 0.3.0 */
8333     .connectGetLibVersion = remoteConnectGetLibVersion, /* 0.7.3 */
8334     .connectGetHostname = remoteConnectGetHostname, /* 0.3.0 */
8335     .connectGetSysinfo = remoteConnectGetSysinfo, /* 0.8.8 */
8336     .connectGetMaxVcpus = remoteConnectGetMaxVcpus, /* 0.3.0 */
8337     .nodeGetInfo = remoteNodeGetInfo, /* 0.3.0 */
8338     .connectGetCapabilities = remoteConnectGetCapabilities, /* 0.3.0 */
8339     .connectListDomains = remoteConnectListDomains, /* 0.3.0 */
8340     .connectNumOfDomains = remoteConnectNumOfDomains, /* 0.3.0 */
8341     .connectListAllDomains = remoteConnectListAllDomains, /* 0.9.13 */
8342     .domainCreateXML = remoteDomainCreateXML, /* 0.3.0 */
8343     .domainCreateXMLWithFiles = remoteDomainCreateXMLWithFiles, /* 1.1.1 */
8344     .domainLookupByID = remoteDomainLookupByID, /* 0.3.0 */
8345     .domainLookupByUUID = remoteDomainLookupByUUID, /* 0.3.0 */
8346     .domainLookupByName = remoteDomainLookupByName, /* 0.3.0 */
8347     .domainSuspend = remoteDomainSuspend, /* 0.3.0 */
8348     .domainResume = remoteDomainResume, /* 0.3.0 */
8349     .domainPMSuspendForDuration = remoteDomainPMSuspendForDuration, /* 0.9.10 */
8350     .domainPMWakeup = remoteDomainPMWakeup, /* 0.9.11 */
8351     .domainShutdown = remoteDomainShutdown, /* 0.3.0 */
8352     .domainShutdownFlags = remoteDomainShutdownFlags, /* 0.9.10 */
8353     .domainReboot = remoteDomainReboot, /* 0.3.0 */
8354     .domainReset = remoteDomainReset, /* 0.9.7 */
8355     .domainDestroy = remoteDomainDestroy, /* 0.3.0 */
8356     .domainDestroyFlags = remoteDomainDestroyFlags, /* 0.9.4 */
8357     .domainGetOSType = remoteDomainGetOSType, /* 0.3.0 */
8358     .domainGetMaxMemory = remoteDomainGetMaxMemory, /* 0.3.0 */
8359     .domainSetMaxMemory = remoteDomainSetMaxMemory, /* 0.3.0 */
8360     .domainSetMemory = remoteDomainSetMemory, /* 0.3.0 */
8361     .domainSetMemoryFlags = remoteDomainSetMemoryFlags, /* 0.9.0 */
8362     .domainSetMemoryStatsPeriod = remoteDomainSetMemoryStatsPeriod, /* 1.1.1 */
8363     .domainSetMemoryParameters = remoteDomainSetMemoryParameters, /* 0.8.5 */
8364     .domainGetMemoryParameters = remoteDomainGetMemoryParameters, /* 0.8.5 */
8365     .domainSetBlkioParameters = remoteDomainSetBlkioParameters, /* 0.9.0 */
8366     .domainGetBlkioParameters = remoteDomainGetBlkioParameters, /* 0.9.0 */
8367     .domainGetPerfEvents = remoteDomainGetPerfEvents, /* 1.3.3 */
8368     .domainSetPerfEvents = remoteDomainSetPerfEvents, /* 1.3.3 */
8369     .domainGetInfo = remoteDomainGetInfo, /* 0.3.0 */
8370     .domainGetState = remoteDomainGetState, /* 0.9.2 */
8371     .domainGetControlInfo = remoteDomainGetControlInfo, /* 0.9.3 */
8372     .domainSave = remoteDomainSave, /* 0.3.0 */
8373     .domainSaveFlags = remoteDomainSaveFlags, /* 0.9.4 */
8374     .domainRestore = remoteDomainRestore, /* 0.3.0 */
8375     .domainRestoreFlags = remoteDomainRestoreFlags, /* 0.9.4 */
8376     .domainSaveImageGetXMLDesc = remoteDomainSaveImageGetXMLDesc, /* 0.9.4 */
8377     .domainSaveImageDefineXML = remoteDomainSaveImageDefineXML, /* 0.9.4 */
8378     .domainCoreDump = remoteDomainCoreDump, /* 0.3.0 */
8379     .domainCoreDumpWithFormat = remoteDomainCoreDumpWithFormat, /* 1.2.3 */
8380     .domainScreenshot = remoteDomainScreenshot, /* 0.9.2 */
8381     .domainSetVcpus = remoteDomainSetVcpus, /* 0.3.0 */
8382     .domainSetVcpusFlags = remoteDomainSetVcpusFlags, /* 0.8.5 */
8383     .domainGetVcpusFlags = remoteDomainGetVcpusFlags, /* 0.8.5 */
8384     .domainPinVcpu = remoteDomainPinVcpu, /* 0.3.0 */
8385     .domainPinVcpuFlags = remoteDomainPinVcpuFlags, /* 0.9.3 */
8386     .domainGetVcpuPinInfo = remoteDomainGetVcpuPinInfo, /* 0.9.3 */
8387     .domainPinEmulator = remoteDomainPinEmulator, /* 0.10.0 */
8388     .domainGetEmulatorPinInfo = remoteDomainGetEmulatorPinInfo, /* 0.10.0 */
8389     .domainGetVcpus = remoteDomainGetVcpus, /* 0.3.0 */
8390     .domainGetMaxVcpus = remoteDomainGetMaxVcpus, /* 0.3.0 */
8391     .domainGetIOThreadInfo = remoteDomainGetIOThreadInfo, /* 1.2.14 */
8392     .domainPinIOThread = remoteDomainPinIOThread, /* 1.2.14 */
8393     .domainAddIOThread = remoteDomainAddIOThread, /* 1.2.15 */
8394     .domainDelIOThread = remoteDomainDelIOThread, /* 1.2.15 */
8395     .domainSetIOThreadParams = remoteDomainSetIOThreadParams, /* 4.10.0 */
8396     .domainGetSecurityLabel = remoteDomainGetSecurityLabel, /* 0.6.1 */
8397     .domainGetSecurityLabelList = remoteDomainGetSecurityLabelList, /* 0.10.0 */
8398     .nodeGetSecurityModel = remoteNodeGetSecurityModel, /* 0.6.1 */
8399     .domainGetXMLDesc = remoteDomainGetXMLDesc, /* 0.3.0 */
8400     .connectDomainXMLFromNative = remoteConnectDomainXMLFromNative, /* 0.6.4 */
8401     .connectDomainXMLToNative = remoteConnectDomainXMLToNative, /* 0.6.4 */
8402     .connectListDefinedDomains = remoteConnectListDefinedDomains, /* 0.3.0 */
8403     .connectNumOfDefinedDomains = remoteConnectNumOfDefinedDomains, /* 0.3.0 */
8404     .domainCreate = remoteDomainCreate, /* 0.3.0 */
8405     .domainCreateWithFlags = remoteDomainCreateWithFlags, /* 0.8.2 */
8406     .domainCreateWithFiles = remoteDomainCreateWithFiles, /* 1.1.1 */
8407     .domainDefineXML = remoteDomainDefineXML, /* 0.3.0 */
8408     .domainDefineXMLFlags = remoteDomainDefineXMLFlags, /* 1.2.12 */
8409     .domainUndefine = remoteDomainUndefine, /* 0.3.0 */
8410     .domainUndefineFlags = remoteDomainUndefineFlags, /* 0.9.4 */
8411     .domainAttachDevice = remoteDomainAttachDevice, /* 0.3.0 */
8412     .domainAttachDeviceFlags = remoteDomainAttachDeviceFlags, /* 0.7.7 */
8413     .domainDetachDevice = remoteDomainDetachDevice, /* 0.3.0 */
8414     .domainDetachDeviceFlags = remoteDomainDetachDeviceFlags, /* 0.7.7 */
8415     .domainUpdateDeviceFlags = remoteDomainUpdateDeviceFlags, /* 0.8.0 */
8416     .domainDetachDeviceAlias = remoteDomainDetachDeviceAlias, /* 4.4.0 */
8417     .domainGetAutostart = remoteDomainGetAutostart, /* 0.3.0 */
8418     .domainSetAutostart = remoteDomainSetAutostart, /* 0.3.0 */
8419     .domainGetSchedulerType = remoteDomainGetSchedulerType, /* 0.3.0 */
8420     .domainGetSchedulerParameters = remoteDomainGetSchedulerParameters, /* 0.3.0 */
8421     .domainGetSchedulerParametersFlags = remoteDomainGetSchedulerParametersFlags, /* 0.9.2 */
8422     .domainSetSchedulerParameters = remoteDomainSetSchedulerParameters, /* 0.3.0 */
8423     .domainSetSchedulerParametersFlags = remoteDomainSetSchedulerParametersFlags, /* 0.9.2 */
8424     .domainMigratePrepare = remoteDomainMigratePrepare, /* 0.3.2 */
8425     .domainMigratePerform = remoteDomainMigratePerform, /* 0.3.2 */
8426     .domainMigrateFinish = remoteDomainMigrateFinish, /* 0.3.2 */
8427     .domainBlockResize = remoteDomainBlockResize, /* 0.9.8 */
8428     .domainBlockStats = remoteDomainBlockStats, /* 0.3.2 */
8429     .domainBlockStatsFlags = remoteDomainBlockStatsFlags, /* 0.9.5 */
8430     .domainInterfaceStats = remoteDomainInterfaceStats, /* 0.3.2 */
8431     .domainSetInterfaceParameters = remoteDomainSetInterfaceParameters, /* 0.9.9 */
8432     .domainGetInterfaceParameters = remoteDomainGetInterfaceParameters, /* 0.9.9 */
8433     .domainMemoryStats = remoteDomainMemoryStats, /* 0.7.5 */
8434     .domainBlockPeek = remoteDomainBlockPeek, /* 0.4.2 */
8435     .domainMemoryPeek = remoteDomainMemoryPeek, /* 0.4.2 */
8436     .domainGetBlockInfo = remoteDomainGetBlockInfo, /* 0.8.1 */
8437     .nodeGetCPUStats = remoteNodeGetCPUStats, /* 0.9.3 */
8438     .nodeGetMemoryStats = remoteNodeGetMemoryStats, /* 0.9.3 */
8439     .nodeGetCellsFreeMemory = remoteNodeGetCellsFreeMemory, /* 0.3.3 */
8440     .nodeGetFreeMemory = remoteNodeGetFreeMemory, /* 0.3.3 */
8441     .connectDomainEventRegister = remoteConnectDomainEventRegister, /* 0.5.0 */
8442     .connectDomainEventDeregister = remoteConnectDomainEventDeregister, /* 0.5.0 */
8443     .domainMigratePrepare2 = remoteDomainMigratePrepare2, /* 0.5.0 */
8444     .domainMigrateFinish2 = remoteDomainMigrateFinish2, /* 0.5.0 */
8445     .nodeDeviceDettach = remoteNodeDeviceDettach, /* 0.6.1 */
8446     .nodeDeviceDetachFlags = remoteNodeDeviceDetachFlags, /* 1.0.5 */
8447     .nodeDeviceReAttach = remoteNodeDeviceReAttach, /* 0.6.1 */
8448     .nodeDeviceReset = remoteNodeDeviceReset, /* 0.6.1 */
8449     .domainMigratePrepareTunnel = remoteDomainMigratePrepareTunnel, /* 0.7.2 */
8450     .connectIsEncrypted = remoteConnectIsEncrypted, /* 0.7.3 */
8451     .connectIsSecure = remoteConnectIsSecure, /* 0.7.3 */
8452     .domainIsActive = remoteDomainIsActive, /* 0.7.3 */
8453     .domainIsPersistent = remoteDomainIsPersistent, /* 0.7.3 */
8454     .domainIsUpdated = remoteDomainIsUpdated, /* 0.8.6 */
8455     .connectCompareCPU = remoteConnectCompareCPU, /* 0.7.5 */
8456     .connectBaselineCPU = remoteConnectBaselineCPU, /* 0.7.7 */
8457     .domainGetJobInfo = remoteDomainGetJobInfo, /* 0.7.7 */
8458     .domainGetJobStats = remoteDomainGetJobStats, /* 1.0.3 */
8459     .domainAbortJob = remoteDomainAbortJob, /* 0.7.7 */
8460     .domainMigrateGetMaxDowntime = remoteDomainMigrateGetMaxDowntime, /* 3.7.0 */
8461     .domainMigrateSetMaxDowntime = remoteDomainMigrateSetMaxDowntime, /* 0.8.0 */
8462     .domainMigrateGetCompressionCache = remoteDomainMigrateGetCompressionCache, /* 1.0.3 */
8463     .domainMigrateSetCompressionCache = remoteDomainMigrateSetCompressionCache, /* 1.0.3 */
8464     .domainMigrateSetMaxSpeed = remoteDomainMigrateSetMaxSpeed, /* 0.9.0 */
8465     .domainMigrateGetMaxSpeed = remoteDomainMigrateGetMaxSpeed, /* 0.9.5 */
8466     .connectDomainEventRegisterAny = remoteConnectDomainEventRegisterAny, /* 0.8.0 */
8467     .connectDomainEventDeregisterAny = remoteConnectDomainEventDeregisterAny, /* 0.8.0 */
8468     .domainManagedSave = remoteDomainManagedSave, /* 0.8.0 */
8469     .domainHasManagedSaveImage = remoteDomainHasManagedSaveImage, /* 0.8.0 */
8470     .domainManagedSaveRemove = remoteDomainManagedSaveRemove, /* 0.8.0 */
8471     .domainManagedSaveGetXMLDesc = remoteDomainManagedSaveGetXMLDesc, /* 3.7.0 */
8472     .domainManagedSaveDefineXML = remoteDomainManagedSaveDefineXML, /* 3.7.0 */
8473     .domainSnapshotCreateXML = remoteDomainSnapshotCreateXML, /* 0.8.0 */
8474     .domainSnapshotGetXMLDesc = remoteDomainSnapshotGetXMLDesc, /* 0.8.0 */
8475     .domainSnapshotNum = remoteDomainSnapshotNum, /* 0.8.0 */
8476     .domainSnapshotListNames = remoteDomainSnapshotListNames, /* 0.8.0 */
8477     .domainListAllSnapshots = remoteDomainListAllSnapshots, /* 0.9.13 */
8478     .domainSnapshotNumChildren = remoteDomainSnapshotNumChildren, /* 0.9.7 */
8479     .domainSnapshotListAllChildren = remoteDomainSnapshotListAllChildren, /* 0.9.13 */
8480     .domainSnapshotListChildrenNames = remoteDomainSnapshotListChildrenNames, /* 0.9.7 */
8481     .domainSnapshotLookupByName = remoteDomainSnapshotLookupByName, /* 0.8.0 */
8482     .domainHasCurrentSnapshot = remoteDomainHasCurrentSnapshot, /* 0.8.0 */
8483     .domainSnapshotGetParent = remoteDomainSnapshotGetParent, /* 0.9.7 */
8484     .domainSnapshotCurrent = remoteDomainSnapshotCurrent, /* 0.8.0 */
8485     .domainRevertToSnapshot = remoteDomainRevertToSnapshot, /* 0.8.0 */
8486     .domainSnapshotIsCurrent = remoteDomainSnapshotIsCurrent, /* 0.9.13 */
8487     .domainSnapshotHasMetadata = remoteDomainSnapshotHasMetadata, /* 0.9.13 */
8488     .domainSnapshotDelete = remoteDomainSnapshotDelete, /* 0.8.0 */
8489     .domainQemuMonitorCommand = remoteDomainQemuMonitorCommand, /* 0.8.3 */
8490     .domainQemuAttach = remoteDomainQemuAttach, /* 0.9.4 */
8491     .domainQemuAgentCommand = remoteDomainQemuAgentCommand, /* 0.10.0 */
8492     .connectDomainQemuMonitorEventRegister = remoteConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
8493     .connectDomainQemuMonitorEventDeregister = remoteConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
8494     .domainOpenConsole = remoteDomainOpenConsole, /* 0.8.6 */
8495     .domainOpenChannel = remoteDomainOpenChannel, /* 1.0.2 */
8496     .domainOpenGraphics = remoteDomainOpenGraphics, /* 0.9.7 */
8497     .domainOpenGraphicsFD = remoteDomainOpenGraphicsFD, /* 1.2.8 */
8498     .domainInjectNMI = remoteDomainInjectNMI, /* 0.9.2 */
8499     .domainMigrateBegin3 = remoteDomainMigrateBegin3, /* 0.9.2 */
8500     .domainMigratePrepare3 = remoteDomainMigratePrepare3, /* 0.9.2 */
8501     .domainMigratePrepareTunnel3 = remoteDomainMigratePrepareTunnel3, /* 0.9.2 */
8502     .domainMigratePerform3 = remoteDomainMigratePerform3, /* 0.9.2 */
8503     .domainMigrateFinish3 = remoteDomainMigrateFinish3, /* 0.9.2 */
8504     .domainMigrateConfirm3 = remoteDomainMigrateConfirm3, /* 0.9.2 */
8505     .domainSendKey = remoteDomainSendKey, /* 0.9.3 */
8506     .domainSendProcessSignal = remoteDomainSendProcessSignal, /* 1.0.1 */
8507     .domainBlockJobAbort = remoteDomainBlockJobAbort, /* 0.9.4 */
8508     .domainGetBlockJobInfo = remoteDomainGetBlockJobInfo, /* 0.9.4 */
8509     .domainBlockJobSetSpeed = remoteDomainBlockJobSetSpeed, /* 0.9.4 */
8510     .domainBlockPull = remoteDomainBlockPull, /* 0.9.4 */
8511     .domainBlockRebase = remoteDomainBlockRebase, /* 0.9.10 */
8512     .domainBlockCopy = remoteDomainBlockCopy, /* 1.2.9 */
8513     .domainBlockCommit = remoteDomainBlockCommit, /* 0.10.2 */
8514     .connectSetKeepAlive = remoteConnectSetKeepAlive, /* 0.9.8 */
8515     .connectIsAlive = remoteConnectIsAlive, /* 0.9.8 */
8516     .nodeSuspendForDuration = remoteNodeSuspendForDuration, /* 0.9.8 */
8517     .domainSetBlockIoTune = remoteDomainSetBlockIoTune, /* 0.9.8 */
8518     .domainGetBlockIoTune = remoteDomainGetBlockIoTune, /* 0.9.8 */
8519     .domainSetNumaParameters = remoteDomainSetNumaParameters, /* 0.9.9 */
8520     .domainGetNumaParameters = remoteDomainGetNumaParameters, /* 0.9.9 */
8521     .domainGetCPUStats = remoteDomainGetCPUStats, /* 0.9.10 */
8522     .domainGetDiskErrors = remoteDomainGetDiskErrors, /* 0.9.10 */
8523     .domainSetMetadata = remoteDomainSetMetadata, /* 0.9.10 */
8524     .domainGetMetadata = remoteDomainGetMetadata, /* 0.9.10 */
8525     .domainGetHostname = remoteDomainGetHostname, /* 0.10.0 */
8526     .nodeSetMemoryParameters = remoteNodeSetMemoryParameters, /* 0.10.2 */
8527     .nodeGetMemoryParameters = remoteNodeGetMemoryParameters, /* 0.10.2 */
8528     .nodeGetCPUMap = remoteNodeGetCPUMap, /* 1.0.0 */
8529     .domainFSTrim = remoteDomainFSTrim, /* 1.0.1 */
8530     .domainLxcOpenNamespace = remoteDomainLxcOpenNamespace, /* 1.0.2 */
8531     .domainMigrateBegin3Params = remoteDomainMigrateBegin3Params, /* 1.1.0 */
8532     .domainMigratePrepare3Params = remoteDomainMigratePrepare3Params, /* 1.1.0 */
8533     .domainMigratePrepareTunnel3Params = remoteDomainMigratePrepareTunnel3Params, /* 1.1.0 */
8534     .domainMigratePerform3Params = remoteDomainMigratePerform3Params, /* 1.1.0 */
8535     .domainMigrateFinish3Params = remoteDomainMigrateFinish3Params, /* 1.1.0 */
8536     .domainMigrateConfirm3Params = remoteDomainMigrateConfirm3Params, /* 1.1.0 */
8537     .connectGetCPUModelNames = remoteConnectGetCPUModelNames, /* 1.1.3 */
8538     .domainFSFreeze = remoteDomainFSFreeze, /* 1.2.5 */
8539     .domainFSThaw = remoteDomainFSThaw, /* 1.2.5 */
8540     .domainGetTime = remoteDomainGetTime, /* 1.2.5 */
8541     .domainSetTime = remoteDomainSetTime, /* 1.2.5 */
8542     .nodeGetFreePages = remoteNodeGetFreePages, /* 1.2.6 */
8543     .connectGetDomainCapabilities = remoteConnectGetDomainCapabilities, /* 1.2.7 */
8544     .connectGetAllDomainStats = remoteConnectGetAllDomainStats, /* 1.2.8 */
8545     .nodeAllocPages = remoteNodeAllocPages, /* 1.2.9 */
8546     .domainGetFSInfo = remoteDomainGetFSInfo, /* 1.2.11 */
8547     .domainInterfaceAddresses = remoteDomainInterfaceAddresses, /* 1.2.14 */
8548     .domainSetUserPassword = remoteDomainSetUserPassword, /* 1.2.16 */
8549     .domainRename = remoteDomainRename, /* 1.2.19 */
8550     .connectRegisterCloseCallback = remoteConnectRegisterCloseCallback, /* 1.3.2 */
8551     .connectUnregisterCloseCallback = remoteConnectUnregisterCloseCallback, /* 1.3.2 */
8552     .domainMigrateStartPostCopy = remoteDomainMigrateStartPostCopy, /* 1.3.3 */
8553     .domainGetGuestVcpus = remoteDomainGetGuestVcpus, /* 2.0.0 */
8554     .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */
8555     .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */
8556     .domainSetBlockThreshold = remoteDomainSetBlockThreshold, /* 3.2.0 */
8557     .domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
8558     .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 */
8559     .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 4.4.0 */
8560     .nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
8561     .domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo, /* 4.5.0 */
8562     .domainCheckpointCreateXML = remoteDomainCheckpointCreateXML, /* 5.6.0 */
8563     .domainCheckpointGetXMLDesc = remoteDomainCheckpointGetXMLDesc, /* 5.6.0 */
8564     .domainListAllCheckpoints = remoteDomainListAllCheckpoints, /* 5.6.0 */
8565     .domainCheckpointListAllChildren = remoteDomainCheckpointListAllChildren, /* 5.6.0 */
8566     .domainCheckpointLookupByName = remoteDomainCheckpointLookupByName, /* 5.6.0 */
8567     .domainCheckpointGetParent = remoteDomainCheckpointGetParent, /* 5.6.0 */
8568     .domainCheckpointDelete = remoteDomainCheckpointDelete, /* 5.6.0 */
8569     .domainGetGuestInfo = remoteDomainGetGuestInfo, /* 5.7.0 */
8570     .domainAgentSetResponseTimeout = remoteDomainAgentSetResponseTimeout, /* 5.10.0 */
8571     .domainBackupBegin = remoteDomainBackupBegin, /* 6.0.0 */
8572     .domainBackupGetXMLDesc = remoteDomainBackupGetXMLDesc, /* 6.0.0 */
8573     .domainAuthorizedSSHKeysGet = remoteDomainAuthorizedSSHKeysGet, /* 6.10.0 */
8574     .domainAuthorizedSSHKeysSet = remoteDomainAuthorizedSSHKeysSet, /* 6.10.0 */
8575     .domainGetMessages = remoteDomainGetMessages, /* 7.1.0 */
8576     .domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */
8577 };
8578 
8579 static virNetworkDriver network_driver = {
8580     .connectNumOfNetworks = remoteConnectNumOfNetworks, /* 0.3.0 */
8581     .connectListNetworks = remoteConnectListNetworks, /* 0.3.0 */
8582     .connectNumOfDefinedNetworks = remoteConnectNumOfDefinedNetworks, /* 0.3.0 */
8583     .connectListDefinedNetworks = remoteConnectListDefinedNetworks, /* 0.3.0 */
8584     .connectListAllNetworks = remoteConnectListAllNetworks, /* 0.10.2 */
8585     .connectNetworkEventDeregisterAny = remoteConnectNetworkEventDeregisterAny, /* 1.2.1 */
8586     .connectNetworkEventRegisterAny = remoteConnectNetworkEventRegisterAny, /* 1.2.1 */
8587     .networkLookupByUUID = remoteNetworkLookupByUUID, /* 0.3.0 */
8588     .networkLookupByName = remoteNetworkLookupByName, /* 0.3.0 */
8589     .networkCreateXML = remoteNetworkCreateXML, /* 0.3.0 */
8590     .networkCreateXMLFlags = remoteNetworkCreateXMLFlags, /* 7.8.0 */
8591     .networkDefineXML = remoteNetworkDefineXML, /* 0.3.0 */
8592     .networkDefineXMLFlags = remoteNetworkDefineXMLFlags, /* 7.7.0 */
8593     .networkUndefine = remoteNetworkUndefine, /* 0.3.0 */
8594     .networkUpdate = remoteNetworkUpdate, /* 0.10.2 */
8595     .networkCreate = remoteNetworkCreate, /* 0.3.0 */
8596     .networkDestroy = remoteNetworkDestroy, /* 0.3.0 */
8597     .networkGetXMLDesc = remoteNetworkGetXMLDesc, /* 0.3.0 */
8598     .networkGetBridgeName = remoteNetworkGetBridgeName, /* 0.3.0 */
8599     .networkGetAutostart = remoteNetworkGetAutostart, /* 0.3.0 */
8600     .networkSetAutostart = remoteNetworkSetAutostart, /* 0.3.0 */
8601     .networkIsActive = remoteNetworkIsActive, /* 0.7.3 */
8602     .networkIsPersistent = remoteNetworkIsPersistent, /* 0.7.3 */
8603     .networkGetDHCPLeases = remoteNetworkGetDHCPLeases, /* 1.2.6 */
8604     .networkListAllPorts = remoteNetworkListAllPorts, /* 5.5.0 */
8605     .networkPortLookupByUUID = remoteNetworkPortLookupByUUID, /* 5.5.0 */
8606     .networkPortCreateXML = remoteNetworkPortCreateXML, /* 5.5.0 */
8607     .networkPortGetXMLDesc = remoteNetworkPortGetXMLDesc, /* 5.5.0 */
8608     .networkPortSetParameters = remoteNetworkPortSetParameters, /* 5.5.0 */
8609     .networkPortGetParameters = remoteNetworkPortGetParameters, /* 5.5.0 */
8610     .networkPortDelete = remoteNetworkPortDelete, /* 5.5.0 */
8611 };
8612 
8613 static virInterfaceDriver interface_driver = {
8614     .connectNumOfInterfaces = remoteConnectNumOfInterfaces, /* 0.7.2 */
8615     .connectListInterfaces = remoteConnectListInterfaces, /* 0.7.2 */
8616     .connectNumOfDefinedInterfaces = remoteConnectNumOfDefinedInterfaces, /* 0.7.2 */
8617     .connectListDefinedInterfaces = remoteConnectListDefinedInterfaces, /* 0.7.2 */
8618     .connectListAllInterfaces = remoteConnectListAllInterfaces, /* 0.10.2 */
8619     .interfaceLookupByName = remoteInterfaceLookupByName, /* 0.7.2 */
8620     .interfaceLookupByMACString = remoteInterfaceLookupByMACString, /* 0.7.2 */
8621     .interfaceGetXMLDesc = remoteInterfaceGetXMLDesc, /* 0.7.2 */
8622     .interfaceDefineXML = remoteInterfaceDefineXML, /* 0.7.2 */
8623     .interfaceUndefine = remoteInterfaceUndefine, /* 0.7.2 */
8624     .interfaceCreate = remoteInterfaceCreate, /* 0.7.2 */
8625     .interfaceDestroy = remoteInterfaceDestroy, /* 0.7.2 */
8626     .interfaceIsActive = remoteInterfaceIsActive, /* 0.7.3 */
8627     .interfaceChangeBegin = remoteInterfaceChangeBegin, /* 0.9.2 */
8628     .interfaceChangeCommit = remoteInterfaceChangeCommit, /* 0.9.2 */
8629     .interfaceChangeRollback = remoteInterfaceChangeRollback, /* 0.9.2 */
8630 };
8631 
8632 static virStorageDriver storage_driver = {
8633     .connectNumOfStoragePools = remoteConnectNumOfStoragePools, /* 0.4.1 */
8634     .connectListStoragePools = remoteConnectListStoragePools, /* 0.4.1 */
8635     .connectNumOfDefinedStoragePools = remoteConnectNumOfDefinedStoragePools, /* 0.4.1 */
8636     .connectListDefinedStoragePools = remoteConnectListDefinedStoragePools, /* 0.4.1 */
8637     .connectListAllStoragePools = remoteConnectListAllStoragePools, /* 0.10.2 */
8638     .connectFindStoragePoolSources = remoteConnectFindStoragePoolSources, /* 0.4.5 */
8639     .connectStoragePoolEventDeregisterAny = remoteConnectStoragePoolEventDeregisterAny, /* 2.0.0 */
8640     .connectStoragePoolEventRegisterAny = remoteConnectStoragePoolEventRegisterAny, /* 2.0.0 */
8641     .connectGetStoragePoolCapabilities = remoteConnectGetStoragePoolCapabilities, /* 5.2.0 */
8642     .storagePoolLookupByName = remoteStoragePoolLookupByName, /* 0.4.1 */
8643     .storagePoolLookupByUUID = remoteStoragePoolLookupByUUID, /* 0.4.1 */
8644     .storagePoolLookupByVolume = remoteStoragePoolLookupByVolume, /* 0.4.1 */
8645     .storagePoolLookupByTargetPath = remoteStoragePoolLookupByTargetPath, /* 4.1.0 */
8646     .storagePoolCreateXML = remoteStoragePoolCreateXML, /* 0.4.1 */
8647     .storagePoolDefineXML = remoteStoragePoolDefineXML, /* 0.4.1 */
8648     .storagePoolBuild = remoteStoragePoolBuild, /* 0.4.1 */
8649     .storagePoolUndefine = remoteStoragePoolUndefine, /* 0.4.1 */
8650     .storagePoolCreate = remoteStoragePoolCreate, /* 0.4.1 */
8651     .storagePoolDestroy = remoteStoragePoolDestroy, /* 0.4.1 */
8652     .storagePoolDelete = remoteStoragePoolDelete, /* 0.4.1 */
8653     .storagePoolRefresh = remoteStoragePoolRefresh, /* 0.4.1 */
8654     .storagePoolGetInfo = remoteStoragePoolGetInfo, /* 0.4.1 */
8655     .storagePoolGetXMLDesc = remoteStoragePoolGetXMLDesc, /* 0.4.1 */
8656     .storagePoolGetAutostart = remoteStoragePoolGetAutostart, /* 0.4.1 */
8657     .storagePoolSetAutostart = remoteStoragePoolSetAutostart, /* 0.4.1 */
8658     .storagePoolNumOfVolumes = remoteStoragePoolNumOfVolumes, /* 0.4.1 */
8659     .storagePoolListVolumes = remoteStoragePoolListVolumes, /* 0.4.1 */
8660     .storagePoolListAllVolumes = remoteStoragePoolListAllVolumes, /* 0.10.0 */
8661 
8662     .storageVolLookupByName = remoteStorageVolLookupByName, /* 0.4.1 */
8663     .storageVolLookupByKey = remoteStorageVolLookupByKey, /* 0.4.1 */
8664     .storageVolLookupByPath = remoteStorageVolLookupByPath, /* 0.4.1 */
8665     .storageVolCreateXML = remoteStorageVolCreateXML, /* 0.4.1 */
8666     .storageVolCreateXMLFrom = remoteStorageVolCreateXMLFrom, /* 0.6.4 */
8667     .storageVolDownload = remoteStorageVolDownload, /* 0.9.0 */
8668     .storageVolUpload = remoteStorageVolUpload, /* 0.9.0 */
8669     .storageVolDelete = remoteStorageVolDelete, /* 0.4.1 */
8670     .storageVolWipe = remoteStorageVolWipe, /* 0.8.0 */
8671     .storageVolWipePattern = remoteStorageVolWipePattern, /* 0.9.10 */
8672     .storageVolGetInfo = remoteStorageVolGetInfo, /* 0.4.1 */
8673     .storageVolGetInfoFlags = remoteStorageVolGetInfoFlags, /* 3.0.0 */
8674     .storageVolGetXMLDesc = remoteStorageVolGetXMLDesc, /* 0.4.1 */
8675     .storageVolGetPath = remoteStorageVolGetPath, /* 0.4.1 */
8676     .storageVolResize = remoteStorageVolResize, /* 0.9.10 */
8677     .storagePoolIsActive = remoteStoragePoolIsActive, /* 0.7.3 */
8678     .storagePoolIsPersistent = remoteStoragePoolIsPersistent, /* 0.7.3 */
8679 };
8680 
8681 static virSecretDriver secret_driver = {
8682     .connectNumOfSecrets = remoteConnectNumOfSecrets, /* 0.7.1 */
8683     .connectListSecrets = remoteConnectListSecrets, /* 0.7.1 */
8684     .connectListAllSecrets = remoteConnectListAllSecrets, /* 0.10.2 */
8685     .secretLookupByUUID = remoteSecretLookupByUUID, /* 0.7.1 */
8686     .secretLookupByUsage = remoteSecretLookupByUsage, /* 0.7.1 */
8687     .secretDefineXML = remoteSecretDefineXML, /* 0.7.1 */
8688     .secretGetXMLDesc = remoteSecretGetXMLDesc, /* 0.7.1 */
8689     .secretSetValue = remoteSecretSetValue, /* 0.7.1 */
8690     .secretGetValue = remoteSecretGetValue, /* 0.7.1 */
8691     .secretUndefine = remoteSecretUndefine, /* 0.7.1 */
8692     .connectSecretEventDeregisterAny = remoteConnectSecretEventDeregisterAny, /* 3.0.0 */
8693     .connectSecretEventRegisterAny = remoteConnectSecretEventRegisterAny, /* 3.0.0 */
8694 };
8695 
8696 static virNodeDeviceDriver node_device_driver = {
8697     .connectNodeDeviceEventDeregisterAny = remoteConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
8698     .connectNodeDeviceEventRegisterAny = remoteConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
8699     .nodeNumOfDevices = remoteNodeNumOfDevices, /* 0.5.0 */
8700     .nodeListDevices = remoteNodeListDevices, /* 0.5.0 */
8701     .connectListAllNodeDevices  = remoteConnectListAllNodeDevices, /* 0.10.2 */
8702     .nodeDeviceLookupByName = remoteNodeDeviceLookupByName, /* 0.5.0 */
8703     .nodeDeviceLookupSCSIHostByWWN = remoteNodeDeviceLookupSCSIHostByWWN, /* 1.0.2 */
8704     .nodeDeviceGetXMLDesc = remoteNodeDeviceGetXMLDesc, /* 0.5.0 */
8705     .nodeDeviceGetParent = remoteNodeDeviceGetParent, /* 0.5.0 */
8706     .nodeDeviceNumOfCaps = remoteNodeDeviceNumOfCaps, /* 0.5.0 */
8707     .nodeDeviceListCaps = remoteNodeDeviceListCaps, /* 0.5.0 */
8708     .nodeDeviceCreateXML = remoteNodeDeviceCreateXML, /* 0.6.3 */
8709     .nodeDeviceCreate = remoteNodeDeviceCreate, /* 7.3.0 */
8710     .nodeDeviceDefineXML = remoteNodeDeviceDefineXML, /* 7.3.0 */
8711     .nodeDeviceUndefine = remoteNodeDeviceUndefine, /* 7.3.0 */
8712     .nodeDeviceDestroy = remoteNodeDeviceDestroy, /* 0.6.3 */
8713     .nodeDeviceGetAutostart = remoteNodeDeviceGetAutostart, /* 7.8.0 */
8714     .nodeDeviceSetAutostart = remoteNodeDeviceSetAutostart, /* 7.8.0 */
8715     .nodeDeviceIsPersistent = remoteNodeDeviceIsPersistent, /* 7.8.0 */
8716     .nodeDeviceIsActive = remoteNodeDeviceIsActive, /* 7.8.0 */
8717 };
8718 
8719 static virNWFilterDriver nwfilter_driver = {
8720     .nwfilterLookupByUUID = remoteNWFilterLookupByUUID, /* 0.8.0 */
8721     .nwfilterLookupByName = remoteNWFilterLookupByName, /* 0.8.0 */
8722     .nwfilterGetXMLDesc           = remoteNWFilterGetXMLDesc, /* 0.8.0 */
8723     .nwfilterDefineXML            = remoteNWFilterDefineXML, /* 0.8.0 */
8724     .nwfilterDefineXMLFlags       = remoteNWFilterDefineXMLFlags, /* 7.7.0 */
8725     .nwfilterUndefine             = remoteNWFilterUndefine, /* 0.8.0 */
8726     .connectNumOfNWFilters       = remoteConnectNumOfNWFilters, /* 0.8.0 */
8727     .connectListNWFilters        = remoteConnectListNWFilters, /* 0.8.0 */
8728     .connectListAllNWFilters     = remoteConnectListAllNWFilters, /* 0.10.2 */
8729     .connectListAllNWFilterBindings = remoteConnectListAllNWFilterBindings, /* 4.5.0 */
8730     .nwfilterBindingLookupByPortDev = remoteNWFilterBindingLookupByPortDev, /* 4.5.0 */
8731     .nwfilterBindingCreateXML = remoteNWFilterBindingCreateXML, /* 4.5.0 */
8732     .nwfilterBindingDelete = remoteNWFilterBindingDelete, /* 4.5.0 */
8733     .nwfilterBindingGetXMLDesc = remoteNWFilterBindingGetXMLDesc, /* 4.5.0 */
8734 };
8735 
8736 static virConnectDriver connect_driver = {
8737     .hypervisorDriver = &hypervisor_driver,
8738     .interfaceDriver = &interface_driver,
8739     .networkDriver = &network_driver,
8740     .nodeDeviceDriver = &node_device_driver,
8741     .nwfilterDriver = &nwfilter_driver,
8742     .secretDriver = &secret_driver,
8743     .storageDriver = &storage_driver,
8744 };
8745 
8746 static virStateDriver state_driver = {
8747     .name = "Remote",
8748     .stateInitialize = remoteStateInitialize,
8749 };
8750 
8751 
8752 /** remoteRegister:
8753  *
8754  * Register driver with libvirt driver system.
8755  *
8756  * Returns -1 on error.
8757  */
8758 int
remoteRegister(void)8759 remoteRegister(void)
8760 {
8761     if (virRegisterConnectDriver(&connect_driver,
8762                                  false) < 0)
8763         return -1;
8764     if (virRegisterStateDriver(&state_driver) < 0)
8765         return -1;
8766 
8767     return 0;
8768 }
8769