1 /*
2  * domain_conf.c: domain XML processing
3  *
4  * Copyright (C) 2006-2016 Red Hat, Inc.
5  * Copyright (C) 2006-2008 Daniel P. Berrange
6  * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library.  If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <config.h>
24 
25 #include <fcntl.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 
29 #include "configmake.h"
30 #include "internal.h"
31 #include "virerror.h"
32 #include "checkpoint_conf.h"
33 #include "datatypes.h"
34 #include "domain_addr.h"
35 #include "domain_conf.h"
36 #include "domain_validate.h"
37 #include "snapshot_conf.h"
38 #include "viralloc.h"
39 #include "virxml.h"
40 #include "viruuid.h"
41 #include "virbuffer.h"
42 #include "virlog.h"
43 #include "nwfilter_conf.h"
44 #include "virnetworkportdef.h"
45 #include "storage_conf.h"
46 #include "storage_source_conf.h"
47 #include "virfile.h"
48 #include "virbitmap.h"
49 #include "secret_conf.h"
50 #include "netdev_vport_profile_conf.h"
51 #include "netdev_bandwidth_conf.h"
52 #include "netdev_vlan_conf.h"
53 #include "device_conf.h"
54 #include "network_conf.h"
55 #include "virtpm.h"
56 #include "virsecret.h"
57 #include "virstring.h"
58 #include "virnetdev.h"
59 #include "virnetdevtap.h"
60 #include "virnetdevmacvlan.h"
61 #include "virarptable.h"
62 #include "virmdev.h"
63 #include "virdomainsnapshotobjlist.h"
64 #include "virdomaincheckpointobjlist.h"
65 #include "virutil.h"
66 
67 #define VIR_FROM_THIS VIR_FROM_DOMAIN
68 
69 VIR_LOG_INIT("conf.domain_conf");
70 
71 #define VIR_DOMAIN_DEF_FORMAT_COMMON_FLAGS \
72     (VIR_DOMAIN_DEF_FORMAT_SECURE | \
73      VIR_DOMAIN_DEF_FORMAT_INACTIVE | \
74      VIR_DOMAIN_DEF_FORMAT_MIGRATABLE)
75 
76 VIR_ENUM_IMPL(virDomainTaint,
77               VIR_DOMAIN_TAINT_LAST,
78               "custom-argv",
79               "custom-monitor",
80               "high-privileges",
81               "shell-scripts",
82               "disk-probing",
83               "external-launch",
84               "host-cpu",
85               "hook-script",
86               "cdrom-passthrough",
87               "custom-dtb",
88               "custom-ga-command",
89               "custom-hypervisor-feature",
90               "deprecated-config",
91 );
92 
93 VIR_ENUM_IMPL(virDomainTaintMessage,
94               VIR_DOMAIN_TAINT_LAST,
95               N_("custom configuration parameters specified"),
96               N_("custom monitor control commands issued"),
97               N_("running with undesirable elevated privileges"),
98               N_("network configuration using opaque shell scripts"),
99               N_("potentially unsafe disk format probing"),
100               N_("managing externally launched configuration"),
101               N_("potentially unsafe use of host CPU passthrough"),
102               N_("configuration potentially modified by hook script"),
103               N_("use of host cdrom passthrough"),
104               N_("custom device tree blob used"),
105               N_("custom guest agent control commands issued"),
106               N_("hypervisor feature autodetection override"),
107               N_("use of deprecated configuration settings"),
108 );
109 
110 VIR_ENUM_IMPL(virDomainVirt,
111               VIR_DOMAIN_VIRT_LAST,
112               "none",
113               "qemu",
114               "kqemu",
115               "kvm",
116               "xen",
117               "lxc",
118               "uml",
119               "openvz",
120               "test",
121               "vmware",
122               "hyperv",
123               "vbox",
124               "phyp",
125               "parallels",
126               "bhyve",
127               "vz",
128               "nvmm"
129 );
130 
131 VIR_ENUM_IMPL(virDomainOS,
132               VIR_DOMAIN_OSTYPE_LAST,
133               "hvm",
134               "xen",
135               "linux",
136               "exe",
137               "uml",
138               "xenpvh",
139 );
140 
141 VIR_ENUM_IMPL(virDomainBoot,
142               VIR_DOMAIN_BOOT_LAST,
143               "fd",
144               "cdrom",
145               "hd",
146               "network",
147 );
148 
149 VIR_ENUM_IMPL(virDomainFeature,
150               VIR_DOMAIN_FEATURE_LAST,
151               "acpi",
152               "apic",
153               "pae",
154               "hap",
155               "viridian",
156               "privnet",
157               "hyperv",
158               "kvm",
159               "pvspinlock",
160               "capabilities",
161               "pmu",
162               "vmport",
163               "gic",
164               "smm",
165               "ioapic",
166               "hpt",
167               "vmcoreinfo",
168               "htm",
169               "nested-hv",
170               "msrs",
171               "ccf-assist",
172               "xen",
173               "cfpc",
174               "sbbc",
175               "ibs",
176 );
177 
178 VIR_ENUM_IMPL(virDomainCapabilitiesPolicy,
179               VIR_DOMAIN_CAPABILITIES_POLICY_LAST,
180               "default",
181               "allow",
182               "deny",
183 );
184 
185 VIR_ENUM_IMPL(virDomainHyperv,
186               VIR_DOMAIN_HYPERV_LAST,
187               "relaxed",
188               "vapic",
189               "spinlocks",
190               "vpindex",
191               "runtime",
192               "synic",
193               "stimer",
194               "reset",
195               "vendor_id",
196               "frequencies",
197               "reenlightenment",
198               "tlbflush",
199               "ipi",
200               "evmcs",
201 );
202 
203 VIR_ENUM_IMPL(virDomainKVM,
204               VIR_DOMAIN_KVM_LAST,
205               "hidden",
206               "hint-dedicated",
207               "poll-control",
208               "pv-ipi",
209 );
210 
211 VIR_ENUM_IMPL(virDomainXen,
212               VIR_DOMAIN_XEN_LAST,
213               "e820_host",
214               "passthrough",
215 );
216 
217 VIR_ENUM_IMPL(virDomainXenPassthroughMode,
218               VIR_DOMAIN_XEN_PASSTHROUGH_MODE_LAST,
219               "default",
220               "sync_pt",
221               "share_pt",
222 );
223 
224 VIR_ENUM_IMPL(virDomainMsrsUnknown,
225               VIR_DOMAIN_MSRS_UNKNOWN_LAST,
226               "ignore",
227               "fault",
228 );
229 
230 VIR_ENUM_IMPL(virDomainProcessCapsFeature,
231               VIR_DOMAIN_PROCES_CAPS_FEATURE_LAST,
232               "audit_control",
233               "audit_write",
234               "block_suspend",
235               "chown",
236               "dac_override",
237               "dac_read_search",
238               "fowner",
239               "fsetid",
240               "ipc_lock",
241               "ipc_owner",
242               "kill",
243               "lease",
244               "linux_immutable",
245               "mac_admin",
246               "mac_override",
247               "mknod",
248               "net_admin",
249               "net_bind_service",
250               "net_broadcast",
251               "net_raw",
252               "setgid",
253               "setfcap",
254               "setpcap",
255               "setuid",
256               "sys_admin",
257               "sys_boot",
258               "sys_chroot",
259               "sys_module",
260               "sys_nice",
261               "sys_pacct",
262               "sys_ptrace",
263               "sys_rawio",
264               "sys_resource",
265               "sys_time",
266               "sys_tty_config",
267               "syslog",
268               "wake_alarm",
269 );
270 
271 VIR_ENUM_IMPL(virDomainLifecycle,
272               VIR_DOMAIN_LIFECYCLE_LAST,
273               "poweroff",
274               "reboot",
275               "crash",
276 );
277 
278 VIR_ENUM_IMPL(virDomainLifecycleAction,
279               VIR_DOMAIN_LIFECYCLE_ACTION_LAST,
280               "destroy",
281               "restart",
282               "rename-restart",
283               "preserve",
284               "coredump-destroy",
285               "coredump-restart",
286 );
287 
288 VIR_ENUM_IMPL(virDomainLockFailure,
289               VIR_DOMAIN_LOCK_FAILURE_LAST,
290               "default",
291               "poweroff",
292               "restart",
293               "pause",
294               "ignore",
295 );
296 
297 VIR_ENUM_IMPL(virDomainDevice,
298               VIR_DOMAIN_DEVICE_LAST,
299               "none",
300               "disk",
301               "lease",
302               "filesystem",
303               "interface",
304               "input",
305               "sound",
306               "video",
307               "hostdev",
308               "watchdog",
309               "controller",
310               "graphics",
311               "hub",
312               "redirdev",
313               "smartcard",
314               "chr",
315               "memballoon",
316               "nvram",
317               "rng",
318               "shmem",
319               "tpm",
320               "panic",
321               "memory",
322               "iommu",
323               "vsock",
324               "audio",
325 );
326 
327 VIR_ENUM_IMPL(virDomainDiskDevice,
328               VIR_DOMAIN_DISK_DEVICE_LAST,
329               "disk",
330               "cdrom",
331               "floppy",
332               "lun",
333 );
334 
335 VIR_ENUM_IMPL(virDomainDiskGeometryTrans,
336               VIR_DOMAIN_DISK_TRANS_LAST,
337               "default",
338               "none",
339               "auto",
340               "lba",
341 );
342 
343 VIR_ENUM_IMPL(virDomainDiskBus,
344               VIR_DOMAIN_DISK_BUS_LAST,
345               "none",
346               "ide",
347               "fdc",
348               "scsi",
349               "virtio",
350               "xen",
351               "usb",
352               "uml",
353               "sata",
354               "sd",
355 );
356 
357 VIR_ENUM_IMPL(virDomainDiskCache,
358               VIR_DOMAIN_DISK_CACHE_LAST,
359               "default",
360               "none",
361               "writethrough",
362               "writeback",
363               "directsync",
364               "unsafe",
365 );
366 
367 VIR_ENUM_IMPL(virDomainDiskErrorPolicy,
368               VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
369               "default",
370               "stop",
371               "report",
372               "ignore",
373               "enospace",
374 );
375 
376 VIR_ENUM_IMPL(virDomainDiskIo,
377               VIR_DOMAIN_DISK_IO_LAST,
378               "default",
379               "native",
380               "threads",
381               "io_uring",
382 );
383 
384 VIR_ENUM_IMPL(virDomainDeviceSGIO,
385               VIR_DOMAIN_DEVICE_SGIO_LAST,
386               "default",
387               "filtered",
388               "unfiltered",
389 );
390 
391 VIR_ENUM_IMPL(virDomainController,
392               VIR_DOMAIN_CONTROLLER_TYPE_LAST,
393               "ide",
394               "fdc",
395               "scsi",
396               "sata",
397               "virtio-serial",
398               "ccid",
399               "usb",
400               "pci",
401               "xenbus",
402               "isa",
403 );
404 
405 VIR_ENUM_IMPL(virDomainControllerModelPCI,
406               VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST,
407               "pci-root",
408               "pcie-root",
409               "pci-bridge",
410               "dmi-to-pci-bridge",
411               "pcie-to-pci-bridge",
412               "pcie-root-port",
413               "pcie-switch-upstream-port",
414               "pcie-switch-downstream-port",
415               "pci-expander-bus",
416               "pcie-expander-bus",
417 );
418 
419 VIR_ENUM_IMPL(virDomainControllerPCIModelName,
420               VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_LAST,
421               "none",
422               "pci-bridge",
423               "i82801b11-bridge",
424               "ioh3420",
425               "x3130-upstream",
426               "xio3130-downstream",
427               "pxb",
428               "pxb-pcie",
429               "pcie-root-port",
430               "spapr-pci-host-bridge",
431               "pcie-pci-bridge",
432 );
433 
434 VIR_ENUM_IMPL(virDomainControllerModelSCSI,
435               VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST,
436               "auto",
437               "buslogic",
438               "lsilogic",
439               "lsisas1068",
440               "vmpvscsi",
441               "ibmvscsi",
442               "virtio-scsi",
443               "lsisas1078",
444               "virtio-transitional",
445               "virtio-non-transitional",
446               "ncr53c90",
447               "dc390",
448               "am53c974",
449 );
450 
451 VIR_ENUM_IMPL(virDomainControllerModelISA, VIR_DOMAIN_CONTROLLER_MODEL_ISA_LAST,
452 );
453 
454 VIR_ENUM_IMPL(virDomainControllerModelUSB,
455               VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST,
456               "piix3-uhci",
457               "piix4-uhci",
458               "ehci",
459               "ich9-ehci1",
460               "ich9-uhci1",
461               "ich9-uhci2",
462               "ich9-uhci3",
463               "vt82c686b-uhci",
464               "pci-ohci",
465               "nec-xhci",
466               "qusb1",
467               "qusb2",
468               "qemu-xhci",
469               "none",
470 );
471 
472 VIR_ENUM_IMPL(virDomainControllerModelIDE,
473               VIR_DOMAIN_CONTROLLER_MODEL_IDE_LAST,
474               "piix3",
475               "piix4",
476               "ich6",
477 );
478 
479 VIR_ENUM_IMPL(virDomainControllerModelVirtioSerial,
480               VIR_DOMAIN_CONTROLLER_MODEL_VIRTIO_SERIAL_LAST,
481               "virtio",
482               "virtio-transitional",
483               "virtio-non-transitional",
484 );
485 
486 VIR_ENUM_IMPL(virDomainFS,
487               VIR_DOMAIN_FS_TYPE_LAST,
488               "mount",
489               "block",
490               "file",
491               "template",
492               "ram",
493               "bind",
494               "volume",
495 );
496 
497 VIR_ENUM_IMPL(virDomainFSDriver,
498               VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
499               "default",
500               "path",
501               "handle",
502               "loop",
503               "nbd",
504               "ploop",
505               "virtiofs",
506 );
507 
508 VIR_ENUM_IMPL(virDomainFSAccessMode,
509               VIR_DOMAIN_FS_ACCESSMODE_LAST,
510               "",
511               "passthrough",
512               "mapped",
513               "squash",
514 );
515 
516 VIR_ENUM_IMPL(virDomainFSWrpolicy,
517               VIR_DOMAIN_FS_WRPOLICY_LAST,
518               "default",
519               "immediate",
520 );
521 
522 VIR_ENUM_IMPL(virDomainFSModel,
523               VIR_DOMAIN_FS_MODEL_LAST,
524               "default",
525               "virtio",
526               "virtio-transitional",
527               "virtio-non-transitional",
528 );
529 
530 VIR_ENUM_IMPL(virDomainFSMultidevs,
531               VIR_DOMAIN_FS_MULTIDEVS_LAST,
532               "default",
533               "remap",
534               "forbid",
535               "warn",
536 );
537 
538 VIR_ENUM_IMPL(virDomainFSCacheMode,
539               VIR_DOMAIN_FS_CACHE_MODE_LAST,
540               "default",
541               "none",
542               "always",
543 );
544 
545 VIR_ENUM_IMPL(virDomainFSSandboxMode,
546               VIR_DOMAIN_FS_SANDBOX_MODE_LAST,
547               "default",
548               "namespace",
549               "chroot",
550 );
551 
552 
553 VIR_ENUM_IMPL(virDomainNet,
554               VIR_DOMAIN_NET_TYPE_LAST,
555               "user",
556               "ethernet",
557               "vhostuser",
558               "server",
559               "client",
560               "mcast",
561               "network",
562               "bridge",
563               "internal",
564               "direct",
565               "hostdev",
566               "udp",
567               "vdpa",
568 );
569 
570 VIR_ENUM_IMPL(virDomainNetModel,
571               VIR_DOMAIN_NET_MODEL_LAST,
572               "unknown",
573               "netfront",
574               "rtl8139",
575               "virtio",
576               "e1000",
577               "e1000e",
578               "virtio-transitional",
579               "virtio-non-transitional",
580               "usb-net",
581               "spapr-vlan",
582               "lan9118",
583               "scm91c111",
584               "vlance",
585               "vmxnet",
586               "vmxnet2",
587               "vmxnet3",
588               "Am79C970A",
589               "Am79C973",
590               "82540EM",
591               "82545EM",
592               "82543GC",
593 );
594 
595 VIR_ENUM_IMPL(virDomainNetBackend,
596               VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
597               "default",
598               "qemu",
599               "vhost",
600 );
601 
602 VIR_ENUM_IMPL(virDomainNetVirtioTxMode,
603               VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST,
604               "default",
605               "iothread",
606               "timer",
607 );
608 
609 VIR_ENUM_IMPL(virDomainNetTeaming,
610               VIR_DOMAIN_NET_TEAMING_TYPE_LAST,
611               "none",
612               "persistent",
613               "transient",
614 );
615 
616 VIR_ENUM_IMPL(virDomainNetInterfaceLinkState,
617               VIR_DOMAIN_NET_INTERFACE_LINK_STATE_LAST,
618               "default",
619               "up",
620               "down",
621 );
622 
623 VIR_ENUM_IMPL(virDomainChrDeviceState,
624               VIR_DOMAIN_CHR_DEVICE_STATE_LAST,
625               "default",
626               "connected",
627               "disconnected",
628 );
629 
630 VIR_ENUM_IMPL(virDomainNetMacType,
631               VIR_DOMAIN_NET_MAC_TYPE_LAST,
632               "",
633               "generated",
634               "static",
635 );
636 
637 VIR_ENUM_IMPL(virDomainChrSerialTarget,
638               VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST,
639               "none",
640               "isa-serial",
641               "usb-serial",
642               "pci-serial",
643               "spapr-vio-serial",
644               "system-serial",
645               "sclp-serial",
646 );
647 
648 VIR_ENUM_IMPL(virDomainChrChannelTarget,
649               VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
650               "none",
651               "guestfwd",
652               "virtio",
653               "xen",
654 );
655 
656 VIR_ENUM_IMPL(virDomainChrConsoleTarget,
657               VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST,
658               "none",
659               "serial",
660               "xen",
661               "uml",
662               "virtio",
663               "lxc",
664               "openvz",
665               "sclp",
666               "sclplm",
667 );
668 
669 VIR_ENUM_IMPL(virDomainChrSerialTargetModel,
670               VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST,
671               "none",
672               "isa-serial",
673               "usb-serial",
674               "pci-serial",
675               "spapr-vty",
676               "pl011",
677               "sclpconsole",
678               "sclplmconsole",
679               "16550a",
680 );
681 
682 VIR_ENUM_IMPL(virDomainChrDevice,
683               VIR_DOMAIN_CHR_DEVICE_TYPE_LAST,
684               "parallel",
685               "serial",
686               "console",
687               "channel",
688 );
689 
690 VIR_ENUM_IMPL(virDomainChr,
691               VIR_DOMAIN_CHR_TYPE_LAST,
692               "null",
693               "vc",
694               "pty",
695               "dev",
696               "file",
697               "pipe",
698               "stdio",
699               "udp",
700               "tcp",
701               "unix",
702               "spicevmc",
703               "spiceport",
704               "nmdm",
705 );
706 
707 VIR_ENUM_IMPL(virDomainChrTcpProtocol,
708               VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
709               "raw",
710               "telnet",
711               "telnets",
712               "tls",
713 );
714 
715 VIR_ENUM_IMPL(virDomainChrSpicevmc,
716               VIR_DOMAIN_CHR_SPICEVMC_LAST,
717               "vdagent",
718               "smartcard",
719               "usbredir",
720 );
721 
722 VIR_ENUM_IMPL(virDomainSmartcard,
723               VIR_DOMAIN_SMARTCARD_TYPE_LAST,
724               "host",
725               "host-certificates",
726               "passthrough",
727 );
728 
729 VIR_ENUM_IMPL(virDomainSoundCodec,
730               VIR_DOMAIN_SOUND_CODEC_TYPE_LAST,
731               "duplex",
732               "micro",
733               "output",
734 );
735 
736 VIR_ENUM_IMPL(virDomainSoundModel,
737               VIR_DOMAIN_SOUND_MODEL_LAST,
738               "sb16",
739               "es1370",
740               "pcspk",
741               "ac97",
742               "ich6",
743               "ich9",
744               "usb",
745               "ich7",
746 );
747 
748 VIR_ENUM_IMPL(virDomainAudioType,
749               VIR_DOMAIN_AUDIO_TYPE_LAST,
750               "none",
751               "alsa",
752               "coreaudio",
753               "jack",
754               "oss",
755               "pulseaudio",
756               "sdl",
757               "spice",
758               "file",
759 );
760 
761 VIR_ENUM_IMPL(virDomainAudioSDLDriver,
762               VIR_DOMAIN_AUDIO_SDL_DRIVER_LAST,
763               "",
764               "esd",
765               "alsa",
766               "arts",
767               "pulseaudio",
768 );
769 
770 VIR_ENUM_IMPL(virDomainAudioFormat,
771               VIR_DOMAIN_AUDIO_FORMAT_LAST,
772               "",
773               "u8",
774               "s8",
775               "u16",
776               "s16",
777               "u32",
778               "s32",
779               "f32",
780 );
781 
782 VIR_ENUM_IMPL(virDomainKeyWrapCipherName,
783               VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST,
784               "aes",
785               "dea",
786 );
787 
788 VIR_ENUM_IMPL(virDomainMemballoonModel,
789               VIR_DOMAIN_MEMBALLOON_MODEL_LAST,
790               "virtio",
791               "xen",
792               "none",
793               "virtio-transitional",
794               "virtio-non-transitional",
795 );
796 
797 VIR_ENUM_IMPL(virDomainSmbiosMode,
798               VIR_DOMAIN_SMBIOS_LAST,
799               "none",
800               "emulate",
801               "host",
802               "sysinfo",
803 );
804 
805 VIR_ENUM_IMPL(virDomainWatchdogModel,
806               VIR_DOMAIN_WATCHDOG_MODEL_LAST,
807               "i6300esb",
808               "ib700",
809               "diag288",
810 );
811 
812 VIR_ENUM_IMPL(virDomainWatchdogAction,
813               VIR_DOMAIN_WATCHDOG_ACTION_LAST,
814               "reset",
815               "shutdown",
816               "poweroff",
817               "pause",
818               "dump",
819               "none",
820               "inject-nmi",
821 );
822 
823 VIR_ENUM_IMPL(virDomainPanicModel,
824               VIR_DOMAIN_PANIC_MODEL_LAST,
825               "default",
826               "isa",
827               "pseries",
828               "hyperv",
829               "s390",
830 );
831 
832 VIR_ENUM_IMPL(virDomainVideoBackend,
833               VIR_DOMAIN_VIDEO_BACKEND_TYPE_LAST,
834               "default",
835               "qemu",
836               "vhostuser",
837 );
838 
839 VIR_ENUM_IMPL(virDomainVideo,
840               VIR_DOMAIN_VIDEO_TYPE_LAST,
841               "default",
842               "vga",
843               "cirrus",
844               "vmvga",
845               "xen",
846               "vbox",
847               "qxl",
848               "parallels",
849               "virtio",
850               "gop",
851               "none",
852               "bochs",
853               "ramfb",
854 );
855 
856 VIR_ENUM_IMPL(virDomainVideoVGAConf,
857               VIR_DOMAIN_VIDEO_VGACONF_LAST,
858               "io",
859               "on",
860               "off",
861 );
862 
863 VIR_ENUM_IMPL(virDomainInput,
864               VIR_DOMAIN_INPUT_TYPE_LAST,
865               "mouse",
866               "tablet",
867               "keyboard",
868               "passthrough",
869               "evdev",
870 );
871 
872 VIR_ENUM_IMPL(virDomainInputBus,
873               VIR_DOMAIN_INPUT_BUS_LAST,
874               "ps2",
875               "usb",
876               "xen",
877               "parallels",
878               "virtio",
879               "none",
880 );
881 
882 VIR_ENUM_IMPL(virDomainInputModel,
883               VIR_DOMAIN_INPUT_MODEL_LAST,
884               "default",
885               "virtio",
886               "virtio-transitional",
887               "virtio-non-transitional",
888 );
889 
890 VIR_ENUM_IMPL(virDomainInputSourceGrab,
891               VIR_DOMAIN_INPUT_SOURCE_GRAB_LAST,
892               "default",
893               "all",
894 );
895 
896 VIR_ENUM_IMPL(virDomainInputSourceGrabToggle,
897               VIR_DOMAIN_INPUT_SOURCE_GRAB_TOGGLE_LAST,
898               "default",
899               "ctrl-ctrl",
900               "alt-alt",
901               "shift-shift",
902               "meta-meta",
903               "scrolllock",
904               "ctrl-scrolllock",
905 );
906 
907 VIR_ENUM_IMPL(virDomainGraphics,
908               VIR_DOMAIN_GRAPHICS_TYPE_LAST,
909               "sdl",
910               "vnc",
911               "rdp",
912               "desktop",
913               "spice",
914               "egl-headless",
915 );
916 
917 VIR_ENUM_IMPL(virDomainGraphicsListen,
918               VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST,
919               "none",
920               "address",
921               "network",
922               "socket",
923 );
924 
925 VIR_ENUM_IMPL(virDomainGraphicsAuthConnected,
926               VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_LAST,
927               "default",
928               "fail",
929               "disconnect",
930               "keep",
931 );
932 
933 VIR_ENUM_IMPL(virDomainGraphicsVNCSharePolicy,
934               VIR_DOMAIN_GRAPHICS_VNC_SHARE_LAST,
935               "default",
936               "allow-exclusive",
937               "force-shared",
938               "ignore",
939 );
940 
941 VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelName,
942               VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST,
943               "main",
944               "display",
945               "inputs",
946               "cursor",
947               "playback",
948               "record",
949               "smartcard",
950               "usbredir",
951 );
952 
953 VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelMode,
954               VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST,
955               "any",
956               "secure",
957               "insecure",
958 );
959 
960 VIR_ENUM_IMPL(virDomainGraphicsSpiceImageCompression,
961               VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST,
962               "default",
963               "auto_glz",
964               "auto_lz",
965               "quic",
966               "glz",
967               "lz",
968               "off",
969 );
970 
971 VIR_ENUM_IMPL(virDomainGraphicsSpiceJpegCompression,
972               VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST,
973               "default",
974               "auto",
975               "never",
976               "always",
977 );
978 
979 VIR_ENUM_IMPL(virDomainGraphicsSpiceZlibCompression,
980               VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST,
981               "default",
982               "auto",
983               "never",
984               "always",
985 );
986 
987 VIR_ENUM_IMPL(virDomainGraphicsSpiceMouseMode,
988               VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_LAST,
989               "default",
990               "server",
991               "client",
992 );
993 
994 VIR_ENUM_IMPL(virDomainGraphicsSpiceStreamingMode,
995               VIR_DOMAIN_GRAPHICS_SPICE_STREAMING_MODE_LAST,
996               "default",
997               "filter",
998               "all",
999               "off",
1000 );
1001 
1002 VIR_ENUM_IMPL(virDomainHostdevMode,
1003               VIR_DOMAIN_HOSTDEV_MODE_LAST,
1004               "subsystem",
1005               "capabilities",
1006 );
1007 
1008 VIR_ENUM_IMPL(virDomainHostdevSubsys,
1009               VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
1010               "usb",
1011               "pci",
1012               "scsi",
1013               "scsi_host",
1014               "mdev",
1015 );
1016 
1017 VIR_ENUM_IMPL(virDomainHostdevSubsysPCIBackend,
1018               VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST,
1019               "default",
1020               "kvm",
1021               "vfio",
1022               "xen",
1023 );
1024 
1025 VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIProtocol,
1026               VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST,
1027               "adapter",
1028               "iscsi",
1029 );
1030 
1031 VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIHostProtocol,
1032               VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_LAST,
1033               "none",
1034               "vhost",
1035 );
1036 
1037 VIR_ENUM_IMPL(virDomainHostdevSubsysSCSIVHostModel,
1038               VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_VHOST_MODEL_TYPE_LAST,
1039               "default",
1040               "virtio",
1041               "virtio-transitional",
1042               "virtio-non-transitional",
1043 );
1044 
1045 VIR_ENUM_IMPL(virDomainHostdevCaps,
1046               VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST,
1047               "storage",
1048               "misc",
1049               "net",
1050 );
1051 
1052 VIR_ENUM_IMPL(virDomainHub,
1053               VIR_DOMAIN_HUB_TYPE_LAST,
1054               "usb",
1055 );
1056 
1057 VIR_ENUM_IMPL(virDomainRedirdevBus,
1058               VIR_DOMAIN_REDIRDEV_BUS_LAST,
1059               "usb",
1060 );
1061 
1062 VIR_ENUM_IMPL(virDomainState,
1063               VIR_DOMAIN_LAST,
1064               "nostate",
1065               "running",
1066               "blocked",
1067               "paused",
1068               "shutdown",
1069               "shutoff",
1070               "crashed",
1071               "pmsuspended",
1072 );
1073 
1074 VIR_ENUM_IMPL(virDomainNostateReason,
1075               VIR_DOMAIN_NOSTATE_LAST,
1076               "unknown",
1077 );
1078 
1079 VIR_ENUM_IMPL(virDomainRunningReason,
1080               VIR_DOMAIN_RUNNING_LAST,
1081               "unknown",
1082               "booted",
1083               "migrated",
1084               "restored",
1085               "from snapshot",
1086               "unpaused",
1087               "migration canceled",
1088               "save canceled",
1089               "wakeup",
1090               "crashed",
1091               "post-copy",
1092 );
1093 
1094 VIR_ENUM_IMPL(virDomainBlockedReason,
1095               VIR_DOMAIN_BLOCKED_LAST,
1096               "unknown",
1097 );
1098 
1099 VIR_ENUM_IMPL(virDomainPausedReason,
1100               VIR_DOMAIN_PAUSED_LAST,
1101               "unknown",
1102               "user",
1103               "migration",
1104               "save",
1105               "dump",
1106               "ioerror",
1107               "watchdog",
1108               "from snapshot",
1109               "shutdown",
1110               "snapshot",
1111               "panicked",
1112               "starting up",
1113               "post-copy",
1114               "post-copy failed",
1115 );
1116 
1117 VIR_ENUM_IMPL(virDomainShutdownReason,
1118               VIR_DOMAIN_SHUTDOWN_LAST,
1119               "unknown",
1120               "user",
1121 );
1122 
1123 VIR_ENUM_IMPL(virDomainShutoffReason,
1124               VIR_DOMAIN_SHUTOFF_LAST,
1125               "unknown",
1126               "shutdown",
1127               "destroyed",
1128               "crashed",
1129               "migrated",
1130               "saved",
1131               "failed",
1132               "from snapshot",
1133               "daemon",
1134 );
1135 
1136 VIR_ENUM_IMPL(virDomainCrashedReason,
1137               VIR_DOMAIN_CRASHED_LAST,
1138               "unknown",
1139               "panicked",
1140 );
1141 
1142 VIR_ENUM_IMPL(virDomainPMSuspendedReason,
1143               VIR_DOMAIN_PMSUSPENDED_LAST,
1144               "unknown",
1145 );
1146 
1147 VIR_ENUM_IMPL(virDomainSeclabel,
1148               VIR_DOMAIN_SECLABEL_LAST,
1149               "default",
1150               "none",
1151               "dynamic",
1152               "static",
1153 );
1154 
1155 VIR_ENUM_IMPL(virDomainClockOffset,
1156               VIR_DOMAIN_CLOCK_OFFSET_LAST,
1157               "utc",
1158               "localtime",
1159               "variable",
1160               "timezone",
1161 );
1162 
1163 VIR_ENUM_IMPL(virDomainClockBasis,
1164               VIR_DOMAIN_CLOCK_BASIS_LAST,
1165               "utc",
1166               "localtime",
1167 );
1168 
1169 VIR_ENUM_IMPL(virDomainTimerName,
1170               VIR_DOMAIN_TIMER_NAME_LAST,
1171               "platform",
1172               "pit",
1173               "rtc",
1174               "hpet",
1175               "tsc",
1176               "kvmclock",
1177               "hypervclock",
1178               "armvtimer",
1179 );
1180 
1181 VIR_ENUM_IMPL(virDomainTimerTrack,
1182               VIR_DOMAIN_TIMER_TRACK_LAST,
1183               "boot",
1184               "guest",
1185               "wall",
1186               "realtime",
1187 );
1188 
1189 VIR_ENUM_IMPL(virDomainTimerTickpolicy,
1190               VIR_DOMAIN_TIMER_TICKPOLICY_LAST,
1191               "delay",
1192               "catchup",
1193               "merge",
1194               "discard",
1195 );
1196 
1197 VIR_ENUM_IMPL(virDomainTimerMode,
1198               VIR_DOMAIN_TIMER_MODE_LAST,
1199               "auto",
1200               "native",
1201               "emulate",
1202               "paravirt",
1203               "smpsafe",
1204 );
1205 
1206 VIR_ENUM_IMPL(virDomainStartupPolicy,
1207               VIR_DOMAIN_STARTUP_POLICY_LAST,
1208               "default",
1209               "mandatory",
1210               "requisite",
1211               "optional",
1212 );
1213 
1214 VIR_ENUM_IMPL(virDomainCpuPlacementMode,
1215               VIR_DOMAIN_CPU_PLACEMENT_MODE_LAST,
1216               "static",
1217               "auto",
1218 );
1219 
1220 VIR_ENUM_IMPL(virDomainDiskTray,
1221               VIR_DOMAIN_DISK_TRAY_LAST,
1222               "closed",
1223               "open",
1224 );
1225 
1226 VIR_ENUM_IMPL(virDomainRNGModel,
1227               VIR_DOMAIN_RNG_MODEL_LAST,
1228               "virtio",
1229               "virtio-transitional",
1230               "virtio-non-transitional",
1231 );
1232 
1233 VIR_ENUM_IMPL(virDomainRNGBackend,
1234               VIR_DOMAIN_RNG_BACKEND_LAST,
1235               "random",
1236               "egd",
1237               "builtin",
1238 );
1239 
1240 VIR_ENUM_IMPL(virDomainTPMModel,
1241               VIR_DOMAIN_TPM_MODEL_LAST,
1242               "default",
1243               "tpm-tis",
1244               "tpm-crb",
1245               "tpm-spapr",
1246               "spapr-tpm-proxy",
1247 );
1248 
1249 VIR_ENUM_IMPL(virDomainTPMBackend,
1250               VIR_DOMAIN_TPM_TYPE_LAST,
1251               "passthrough",
1252               "emulator",
1253 );
1254 
1255 VIR_ENUM_IMPL(virDomainTPMVersion,
1256               VIR_DOMAIN_TPM_VERSION_LAST,
1257               "default",
1258               "1.2",
1259               "2.0",
1260 );
1261 
1262 VIR_ENUM_IMPL(virDomainTPMPcrBank,
1263               VIR_DOMAIN_TPM_PCR_BANK_LAST,
1264               "sha1",
1265               "sha256",
1266               "sha384",
1267               "sha512",
1268 );
1269 
1270 VIR_ENUM_IMPL(virDomainIOMMUModel,
1271               VIR_DOMAIN_IOMMU_MODEL_LAST,
1272               "intel",
1273               "smmuv3",
1274 );
1275 
1276 VIR_ENUM_IMPL(virDomainVsockModel,
1277               VIR_DOMAIN_VSOCK_MODEL_LAST,
1278               "default",
1279               "virtio",
1280               "virtio-transitional",
1281               "virtio-non-transitional",
1282 );
1283 
1284 VIR_ENUM_IMPL(virDomainDiskDiscard,
1285               VIR_DOMAIN_DISK_DISCARD_LAST,
1286               "default",
1287               "unmap",
1288               "ignore",
1289 );
1290 
1291 VIR_ENUM_IMPL(virDomainDiskDetectZeroes,
1292               VIR_DOMAIN_DISK_DETECT_ZEROES_LAST,
1293               "default",
1294               "off",
1295               "on",
1296               "unmap",
1297 );
1298 
1299 VIR_ENUM_IMPL(virDomainDiskModel,
1300               VIR_DOMAIN_DISK_MODEL_LAST,
1301               "default",
1302               "virtio",
1303               "virtio-transitional",
1304               "virtio-non-transitional",
1305 );
1306 
1307 VIR_ENUM_IMPL(virDomainDiskMirrorState,
1308               VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
1309               "none",
1310               "yes",
1311               "abort",
1312               "pivot",
1313 );
1314 
1315 VIR_ENUM_IMPL(virDomainMemorySource,
1316               VIR_DOMAIN_MEMORY_SOURCE_LAST,
1317               "none",
1318               "file",
1319               "anonymous",
1320               "memfd",
1321 );
1322 
1323 VIR_ENUM_IMPL(virDomainMemoryAllocation,
1324               VIR_DOMAIN_MEMORY_ALLOCATION_LAST,
1325               "none",
1326               "immediate",
1327               "ondemand",
1328 );
1329 
1330 VIR_ENUM_IMPL(virDomainLoader,
1331               VIR_DOMAIN_LOADER_TYPE_LAST,
1332               "none",
1333               "rom",
1334               "pflash",
1335 );
1336 
1337 VIR_ENUM_IMPL(virDomainIOAPIC,
1338               VIR_DOMAIN_IOAPIC_LAST,
1339               "none",
1340               "qemu",
1341               "kvm",
1342 );
1343 
1344 VIR_ENUM_IMPL(virDomainHPTResizing,
1345               VIR_DOMAIN_HPT_RESIZING_LAST,
1346               "none",
1347               "enabled",
1348               "disabled",
1349               "required",
1350 );
1351 
1352 VIR_ENUM_IMPL(virDomainOsDefFirmware,
1353               VIR_DOMAIN_OS_DEF_FIRMWARE_LAST,
1354               "none",
1355               "bios",
1356               "efi",
1357 );
1358 
1359 VIR_ENUM_IMPL(virDomainOsDefFirmwareFeature,
1360               VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_LAST,
1361               "enrolled-keys",
1362               "secure-boot",
1363 );
1364 
1365 VIR_ENUM_IMPL(virDomainCFPC,
1366               VIR_DOMAIN_CFPC_LAST,
1367               "none",
1368               "broken",
1369               "workaround",
1370               "fixed",
1371 );
1372 
1373 VIR_ENUM_IMPL(virDomainSBBC,
1374               VIR_DOMAIN_SBBC_LAST,
1375               "none",
1376               "broken",
1377               "workaround",
1378               "fixed",
1379 );
1380 
1381 VIR_ENUM_IMPL(virDomainIBS,
1382               VIR_DOMAIN_IBS_LAST,
1383               "none",
1384               "broken",
1385               "workaround",
1386               "fixed-ibs",
1387               "fixed-ccd",
1388               "fixed-na",
1389 );
1390 
1391 /* Internal mapping: subset of block job types that can be present in
1392  * <mirror> XML (remaining types are not two-phase). */
1393 VIR_ENUM_DECL(virDomainBlockJob);
1394 VIR_ENUM_IMPL(virDomainBlockJob,
1395               VIR_DOMAIN_BLOCK_JOB_TYPE_LAST,
1396               "", "", "copy", "", "active-commit", "",
1397 );
1398 
1399 VIR_ENUM_IMPL(virDomainMemoryModel,
1400               VIR_DOMAIN_MEMORY_MODEL_LAST,
1401               "",
1402               "dimm",
1403               "nvdimm",
1404               "virtio-pmem",
1405               "virtio-mem",
1406 );
1407 
1408 VIR_ENUM_IMPL(virDomainShmemModel,
1409               VIR_DOMAIN_SHMEM_MODEL_LAST,
1410               "ivshmem",
1411               "ivshmem-plain",
1412               "ivshmem-doorbell",
1413 );
1414 
1415 VIR_ENUM_IMPL(virDomainShmemRole,
1416               VIR_DOMAIN_SHMEM_ROLE_LAST,
1417               "default",
1418               "master",
1419               "peer",
1420 );
1421 
1422 VIR_ENUM_IMPL(virDomainLaunchSecurity,
1423               VIR_DOMAIN_LAUNCH_SECURITY_LAST,
1424               "",
1425               "sev",
1426               "s390-pv",
1427 );
1428 
1429 static virClass *virDomainObjClass;
1430 static virClass *virDomainXMLOptionClass;
1431 static void virDomainObjDispose(void *obj);
1432 static void virDomainXMLOptionDispose(void *obj);
1433 
1434 
1435 static void
1436 virDomainChrSourceDefFormat(virBuffer *buf,
1437                             virDomainChrSourceDef *def,
1438                             unsigned int flags);
1439 
1440 
1441 static int
1442 virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDef *def,
1443                                        xmlNodePtr node,
1444                                        xmlXPathContextPtr ctxt);
1445 
1446 
virDomainObjOnceInit(void)1447 static int virDomainObjOnceInit(void)
1448 {
1449     if (!VIR_CLASS_NEW(virDomainObj, virClassForObjectLockable()))
1450         return -1;
1451 
1452     if (!VIR_CLASS_NEW(virDomainXMLOption, virClassForObject()))
1453         return -1;
1454 
1455     return 0;
1456 }
1457 
1458 VIR_ONCE_GLOBAL_INIT(virDomainObj);
1459 
1460 
1461 static void
virDomainXMLOptionDispose(void * obj)1462 virDomainXMLOptionDispose(void *obj)
1463 {
1464     virDomainXMLOption *xmlopt = obj;
1465 
1466     if (xmlopt->config.privFree)
1467         (xmlopt->config.privFree)(xmlopt->config.priv);
1468 }
1469 
1470 /**
1471  * virDomainKeyWrapCipherDefParseXML:
1472  *
1473  * @def  Domain definition
1474  * @node An XML cipher node
1475  *
1476  * Parse the attributes from the cipher node and store the state
1477  * attribute in @def.
1478  *
1479  * A cipher node has the form of
1480  *
1481  *   <cipher name='aes|dea' state='on|off'/>
1482  *
1483  * Returns: 0 if the parse succeeded
1484  *         -1 otherwise
1485  */
1486 static int
virDomainKeyWrapCipherDefParseXML(virDomainKeyWrapDef * keywrap,xmlNodePtr node)1487 virDomainKeyWrapCipherDefParseXML(virDomainKeyWrapDef *keywrap,
1488                                   xmlNodePtr node)
1489 {
1490     virDomainKeyWrapCipherName name;
1491     virTristateSwitch state;
1492 
1493     if (virXMLPropEnum(node, "name", virDomainKeyWrapCipherNameTypeFromString,
1494                        VIR_XML_PROP_REQUIRED, &name) < 0)
1495         return -1;
1496 
1497     if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_REQUIRED,
1498                                  &state) < 0)
1499         return -1;
1500 
1501     switch (name) {
1502     case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_AES:
1503         if (keywrap->aes != VIR_TRISTATE_SWITCH_ABSENT) {
1504             virReportError(VIR_ERR_INTERNAL_ERROR,
1505                            _("A domain definition can have no more than "
1506                              "one cipher node with name %s"),
1507                            virDomainKeyWrapCipherNameTypeToString(name));
1508 
1509             return -1;
1510         }
1511         keywrap->aes = state;
1512         break;
1513 
1514     case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_DEA:
1515         if (keywrap->dea != VIR_TRISTATE_SWITCH_ABSENT) {
1516             virReportError(VIR_ERR_INTERNAL_ERROR,
1517                            _("A domain definition can have no more than "
1518                              "one cipher node with name %s"),
1519                            virDomainKeyWrapCipherNameTypeToString(name));
1520 
1521             return -1;
1522         }
1523         keywrap->dea = state;
1524         break;
1525 
1526     case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST:
1527         break;
1528     }
1529 
1530     return 0;
1531 }
1532 
1533 static int
virDomainKeyWrapDefParseXML(virDomainDef * def,xmlXPathContextPtr ctxt)1534 virDomainKeyWrapDefParseXML(virDomainDef *def, xmlXPathContextPtr ctxt)
1535 {
1536     size_t i;
1537     int n;
1538     g_autofree xmlNodePtr *nodes = NULL;
1539     g_autofree virDomainKeyWrapDef *keywrap = NULL;
1540 
1541     if ((n = virXPathNodeSet("./keywrap/cipher", ctxt, &nodes)) < 0)
1542         return n;
1543 
1544     keywrap = g_new0(virDomainKeyWrapDef, 1);
1545 
1546     for (i = 0; i < n; i++) {
1547         if (virDomainKeyWrapCipherDefParseXML(keywrap, nodes[i]) < 0)
1548             return -1;
1549     }
1550 
1551     if (keywrap->aes || keywrap->dea)
1552         def->keywrap = g_steal_pointer(&keywrap);
1553 
1554     return 0;
1555 }
1556 
1557 
1558 /**
1559  * virDomainXMLOptionNew:
1560  *
1561  * Allocate a new domain XML configuration
1562  */
1563 virDomainXMLOption *
virDomainXMLOptionNew(virDomainDefParserConfig * config,virDomainXMLPrivateDataCallbacks * priv,virXMLNamespace * xmlns,virDomainABIStability * abi,virSaveCookieCallbacks * saveCookie)1564 virDomainXMLOptionNew(virDomainDefParserConfig *config,
1565                       virDomainXMLPrivateDataCallbacks *priv,
1566                       virXMLNamespace *xmlns,
1567                       virDomainABIStability *abi,
1568                       virSaveCookieCallbacks *saveCookie)
1569 {
1570     virDomainXMLOption *xmlopt;
1571 
1572     if (virDomainObjInitialize() < 0)
1573         return NULL;
1574 
1575     if (!(xmlopt = virObjectNew(virDomainXMLOptionClass)))
1576         return NULL;
1577 
1578     if (priv)
1579         xmlopt->privateData = *priv;
1580 
1581     if (config)
1582         xmlopt->config = *config;
1583 
1584     if (xmlns)
1585         xmlopt->ns = *xmlns;
1586 
1587     if (abi)
1588         xmlopt->abi = *abi;
1589 
1590     if (saveCookie)
1591         xmlopt->saveCookie = *saveCookie;
1592 
1593     /* Technically this forbids to use one of Xerox's MAC address prefixes in
1594      * our hypervisor drivers. This shouldn't ever be a problem.
1595      *
1596      * Use the KVM prefix as default as it's in the privately administered
1597      * range */
1598     if (xmlopt->config.macPrefix[0] == 0 &&
1599         xmlopt->config.macPrefix[1] == 0 &&
1600         xmlopt->config.macPrefix[2] == 0) {
1601         xmlopt->config.macPrefix[0] = 0x52;
1602         xmlopt->config.macPrefix[1] = 0x54;
1603     }
1604 
1605     return xmlopt;
1606 }
1607 
1608 /**
1609  * virDomainXMLOptionGetNamespace:
1610  *
1611  * @xmlopt: XML parser configuration object
1612  *
1613  * Returns a pointer to the stored namespace structure.
1614  * The lifetime of the pointer is equal to @xmlopt;
1615  */
1616 virXMLNamespace *
virDomainXMLOptionGetNamespace(virDomainXMLOption * xmlopt)1617 virDomainXMLOptionGetNamespace(virDomainXMLOption *xmlopt)
1618 {
1619     return &xmlopt->ns;
1620 }
1621 
1622 static int
virDomainVirtioOptionsParseXML(xmlNodePtr driver,virDomainVirtioOptions ** virtio)1623 virDomainVirtioOptionsParseXML(xmlNodePtr driver,
1624                                virDomainVirtioOptions **virtio)
1625 {
1626     if (*virtio || !driver)
1627         return 0;
1628 
1629     *virtio = g_new0(virDomainVirtioOptions, 1);
1630 
1631     if (virXMLPropTristateSwitch(driver, "iommu", VIR_XML_PROP_NONE,
1632                                  &(*virtio)->iommu) < 0)
1633         return -1;
1634 
1635     if (virXMLPropTristateSwitch(driver, "ats", VIR_XML_PROP_NONE,
1636                                  &(*virtio)->ats) < 0)
1637         return -1;
1638 
1639     if (virXMLPropTristateSwitch(driver, "packed", VIR_XML_PROP_NONE,
1640                                  &(*virtio)->packed) < 0)
1641         return -1;
1642 
1643     if (virXMLPropTristateSwitch(driver, "page_per_vq", VIR_XML_PROP_NONE,
1644                                  &(*virtio)->page_per_vq) < 0)
1645         return -1;
1646 
1647     return 0;
1648 }
1649 
1650 
1651 virSaveCookieCallbacks *
virDomainXMLOptionGetSaveCookie(virDomainXMLOption * xmlopt)1652 virDomainXMLOptionGetSaveCookie(virDomainXMLOption *xmlopt)
1653 {
1654     return &xmlopt->saveCookie;
1655 }
1656 
1657 
1658 void
virDomainXMLOptionSetMomentPostParse(virDomainXMLOption * xmlopt,virDomainMomentPostParseCallback cb)1659 virDomainXMLOptionSetMomentPostParse(virDomainXMLOption *xmlopt,
1660                                      virDomainMomentPostParseCallback cb)
1661 {
1662     xmlopt->momentPostParse = cb;
1663 }
1664 
1665 
1666 int
virDomainXMLOptionRunMomentPostParse(virDomainXMLOption * xmlopt,virDomainMomentDef * def)1667 virDomainXMLOptionRunMomentPostParse(virDomainXMLOption *xmlopt,
1668                                      virDomainMomentDef *def)
1669 {
1670     if (!xmlopt->momentPostParse)
1671         return virDomainMomentDefPostParse(def);
1672     return xmlopt->momentPostParse(def);
1673 }
1674 
1675 
1676 void
virBlkioDeviceArrayClear(virBlkioDevice * devices,int ndevices)1677 virBlkioDeviceArrayClear(virBlkioDevice *devices,
1678                          int ndevices)
1679 {
1680     size_t i;
1681 
1682     for (i = 0; i < ndevices; i++)
1683         VIR_FREE(devices[i].path);
1684 }
1685 
1686 /**
1687  * virDomainBlkioDeviceParseXML
1688  *
1689  * this function parses a XML node:
1690  *
1691  *   <device>
1692  *     <path>/fully/qualified/device/path</path>
1693  *     <weight>weight</weight>
1694  *     <read_bytes_sec>bps</read_bytes_sec>
1695  *     <write_bytes_sec>bps</write_bytes_sec>
1696  *     <read_iops_sec>iops</read_iops_sec>
1697  *     <write_iops_sec>iops</write_iops_sec>
1698  *   </device>
1699  *
1700  * and fills a virBlkioDevice *struct.
1701  */
1702 static int
virDomainBlkioDeviceParseXML(xmlNodePtr root,xmlXPathContextPtr ctxt,virBlkioDevice * dev)1703 virDomainBlkioDeviceParseXML(xmlNodePtr root,
1704                              xmlXPathContextPtr ctxt,
1705                              virBlkioDevice *dev)
1706 {
1707     g_autofree char *path = NULL;
1708     g_autofree char *weight = NULL;
1709     g_autofree char *read_bytes_sec = NULL;
1710     g_autofree char *write_bytes_sec = NULL;
1711     g_autofree char *read_iops_sec = NULL;
1712     g_autofree char *write_iops_sec = NULL;
1713     VIR_XPATH_NODE_AUTORESTORE(ctxt)
1714 
1715     ctxt->node = root;
1716 
1717     /* To avoid the need for explicit cleanup on failure,
1718      * don't set dev->path until we're assured of
1719      * success. Until then, store it in an autofree pointer.
1720      */
1721     if (!(path = virXPathString("string(./path)", ctxt))) {
1722         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1723                        _("missing per-device path"));
1724         return -1;
1725     }
1726 
1727     if ((weight = virXPathString("string(./weight)", ctxt)) &&
1728         (virStrToLong_ui(weight, NULL, 10, &dev->weight) < 0)) {
1729         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1730                        _("could not parse weight %s"), weight);
1731         return -1;
1732     }
1733 
1734     if ((read_bytes_sec = virXPathString("string(./read_bytes_sec)", ctxt)) &&
1735         (virStrToLong_ull(read_bytes_sec, NULL, 10, &dev->rbps) < 0)) {
1736         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1737                        _("could not parse read bytes sec %s"),
1738                        read_bytes_sec);
1739         return -1;
1740     }
1741 
1742     if ((write_bytes_sec = virXPathString("string(./write_bytes_sec)", ctxt)) &&
1743         (virStrToLong_ull(write_bytes_sec, NULL, 10, &dev->wbps) < 0)) {
1744         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1745                        _("could not parse write bytes sec %s"),
1746                        write_bytes_sec);
1747         return -1;
1748     }
1749 
1750     if ((read_iops_sec = virXPathString("string(./read_iops_sec)", ctxt)) &&
1751         (virStrToLong_ui(read_iops_sec, NULL, 10, &dev->riops) < 0)) {
1752         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1753                        _("could not parse read iops sec %s"),
1754                        read_iops_sec);
1755         return -1;
1756     }
1757 
1758     if ((write_iops_sec = virXPathString("string(./write_iops_sec)", ctxt)) &&
1759         (virStrToLong_ui(write_iops_sec, NULL, 10, &dev->wiops) < 0)) {
1760         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1761                        _("could not parse write iops sec %s"),
1762                        write_iops_sec);
1763         return -1;
1764     }
1765 
1766     dev->path = g_steal_pointer(&path);
1767     return 0;
1768 }
1769 
1770 
1771 /**
1772  * virDomainDefCheckUnsupportedMemoryHotplug:
1773  * @def: domain definition
1774  *
1775  * Returns -1 if the domain definition would enable memory hotplug via the
1776  * <maxMemory> tunable and reports an error. Otherwise returns 0.
1777  */
1778 static int
virDomainDefCheckUnsupportedMemoryHotplug(virDomainDef * def)1779 virDomainDefCheckUnsupportedMemoryHotplug(virDomainDef *def)
1780 {
1781     /* memory hotplug tunables are not supported by this driver */
1782     if (virDomainDefHasMemoryHotplug(def)) {
1783         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1784                        _("memory hotplug tunables <maxMemory> are not "
1785                          "supported by this hypervisor driver"));
1786         return -1;
1787     }
1788 
1789     return 0;
1790 }
1791 
1792 
1793 /**
1794  * virDomainDeviceDefCheckUnsupportedMemoryDevice:
1795  * @dev: device definition
1796  *
1797  * Returns -1 if the device definition describes a memory device and reports an
1798  * error. Otherwise returns 0.
1799  */
1800 static int
virDomainDeviceDefCheckUnsupportedMemoryDevice(virDomainDeviceDef * dev)1801 virDomainDeviceDefCheckUnsupportedMemoryDevice(virDomainDeviceDef *dev)
1802 {
1803     /* This driver doesn't yet know how to handle memory devices */
1804     if (dev->type == VIR_DOMAIN_DEVICE_MEMORY) {
1805         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1806                        _("memory devices are not supported by this driver"));
1807         return -1;
1808     }
1809 
1810     return 0;
1811 }
1812 
1813 
virDomainObjTaint(virDomainObj * obj,virDomainTaintFlags taint)1814 bool virDomainObjTaint(virDomainObj *obj,
1815                        virDomainTaintFlags taint)
1816 {
1817     unsigned int flag = (1 << taint);
1818 
1819     if (obj->taint & flag)
1820         return false;
1821 
1822     obj->taint |= flag;
1823     return true;
1824 }
1825 
1826 
virDomainObjDeprecation(virDomainObj * obj,const char * msg)1827 void virDomainObjDeprecation(virDomainObj *obj,
1828                              const char *msg)
1829 {
1830     obj->deprecations = g_renew(char *, obj->deprecations,
1831                                 obj->ndeprecations + 1);
1832     obj->deprecations[obj->ndeprecations++] = g_strdup(msg);
1833 }
1834 
1835 
1836 static void
virDomainGraphicsAuthDefClear(virDomainGraphicsAuthDef * def)1837 virDomainGraphicsAuthDefClear(virDomainGraphicsAuthDef *def)
1838 {
1839     if (!def)
1840         return;
1841 
1842     VIR_FREE(def->passwd);
1843 
1844     /* Don't free def */
1845 }
1846 
1847 static void
virDomainGraphicsListenDefClear(virDomainGraphicsListenDef * def)1848 virDomainGraphicsListenDefClear(virDomainGraphicsListenDef *def)
1849 {
1850     if (!def)
1851         return;
1852 
1853     VIR_FREE(def->address);
1854     VIR_FREE(def->network);
1855     VIR_FREE(def->socket);
1856     return;
1857 }
1858 
1859 
virDomainGraphicsDefFree(virDomainGraphicsDef * def)1860 void virDomainGraphicsDefFree(virDomainGraphicsDef *def)
1861 {
1862     size_t i;
1863 
1864     if (!def)
1865         return;
1866 
1867     switch (def->type) {
1868     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
1869         g_free(def->data.vnc.keymap);
1870         virDomainGraphicsAuthDefClear(&def->data.vnc.auth);
1871         break;
1872 
1873     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
1874         g_free(def->data.sdl.display);
1875         g_free(def->data.sdl.xauth);
1876         break;
1877 
1878     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
1879         break;
1880 
1881     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
1882         g_free(def->data.desktop.display);
1883         break;
1884 
1885     case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
1886         g_free(def->data.spice.rendernode);
1887         g_free(def->data.spice.keymap);
1888         virDomainGraphicsAuthDefClear(&def->data.spice.auth);
1889         break;
1890 
1891     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
1892         g_free(def->data.egl_headless.rendernode);
1893         break;
1894 
1895     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
1896         break;
1897     }
1898 
1899     for (i = 0; i < def->nListens; i++)
1900         virDomainGraphicsListenDefClear(&def->listens[i]);
1901     g_free(def->listens);
1902 
1903     virObjectUnref(def->privateData);
1904     g_free(def);
1905 }
1906 
virDomainInputDefGetPath(virDomainInputDef * input)1907 const char *virDomainInputDefGetPath(virDomainInputDef *input)
1908 {
1909     switch ((virDomainInputType) input->type) {
1910     case VIR_DOMAIN_INPUT_TYPE_MOUSE:
1911     case VIR_DOMAIN_INPUT_TYPE_TABLET:
1912     case VIR_DOMAIN_INPUT_TYPE_KBD:
1913     case VIR_DOMAIN_INPUT_TYPE_LAST:
1914         return NULL;
1915 
1916     case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
1917     case VIR_DOMAIN_INPUT_TYPE_EVDEV:
1918         return input->source.evdev;
1919     }
1920     return NULL;
1921 }
1922 
virDomainInputDefFree(virDomainInputDef * def)1923 void virDomainInputDefFree(virDomainInputDef *def)
1924 {
1925     if (!def)
1926         return;
1927 
1928     virDomainDeviceInfoClear(&def->info);
1929     g_free(def->source.evdev);
1930     g_free(def->virtio);
1931     g_free(def);
1932 }
1933 
virDomainLeaseDefFree(virDomainLeaseDef * def)1934 void virDomainLeaseDefFree(virDomainLeaseDef *def)
1935 {
1936     if (!def)
1937         return;
1938 
1939     g_free(def->lockspace);
1940     g_free(def->key);
1941     g_free(def->path);
1942 
1943     g_free(def);
1944 }
1945 
1946 
1947 static virDomainVcpuDef *
virDomainVcpuDefNew(virDomainXMLOption * xmlopt)1948 virDomainVcpuDefNew(virDomainXMLOption *xmlopt)
1949 {
1950     virDomainVcpuDef *ret = NULL;
1951     g_autoptr(virObject) priv = NULL;
1952 
1953     if (xmlopt && xmlopt->privateData.vcpuNew &&
1954         !(priv = xmlopt->privateData.vcpuNew()))
1955         return NULL;
1956 
1957     ret = g_new0(virDomainVcpuDef, 1);
1958 
1959     ret->privateData = g_steal_pointer(&priv);
1960 
1961     return ret;
1962 }
1963 
1964 
1965 static void
virDomainVcpuDefFree(virDomainVcpuDef * info)1966 virDomainVcpuDefFree(virDomainVcpuDef *info)
1967 {
1968     if (!info)
1969         return;
1970 
1971     virBitmapFree(info->cpumask);
1972     virObjectUnref(info->privateData);
1973     g_free(info);
1974 }
1975 
1976 
1977 int
virDomainDefSetVcpusMax(virDomainDef * def,unsigned int maxvcpus,virDomainXMLOption * xmlopt)1978 virDomainDefSetVcpusMax(virDomainDef *def,
1979                         unsigned int maxvcpus,
1980                         virDomainXMLOption *xmlopt)
1981 {
1982     size_t oldmax = def->maxvcpus;
1983     size_t i;
1984 
1985     if (def->maxvcpus == maxvcpus)
1986         return 0;
1987 
1988     if (def->maxvcpus < maxvcpus) {
1989         VIR_EXPAND_N(def->vcpus, def->maxvcpus, maxvcpus - def->maxvcpus);
1990 
1991         for (i = oldmax; i < def->maxvcpus; i++) {
1992             if (!(def->vcpus[i] = virDomainVcpuDefNew(xmlopt)))
1993                 return -1;
1994         }
1995     } else {
1996         for (i = maxvcpus; i < def->maxvcpus; i++)
1997             virDomainVcpuDefFree(def->vcpus[i]);
1998 
1999         VIR_SHRINK_N(def->vcpus, def->maxvcpus, def->maxvcpus - maxvcpus);
2000     }
2001 
2002     return 0;
2003 }
2004 
2005 
2006 bool
virDomainDefHasVcpusOffline(const virDomainDef * def)2007 virDomainDefHasVcpusOffline(const virDomainDef *def)
2008 {
2009     size_t i;
2010 
2011     for (i = 0; i < def->maxvcpus; i++) {
2012         if (!def->vcpus[i]->online)
2013             return true;
2014     }
2015 
2016     return false;
2017 }
2018 
2019 
2020 unsigned int
virDomainDefGetVcpusMax(const virDomainDef * def)2021 virDomainDefGetVcpusMax(const virDomainDef *def)
2022 {
2023     return def->maxvcpus;
2024 }
2025 
2026 
2027 int
virDomainDefSetVcpus(virDomainDef * def,unsigned int vcpus)2028 virDomainDefSetVcpus(virDomainDef *def,
2029                      unsigned int vcpus)
2030 {
2031     size_t i;
2032 
2033     if (vcpus > def->maxvcpus) {
2034         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2035                        _("maximum vCPU count must not be less than current "
2036                          "vCPU count"));
2037         return -1;
2038     }
2039 
2040     for (i = 0; i < vcpus; i++)
2041         def->vcpus[i]->online = true;
2042 
2043     for (i = vcpus; i < def->maxvcpus; i++)
2044         def->vcpus[i]->online = false;
2045 
2046     return 0;
2047 }
2048 
2049 
2050 unsigned int
virDomainDefGetVcpus(const virDomainDef * def)2051 virDomainDefGetVcpus(const virDomainDef *def)
2052 {
2053     size_t i;
2054     unsigned int ret = 0;
2055 
2056     for (i = 0; i < def->maxvcpus; i++) {
2057         if (def->vcpus[i]->online)
2058             ret++;
2059     }
2060 
2061     return ret;
2062 }
2063 
2064 
2065 /**
2066  * virDomainDefGetOnlineVcpumap:
2067  * @def: domain definition
2068  *
2069  * Returns a bitmap representing state of individual vcpus.
2070  */
2071 virBitmap *
virDomainDefGetOnlineVcpumap(const virDomainDef * def)2072 virDomainDefGetOnlineVcpumap(const virDomainDef *def)
2073 {
2074     virBitmap *ret = virBitmapNew(def->maxvcpus);
2075     size_t i;
2076 
2077     for (i = 0; i < def->maxvcpus; i++) {
2078         if (def->vcpus[i]->online)
2079             ignore_value(virBitmapSetBit(ret, i));
2080     }
2081 
2082     return ret;
2083 }
2084 
2085 
2086 virDomainVcpuDef *
virDomainDefGetVcpu(virDomainDef * def,unsigned int vcpu)2087 virDomainDefGetVcpu(virDomainDef *def,
2088                     unsigned int vcpu)
2089 {
2090     if (vcpu >= def->maxvcpus)
2091         return NULL;
2092 
2093     return def->vcpus[vcpu];
2094 }
2095 
2096 
2097 static virDomainThreadSchedParam *
virDomainDefGetVcpuSched(virDomainDef * def,unsigned int vcpu)2098 virDomainDefGetVcpuSched(virDomainDef *def,
2099                          unsigned int vcpu)
2100 {
2101     virDomainVcpuDef *vcpuinfo;
2102 
2103     if (!(vcpuinfo = virDomainDefGetVcpu(def, vcpu))) {
2104         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2105                        _("vCPU '%u' is not present in domain definition"),
2106                        vcpu);
2107         return NULL;
2108     }
2109 
2110     return &vcpuinfo->sched;
2111 }
2112 
2113 
2114 /**
2115  * virDomainDefHasVcpuPin:
2116  * @def: domain definition
2117  *
2118  * This helper returns true if any of the domain's vcpus has cpu pinning set
2119  */
2120 static bool
virDomainDefHasVcpuPin(const virDomainDef * def)2121 virDomainDefHasVcpuPin(const virDomainDef *def)
2122 {
2123     size_t i;
2124 
2125     for (i = 0; i < def->maxvcpus; i++) {
2126         if (def->vcpus[i]->cpumask)
2127             return true;
2128     }
2129 
2130     return false;
2131 }
2132 
2133 
2134 /**
2135  * virDomainDefGetVcpuPinInfoHelper:
2136  * @def: domain definition
2137  * @maplen: length of one cpumap passed from caller (@cpumaps)
2138  * @ncpumaps: count of cpumaps of @maplen length in @cpumaps
2139  * @cpumaps: array of pinning information bitmaps to be filled
2140  * @hostcpus: default CPU pinning bitmap based on host CPUs
2141  * @autoCpuset: Cpu pinning bitmap used in case of automatic cpu pinning
2142  *
2143  * Fills the @cpumaps array as documented by the virDomainGetVcpuPinInfo API.
2144  * In case when automatic cpu pinning is supported, the bitmap should be passed
2145  * as @autoCpuset.
2146  *
2147  * Returns number of filled entries.
2148  */
2149 int
virDomainDefGetVcpuPinInfoHelper(virDomainDef * def,int maplen,int ncpumaps,unsigned char * cpumaps,virBitmap * hostcpus,virBitmap * autoCpuset)2150 virDomainDefGetVcpuPinInfoHelper(virDomainDef *def,
2151                                  int maplen,
2152                                  int ncpumaps,
2153                                  unsigned char *cpumaps,
2154                                  virBitmap *hostcpus,
2155                                  virBitmap *autoCpuset)
2156 {
2157     int maxvcpus = virDomainDefGetVcpusMax(def);
2158     size_t i;
2159 
2160     for (i = 0; i < maxvcpus && i < ncpumaps; i++) {
2161         virDomainVcpuDef *vcpu = virDomainDefGetVcpu(def, i);
2162         virBitmap *bitmap = NULL;
2163 
2164         if (vcpu && vcpu->cpumask)
2165             bitmap = vcpu->cpumask;
2166         else if (def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO &&
2167                  autoCpuset)
2168             bitmap = autoCpuset;
2169         else if (def->cpumask)
2170             bitmap = def->cpumask;
2171         else
2172             bitmap = hostcpus;
2173 
2174         virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, i), maplen);
2175     }
2176 
2177     return i;
2178 }
2179 
2180 
2181 /**
2182  * virDomainDeGetVcpusTopology:
2183  * @def: domain definition
2184  * @maxvcpus: optionally filled with number of vcpus the domain topology describes
2185  *
2186  * Calculates and validates that the vcpu topology is in sane bounds and
2187  * optionally returns the total number of vcpus described by given topology.
2188  *
2189  * Returns 0 on success, 1 if topology is not configured and -1 on error.
2190  */
2191 int
virDomainDefGetVcpusTopology(const virDomainDef * def,unsigned int * maxvcpus)2192 virDomainDefGetVcpusTopology(const virDomainDef *def,
2193                              unsigned int *maxvcpus)
2194 {
2195     unsigned long long tmp;
2196 
2197     if (!def->cpu || def->cpu->sockets == 0)
2198         return 1;
2199 
2200     tmp = def->cpu->sockets;
2201 
2202     /* multiplication of 32bit numbers fits into a 64bit variable */
2203     if ((tmp *= def->cpu->dies) > UINT_MAX ||
2204         (tmp *= def->cpu->cores) > UINT_MAX ||
2205         (tmp *= def->cpu->threads) > UINT_MAX) {
2206         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
2207                        _("cpu topology results in more than %u cpus"), UINT_MAX);
2208         return -1;
2209     }
2210 
2211     if (maxvcpus)
2212         *maxvcpus = tmp;
2213 
2214     return 0;
2215 }
2216 
2217 
2218 static virDomainDiskDef *
virDomainDiskDefNewSource(virDomainXMLOption * xmlopt,virStorageSource ** src)2219 virDomainDiskDefNewSource(virDomainXMLOption *xmlopt,
2220                           virStorageSource **src)
2221 {
2222     void *privateData = NULL;
2223     virDomainDiskDef *ret;
2224 
2225     if (xmlopt &&
2226         xmlopt->privateData.diskNew &&
2227         !(privateData = xmlopt->privateData.diskNew()))
2228         return NULL;
2229 
2230     ret = g_new0(virDomainDiskDef, 1);
2231     ret->src = g_steal_pointer(src);
2232     ret->privateData = privateData;
2233 
2234     return ret;
2235 }
2236 
2237 
2238 virDomainDiskDef *
virDomainDiskDefNew(virDomainXMLOption * xmlopt)2239 virDomainDiskDefNew(virDomainXMLOption *xmlopt)
2240 {
2241     g_autoptr(virStorageSource) src = virStorageSourceNew();
2242 
2243     return virDomainDiskDefNewSource(xmlopt, &src);
2244 }
2245 
2246 
2247 void
virDomainDiskDefFree(virDomainDiskDef * def)2248 virDomainDiskDefFree(virDomainDiskDef *def)
2249 {
2250     if (!def)
2251         return;
2252 
2253     virObjectUnref(def->src);
2254     g_free(def->serial);
2255     g_free(def->dst);
2256     virObjectUnref(def->mirror);
2257     g_free(def->wwn);
2258     g_free(def->driverName);
2259     g_free(def->vendor);
2260     g_free(def->product);
2261     g_free(def->domain_name);
2262     g_free(def->blkdeviotune.group_name);
2263     g_free(def->virtio);
2264     virDomainDeviceInfoClear(&def->info);
2265     virObjectUnref(def->privateData);
2266 
2267     g_free(def);
2268 }
2269 
2270 
2271 int
virDomainDiskGetType(virDomainDiskDef * def)2272 virDomainDiskGetType(virDomainDiskDef *def)
2273 {
2274     return def->src->type;
2275 }
2276 
2277 
2278 void
virDomainDiskSetType(virDomainDiskDef * def,int type)2279 virDomainDiskSetType(virDomainDiskDef *def, int type)
2280 {
2281     def->src->type = type;
2282 }
2283 
2284 
2285 const char *
virDomainDiskGetSource(virDomainDiskDef const * def)2286 virDomainDiskGetSource(virDomainDiskDef const *def)
2287 {
2288     return def->src->path;
2289 }
2290 
2291 
2292 void
virDomainDiskSetSource(virDomainDiskDef * def,const char * src)2293 virDomainDiskSetSource(virDomainDiskDef *def, const char *src)
2294 {
2295     char *tmp = g_strdup(src);
2296     g_free(def->src->path);
2297     def->src->path = tmp;
2298 }
2299 
2300 
2301 void
virDomainDiskEmptySource(virDomainDiskDef * def)2302 virDomainDiskEmptySource(virDomainDiskDef *def)
2303 {
2304     virStorageSource *src = def->src;
2305     bool readonly = src->readonly;
2306 
2307     virStorageSourceClear(src);
2308     src->type = VIR_STORAGE_TYPE_FILE;
2309     /* readonly property is necessary for CDROMs and thus can't be cleared */
2310     src->readonly = readonly;
2311 }
2312 
2313 
2314 const char *
virDomainDiskGetDriver(const virDomainDiskDef * def)2315 virDomainDiskGetDriver(const virDomainDiskDef *def)
2316 {
2317     return def->driverName;
2318 }
2319 
2320 
2321 void
virDomainDiskSetDriver(virDomainDiskDef * def,const char * name)2322 virDomainDiskSetDriver(virDomainDiskDef *def, const char *name)
2323 {
2324     char *tmp = g_strdup(name);
2325     g_free(def->driverName);
2326     def->driverName = tmp;
2327 }
2328 
2329 
2330 int
virDomainDiskGetFormat(virDomainDiskDef * def)2331 virDomainDiskGetFormat(virDomainDiskDef *def)
2332 {
2333     return def->src->format;
2334 }
2335 
2336 
2337 void
virDomainDiskSetFormat(virDomainDiskDef * def,int format)2338 virDomainDiskSetFormat(virDomainDiskDef *def, int format)
2339 {
2340     def->src->format = format;
2341 }
2342 
2343 
2344 virDomainControllerDef *
virDomainControllerDefNew(virDomainControllerType type)2345 virDomainControllerDefNew(virDomainControllerType type)
2346 {
2347     virDomainControllerDef *def;
2348 
2349     def = g_new0(virDomainControllerDef, 1);
2350 
2351     def->type = type;
2352 
2353     /* initialize anything that has a non-0 default */
2354     def->model = -1;
2355     def->idx = -1;
2356 
2357     switch ((virDomainControllerType) def->type) {
2358     case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
2359         def->opts.vioserial.ports = -1;
2360         def->opts.vioserial.vectors = -1;
2361         break;
2362     case VIR_DOMAIN_CONTROLLER_TYPE_USB:
2363         def->opts.usbopts.ports = -1;
2364         break;
2365     case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
2366         def->opts.pciopts.chassisNr = -1;
2367         def->opts.pciopts.chassis = -1;
2368         def->opts.pciopts.port = -1;
2369         def->opts.pciopts.busNr = -1;
2370         def->opts.pciopts.targetIndex = -1;
2371         def->opts.pciopts.numaNode = -1;
2372         break;
2373     case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
2374         def->opts.xenbusopts.maxGrantFrames = -1;
2375         def->opts.xenbusopts.maxEventChannels = -1;
2376         break;
2377     case VIR_DOMAIN_CONTROLLER_TYPE_IDE:
2378     case VIR_DOMAIN_CONTROLLER_TYPE_FDC:
2379     case VIR_DOMAIN_CONTROLLER_TYPE_SCSI:
2380     case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
2381     case VIR_DOMAIN_CONTROLLER_TYPE_CCID:
2382     case VIR_DOMAIN_CONTROLLER_TYPE_ISA:
2383     case VIR_DOMAIN_CONTROLLER_TYPE_LAST:
2384         break;
2385     }
2386 
2387     return def;
2388 }
2389 
2390 
virDomainControllerDefFree(virDomainControllerDef * def)2391 void virDomainControllerDefFree(virDomainControllerDef *def)
2392 {
2393     if (!def)
2394         return;
2395 
2396     virDomainDeviceInfoClear(&def->info);
2397     g_free(def->virtio);
2398 
2399     g_free(def);
2400 }
2401 
2402 
2403 /**
2404  * virDomainControllerIsPSeriesPHB:
2405  * @cont: controller
2406  *
2407  * Checks whether @cont is a PCI Host Bridge (PHB), a specific type
2408  * of PCI controller used by pSeries guests.
2409  *
2410  * Returns: true if @cont is a PHB, false otherwise.
2411  */
2412 bool
virDomainControllerIsPSeriesPHB(const virDomainControllerDef * cont)2413 virDomainControllerIsPSeriesPHB(const virDomainControllerDef *cont)
2414 {
2415     virDomainControllerPCIModelName name;
2416 
2417     /* PHBs are pci-root controllers */
2418     if (cont->type != VIR_DOMAIN_CONTROLLER_TYPE_PCI ||
2419         cont->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT) {
2420         return false;
2421     }
2422 
2423     name = cont->opts.pciopts.modelName;
2424 
2425     /* The actual device used for PHBs is spapr-pci-host-bridge */
2426     if (name != VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE)
2427         return false;
2428 
2429     return true;
2430 }
2431 
2432 
2433 virDomainFSDef *
virDomainFSDefNew(virDomainXMLOption * xmlopt)2434 virDomainFSDefNew(virDomainXMLOption *xmlopt)
2435 {
2436     virDomainFSDef *ret;
2437 
2438     ret = g_new0(virDomainFSDef, 1);
2439 
2440     ret->src = virStorageSourceNew();
2441 
2442     if (xmlopt &&
2443         xmlopt->privateData.fsNew &&
2444         !(ret->privateData = xmlopt->privateData.fsNew()))
2445         goto cleanup;
2446 
2447     return ret;
2448 
2449  cleanup:
2450     virDomainFSDefFree(ret);
2451     return NULL;
2452 
2453 }
2454 
virDomainFSDefFree(virDomainFSDef * def)2455 void virDomainFSDefFree(virDomainFSDef *def)
2456 {
2457     if (!def)
2458         return;
2459 
2460     virObjectUnref(def->src);
2461     g_free(def->dst);
2462     virDomainDeviceInfoClear(&def->info);
2463     g_free(def->virtio);
2464     virObjectUnref(def->privateData);
2465     g_free(def->binary);
2466     g_free(def->sock);
2467 
2468     g_free(def);
2469 }
2470 
2471 void
virDomainActualNetDefFree(virDomainActualNetDef * def)2472 virDomainActualNetDefFree(virDomainActualNetDef *def)
2473 {
2474     if (!def)
2475         return;
2476 
2477     switch (def->type) {
2478     case VIR_DOMAIN_NET_TYPE_BRIDGE:
2479     case VIR_DOMAIN_NET_TYPE_NETWORK:
2480         g_free(def->data.bridge.brname);
2481         break;
2482     case VIR_DOMAIN_NET_TYPE_DIRECT:
2483         g_free(def->data.direct.linkdev);
2484         break;
2485     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
2486         virDomainHostdevDefClear(&def->data.hostdev.def);
2487         break;
2488     case VIR_DOMAIN_NET_TYPE_USER:
2489     case VIR_DOMAIN_NET_TYPE_ETHERNET:
2490     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
2491     case VIR_DOMAIN_NET_TYPE_SERVER:
2492     case VIR_DOMAIN_NET_TYPE_CLIENT:
2493     case VIR_DOMAIN_NET_TYPE_MCAST:
2494     case VIR_DOMAIN_NET_TYPE_INTERNAL:
2495     case VIR_DOMAIN_NET_TYPE_UDP:
2496     case VIR_DOMAIN_NET_TYPE_VDPA:
2497     case VIR_DOMAIN_NET_TYPE_LAST:
2498         break;
2499     }
2500 
2501     g_free(def->virtPortProfile);
2502     virNetDevBandwidthFree(def->bandwidth);
2503     virNetDevVlanClear(&def->vlan);
2504     g_free(def);
2505 }
2506 
2507 
2508 virDomainVsockDef *
virDomainVsockDefNew(virDomainXMLOption * xmlopt)2509 virDomainVsockDefNew(virDomainXMLOption *xmlopt)
2510 {
2511     virDomainVsockDef *ret = NULL;
2512     virDomainVsockDef *vsock;
2513 
2514     vsock = g_new0(virDomainVsockDef, 1);
2515 
2516     if (xmlopt &&
2517         xmlopt->privateData.vsockNew &&
2518         !(vsock->privateData = xmlopt->privateData.vsockNew()))
2519         goto cleanup;
2520 
2521     ret = g_steal_pointer(&vsock);
2522  cleanup:
2523     virDomainVsockDefFree(vsock);
2524     return ret;
2525 }
2526 
2527 
2528 void
virDomainVsockDefFree(virDomainVsockDef * vsock)2529 virDomainVsockDefFree(virDomainVsockDef *vsock)
2530 {
2531     if (!vsock)
2532         return;
2533 
2534     virObjectUnref(vsock->privateData);
2535     virDomainDeviceInfoClear(&vsock->info);
2536     g_free(vsock->virtio);
2537     g_free(vsock);
2538 }
2539 
2540 
2541 virDomainIOMMUDef *
virDomainIOMMUDefNew(void)2542 virDomainIOMMUDefNew(void)
2543 {
2544     g_autoptr(virDomainIOMMUDef) iommu = NULL;
2545 
2546     iommu = g_new0(virDomainIOMMUDef, 1);
2547 
2548     return g_steal_pointer(&iommu);
2549 }
2550 
2551 
2552 void
virDomainIOMMUDefFree(virDomainIOMMUDef * iommu)2553 virDomainIOMMUDefFree(virDomainIOMMUDef *iommu)
2554 {
2555     if (!iommu)
2556         return;
2557 
2558     g_free(iommu);
2559 }
2560 
2561 
2562 void
virDomainNetTeamingInfoFree(virDomainNetTeamingInfo * teaming)2563 virDomainNetTeamingInfoFree(virDomainNetTeamingInfo *teaming)
2564 {
2565     if (!teaming)
2566         return;
2567 
2568     g_free(teaming->persistent);
2569     g_free(teaming);
2570 }
2571 
2572 
2573 void
virDomainNetDefFree(virDomainNetDef * def)2574 virDomainNetDefFree(virDomainNetDef *def)
2575 {
2576     if (!def)
2577         return;
2578 
2579     g_free(def->modelstr);
2580 
2581     switch (def->type) {
2582     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
2583         virObjectUnref(def->data.vhostuser);
2584         break;
2585 
2586     case VIR_DOMAIN_NET_TYPE_VDPA:
2587         g_free(def->data.vdpa.devicepath);
2588         break;
2589 
2590     case VIR_DOMAIN_NET_TYPE_SERVER:
2591     case VIR_DOMAIN_NET_TYPE_CLIENT:
2592     case VIR_DOMAIN_NET_TYPE_MCAST:
2593     case VIR_DOMAIN_NET_TYPE_UDP:
2594         g_free(def->data.socket.address);
2595         g_free(def->data.socket.localaddr);
2596         break;
2597 
2598     case VIR_DOMAIN_NET_TYPE_NETWORK:
2599         g_free(def->data.network.name);
2600         g_free(def->data.network.portgroup);
2601         virDomainActualNetDefFree(def->data.network.actual);
2602         break;
2603 
2604     case VIR_DOMAIN_NET_TYPE_BRIDGE:
2605         g_free(def->data.bridge.brname);
2606         break;
2607 
2608     case VIR_DOMAIN_NET_TYPE_INTERNAL:
2609         g_free(def->data.internal.name);
2610         break;
2611 
2612     case VIR_DOMAIN_NET_TYPE_DIRECT:
2613         g_free(def->data.direct.linkdev);
2614         break;
2615 
2616     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
2617         virDomainHostdevDefClear(&def->data.hostdev.def);
2618         break;
2619 
2620     case VIR_DOMAIN_NET_TYPE_ETHERNET:
2621     case VIR_DOMAIN_NET_TYPE_USER:
2622     case VIR_DOMAIN_NET_TYPE_LAST:
2623         break;
2624     }
2625 
2626     g_free(def->backend.tap);
2627     g_free(def->backend.vhost);
2628     virDomainNetTeamingInfoFree(def->teaming);
2629     g_free(def->virtPortProfile);
2630     g_free(def->script);
2631     g_free(def->downscript);
2632     g_free(def->domain_name);
2633     g_free(def->ifname);
2634     g_free(def->ifname_guest);
2635     g_free(def->ifname_guest_actual);
2636     g_free(def->virtio);
2637     g_free(def->coalesce);
2638 
2639     virNetDevIPInfoClear(&def->guestIP);
2640     virNetDevIPInfoClear(&def->hostIP);
2641     virDomainDeviceInfoClear(&def->info);
2642 
2643     g_free(def->filter);
2644     virHashFree(def->filterparams);
2645 
2646     virNetDevBandwidthFree(def->bandwidth);
2647     virNetDevVlanClear(&def->vlan);
2648 
2649     virObjectUnref(def->privateData);
2650     g_free(def);
2651 }
2652 
2653 
2654 const char *
virDomainChrSourceDefGetPath(virDomainChrSourceDef * chr)2655 virDomainChrSourceDefGetPath(virDomainChrSourceDef *chr)
2656 {
2657     if (!chr)
2658         return NULL;
2659 
2660     switch ((virDomainChrType) chr->type) {
2661     case VIR_DOMAIN_CHR_TYPE_PTY:
2662     case VIR_DOMAIN_CHR_TYPE_DEV:
2663     case VIR_DOMAIN_CHR_TYPE_FILE:
2664     case VIR_DOMAIN_CHR_TYPE_PIPE:
2665     case VIR_DOMAIN_CHR_TYPE_NMDM:
2666         return chr->data.file.path;
2667 
2668     case VIR_DOMAIN_CHR_TYPE_UNIX:
2669         return chr->data.nix.path;
2670 
2671     case VIR_DOMAIN_CHR_TYPE_TCP:
2672     case VIR_DOMAIN_CHR_TYPE_UDP:
2673     case VIR_DOMAIN_CHR_TYPE_NULL:
2674     case VIR_DOMAIN_CHR_TYPE_VC:
2675     case VIR_DOMAIN_CHR_TYPE_STDIO:
2676     case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
2677     case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
2678     case VIR_DOMAIN_CHR_TYPE_LAST:
2679         return NULL;
2680     }
2681 
2682     return NULL;
2683 }
2684 
2685 
2686 void ATTRIBUTE_NONNULL(1)
virDomainChrSourceDefClear(virDomainChrSourceDef * def)2687 virDomainChrSourceDefClear(virDomainChrSourceDef *def)
2688 {
2689     switch (def->type) {
2690     case VIR_DOMAIN_CHR_TYPE_PTY:
2691     case VIR_DOMAIN_CHR_TYPE_DEV:
2692     case VIR_DOMAIN_CHR_TYPE_FILE:
2693     case VIR_DOMAIN_CHR_TYPE_PIPE:
2694         VIR_FREE(def->data.file.path);
2695         break;
2696 
2697     case VIR_DOMAIN_CHR_TYPE_NMDM:
2698         VIR_FREE(def->data.nmdm.master);
2699         VIR_FREE(def->data.nmdm.slave);
2700         break;
2701 
2702     case VIR_DOMAIN_CHR_TYPE_UDP:
2703         VIR_FREE(def->data.udp.bindHost);
2704         VIR_FREE(def->data.udp.bindService);
2705         VIR_FREE(def->data.udp.connectHost);
2706         VIR_FREE(def->data.udp.connectService);
2707         break;
2708 
2709     case VIR_DOMAIN_CHR_TYPE_TCP:
2710         VIR_FREE(def->data.tcp.host);
2711         VIR_FREE(def->data.tcp.service);
2712         break;
2713 
2714     case VIR_DOMAIN_CHR_TYPE_UNIX:
2715         VIR_FREE(def->data.nix.path);
2716         break;
2717 
2718     case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
2719         VIR_FREE(def->data.spiceport.channel);
2720         break;
2721     }
2722 
2723     VIR_FREE(def->logfile);
2724 }
2725 
2726 /* Deep copies the contents of src into dest.  Return -1 and report
2727  * error on failure.  */
2728 int
virDomainChrSourceDefCopy(virDomainChrSourceDef * dest,virDomainChrSourceDef * src)2729 virDomainChrSourceDefCopy(virDomainChrSourceDef *dest,
2730                           virDomainChrSourceDef *src)
2731 {
2732     if (!dest || !src)
2733         return -1;
2734 
2735     virDomainChrSourceDefClear(dest);
2736 
2737     switch (src->type) {
2738     case VIR_DOMAIN_CHR_TYPE_FILE:
2739     case VIR_DOMAIN_CHR_TYPE_PTY:
2740     case VIR_DOMAIN_CHR_TYPE_DEV:
2741     case VIR_DOMAIN_CHR_TYPE_PIPE:
2742         if (src->type == VIR_DOMAIN_CHR_TYPE_FILE)
2743             dest->data.file.append = src->data.file.append;
2744         dest->data.file.path = g_strdup(src->data.file.path);
2745         break;
2746 
2747     case VIR_DOMAIN_CHR_TYPE_UDP:
2748         dest->data.udp.bindHost = g_strdup(src->data.udp.bindHost);
2749         dest->data.udp.bindService = g_strdup(src->data.udp.bindService);
2750         dest->data.udp.connectHost = g_strdup(src->data.udp.connectHost);
2751         dest->data.udp.connectService = g_strdup(src->data.udp.connectService);
2752         break;
2753 
2754     case VIR_DOMAIN_CHR_TYPE_TCP:
2755         dest->data.tcp.host = g_strdup(src->data.tcp.host);
2756         dest->data.tcp.service = g_strdup(src->data.tcp.service);
2757 
2758         dest->data.tcp.haveTLS = src->data.tcp.haveTLS;
2759         dest->data.tcp.tlsFromConfig = src->data.tcp.tlsFromConfig;
2760 
2761         dest->data.tcp.reconnect.enabled = src->data.tcp.reconnect.enabled;
2762         dest->data.tcp.reconnect.timeout = src->data.tcp.reconnect.timeout;
2763         break;
2764 
2765     case VIR_DOMAIN_CHR_TYPE_UNIX:
2766         dest->data.nix.path = g_strdup(src->data.nix.path);
2767 
2768         dest->data.nix.reconnect.enabled = src->data.nix.reconnect.enabled;
2769         dest->data.nix.reconnect.timeout = src->data.nix.reconnect.timeout;
2770         break;
2771 
2772     case VIR_DOMAIN_CHR_TYPE_NMDM:
2773         dest->data.nmdm.master = g_strdup(src->data.nmdm.master);
2774         dest->data.nmdm.slave = g_strdup(src->data.nmdm.slave);
2775 
2776         break;
2777     }
2778 
2779     dest->type = src->type;
2780 
2781     return 0;
2782 }
2783 
2784 static void
virDomainChrSourceDefDispose(void * obj)2785 virDomainChrSourceDefDispose(void *obj)
2786 {
2787     virDomainChrSourceDef *def = obj;
2788     size_t i;
2789 
2790     virDomainChrSourceDefClear(def);
2791     virObjectUnref(def->privateData);
2792 
2793     if (def->seclabels) {
2794         for (i = 0; i < def->nseclabels; i++)
2795             virSecurityDeviceLabelDefFree(def->seclabels[i]);
2796         g_free(def->seclabels);
2797     }
2798 }
2799 
2800 
2801 /* virDomainChrSourceDefIsEqual:
2802  * @src: Source
2803  * @tgt: Target
2804  *
2805  * Compares source and target if they contain
2806  * the same information.
2807  */
2808 static bool
virDomainChrSourceDefIsEqual(const virDomainChrSourceDef * src,const virDomainChrSourceDef * tgt)2809 virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src,
2810                              const virDomainChrSourceDef *tgt)
2811 {
2812     if (tgt->type != src->type)
2813         return false;
2814 
2815     switch ((virDomainChrType)src->type) {
2816     case VIR_DOMAIN_CHR_TYPE_FILE:
2817         return src->data.file.append == tgt->data.file.append &&
2818             STREQ_NULLABLE(src->data.file.path, tgt->data.file.path);
2819         break;
2820     case VIR_DOMAIN_CHR_TYPE_PTY:
2821     case VIR_DOMAIN_CHR_TYPE_DEV:
2822     case VIR_DOMAIN_CHR_TYPE_PIPE:
2823         return STREQ_NULLABLE(src->data.file.path, tgt->data.file.path);
2824     case VIR_DOMAIN_CHR_TYPE_NMDM:
2825         return STREQ_NULLABLE(src->data.nmdm.master, tgt->data.nmdm.master) &&
2826             STREQ_NULLABLE(src->data.nmdm.slave, tgt->data.nmdm.slave);
2827         break;
2828     case VIR_DOMAIN_CHR_TYPE_UDP:
2829         return STREQ_NULLABLE(src->data.udp.bindHost, tgt->data.udp.bindHost) &&
2830             STREQ_NULLABLE(src->data.udp.bindService, tgt->data.udp.bindService) &&
2831             STREQ_NULLABLE(src->data.udp.connectHost, tgt->data.udp.connectHost) &&
2832             STREQ_NULLABLE(src->data.udp.connectService, tgt->data.udp.connectService);
2833         break;
2834     case VIR_DOMAIN_CHR_TYPE_TCP:
2835         return src->data.tcp.listen == tgt->data.tcp.listen &&
2836             src->data.tcp.protocol == tgt->data.tcp.protocol &&
2837             STREQ_NULLABLE(src->data.tcp.host, tgt->data.tcp.host) &&
2838             STREQ_NULLABLE(src->data.tcp.service, tgt->data.tcp.service) &&
2839             src->data.tcp.reconnect.enabled == tgt->data.tcp.reconnect.enabled &&
2840             src->data.tcp.reconnect.timeout == tgt->data.tcp.reconnect.timeout;
2841         break;
2842     case VIR_DOMAIN_CHR_TYPE_UNIX:
2843         return src->data.nix.listen == tgt->data.nix.listen &&
2844             STREQ_NULLABLE(src->data.nix.path, tgt->data.nix.path) &&
2845             src->data.nix.reconnect.enabled == tgt->data.nix.reconnect.enabled &&
2846             src->data.nix.reconnect.timeout == tgt->data.nix.reconnect.timeout;
2847         break;
2848 
2849     case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
2850         return STREQ_NULLABLE(src->data.spiceport.channel,
2851                               tgt->data.spiceport.channel);
2852         break;
2853 
2854     case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
2855         return src->data.spicevmc == tgt->data.spicevmc;
2856 
2857     case VIR_DOMAIN_CHR_TYPE_NULL:
2858     case VIR_DOMAIN_CHR_TYPE_VC:
2859     case VIR_DOMAIN_CHR_TYPE_STDIO:
2860     case VIR_DOMAIN_CHR_TYPE_LAST:
2861         break;
2862     }
2863 
2864     return true;
2865 }
2866 
virDomainChrDefFree(virDomainChrDef * def)2867 void virDomainChrDefFree(virDomainChrDef *def)
2868 {
2869     if (!def)
2870         return;
2871 
2872     switch (def->deviceType) {
2873     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
2874         switch (def->targetType) {
2875         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
2876             g_free(def->target.addr);
2877             break;
2878 
2879         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
2880         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
2881             g_free(def->target.name);
2882             break;
2883         }
2884         break;
2885 
2886     default:
2887         break;
2888     }
2889 
2890     virObjectUnref(def->source);
2891     virDomainDeviceInfoClear(&def->info);
2892 
2893     g_free(def);
2894 }
2895 
virDomainSmartcardDefFree(virDomainSmartcardDef * def)2896 void virDomainSmartcardDefFree(virDomainSmartcardDef *def)
2897 {
2898     size_t i;
2899     if (!def)
2900         return;
2901 
2902     switch (def->type) {
2903     case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
2904         break;
2905 
2906     case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
2907         for (i = 0; i < VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES; i++)
2908             g_free(def->data.cert.file[i]);
2909         g_free(def->data.cert.database);
2910         break;
2911 
2912     case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
2913         virObjectUnref(def->data.passthru);
2914         break;
2915 
2916     case VIR_DOMAIN_SMARTCARD_TYPE_LAST:
2917     default:
2918         break;
2919     }
2920 
2921     virDomainDeviceInfoClear(&def->info);
2922 
2923     g_free(def);
2924 }
2925 
virDomainSoundCodecDefFree(virDomainSoundCodecDef * def)2926 void virDomainSoundCodecDefFree(virDomainSoundCodecDef *def)
2927 {
2928     if (!def)
2929         return;
2930 
2931     g_free(def);
2932 }
2933 
virDomainSoundDefFree(virDomainSoundDef * def)2934 void virDomainSoundDefFree(virDomainSoundDef *def)
2935 {
2936     size_t i;
2937 
2938     if (!def)
2939         return;
2940 
2941     virDomainDeviceInfoClear(&def->info);
2942 
2943     for (i = 0; i < def->ncodecs; i++)
2944         virDomainSoundCodecDefFree(def->codecs[i]);
2945     g_free(def->codecs);
2946 
2947     g_free(def);
2948 }
2949 
2950 static void
virDomainAudioIOALSAFree(virDomainAudioIOALSA * def)2951 virDomainAudioIOALSAFree(virDomainAudioIOALSA *def)
2952 {
2953     g_free(def->dev);
2954 }
2955 
2956 static void
virDomainAudioIOJackFree(virDomainAudioIOJack * def)2957 virDomainAudioIOJackFree(virDomainAudioIOJack *def)
2958 {
2959     g_free(def->serverName);
2960     g_free(def->clientName);
2961     g_free(def->connectPorts);
2962 }
2963 
2964 static void
virDomainAudioIOOSSFree(virDomainAudioIOOSS * def)2965 virDomainAudioIOOSSFree(virDomainAudioIOOSS *def)
2966 {
2967     g_free(def->dev);
2968 }
2969 
2970 static void
virDomainAudioIOPulseAudioFree(virDomainAudioIOPulseAudio * def)2971 virDomainAudioIOPulseAudioFree(virDomainAudioIOPulseAudio *def)
2972 {
2973     g_free(def->name);
2974     g_free(def->streamName);
2975 }
2976 
2977 void
virDomainAudioDefFree(virDomainAudioDef * def)2978 virDomainAudioDefFree(virDomainAudioDef *def)
2979 {
2980     if (!def)
2981         return;
2982 
2983     switch (def->type) {
2984     case VIR_DOMAIN_AUDIO_TYPE_NONE:
2985         break;
2986 
2987     case VIR_DOMAIN_AUDIO_TYPE_ALSA:
2988         virDomainAudioIOALSAFree(&def->backend.alsa.input);
2989         virDomainAudioIOALSAFree(&def->backend.alsa.output);
2990         break;
2991 
2992     case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
2993         break;
2994 
2995     case VIR_DOMAIN_AUDIO_TYPE_JACK:
2996         virDomainAudioIOJackFree(&def->backend.jack.input);
2997         virDomainAudioIOJackFree(&def->backend.jack.output);
2998         break;
2999 
3000     case VIR_DOMAIN_AUDIO_TYPE_OSS:
3001         virDomainAudioIOOSSFree(&def->backend.oss.input);
3002         virDomainAudioIOOSSFree(&def->backend.oss.output);
3003         break;
3004 
3005     case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
3006         virDomainAudioIOPulseAudioFree(&def->backend.pulseaudio.input);
3007         virDomainAudioIOPulseAudioFree(&def->backend.pulseaudio.output);
3008         g_free(def->backend.pulseaudio.serverName);
3009         break;
3010 
3011     case VIR_DOMAIN_AUDIO_TYPE_SDL:
3012         break;
3013 
3014     case VIR_DOMAIN_AUDIO_TYPE_SPICE:
3015         break;
3016 
3017     case VIR_DOMAIN_AUDIO_TYPE_FILE:
3018         g_free(def->backend.file.path);
3019         break;
3020 
3021     case VIR_DOMAIN_AUDIO_TYPE_LAST:
3022         break;
3023     }
3024 
3025     g_free(def);
3026 }
3027 
3028 virDomainSoundDef *
virDomainSoundDefRemove(virDomainDef * def,size_t idx)3029 virDomainSoundDefRemove(virDomainDef *def, size_t idx)
3030 {
3031     virDomainSoundDef *ret = def->sounds[idx];
3032     VIR_DELETE_ELEMENT(def->sounds, idx, def->nsounds);
3033     return ret;
3034 }
3035 
virDomainMemballoonDefFree(virDomainMemballoonDef * def)3036 void virDomainMemballoonDefFree(virDomainMemballoonDef *def)
3037 {
3038     if (!def)
3039         return;
3040 
3041     virDomainDeviceInfoClear(&def->info);
3042     g_free(def->virtio);
3043 
3044     g_free(def);
3045 }
3046 
virDomainNVRAMDefFree(virDomainNVRAMDef * def)3047 void virDomainNVRAMDefFree(virDomainNVRAMDef *def)
3048 {
3049     if (!def)
3050         return;
3051 
3052     virDomainDeviceInfoClear(&def->info);
3053 
3054     g_free(def);
3055 }
3056 
virDomainWatchdogDefFree(virDomainWatchdogDef * def)3057 void virDomainWatchdogDefFree(virDomainWatchdogDef *def)
3058 {
3059     if (!def)
3060         return;
3061 
3062     virDomainDeviceInfoClear(&def->info);
3063 
3064     g_free(def);
3065 }
3066 
virDomainShmemDefFree(virDomainShmemDef * def)3067 void virDomainShmemDefFree(virDomainShmemDef *def)
3068 {
3069     if (!def)
3070         return;
3071 
3072     virDomainDeviceInfoClear(&def->info);
3073     virObjectUnref(def->server.chr);
3074     g_free(def->name);
3075     g_free(def);
3076 }
3077 
3078 
3079 virDomainVideoDef *
virDomainVideoDefNew(virDomainXMLOption * xmlopt)3080 virDomainVideoDefNew(virDomainXMLOption *xmlopt)
3081 {
3082     virDomainVideoDef *def;
3083 
3084     def = g_new0(virDomainVideoDef, 1);
3085 
3086     if (xmlopt && xmlopt->privateData.videoNew &&
3087         !(def->privateData = xmlopt->privateData.videoNew())) {
3088         VIR_FREE(def);
3089         return NULL;
3090     }
3091 
3092     def->heads = 1;
3093     return def;
3094 }
3095 
3096 
3097 void
virDomainVideoDefClear(virDomainVideoDef * def)3098 virDomainVideoDefClear(virDomainVideoDef *def)
3099 {
3100     if (!def)
3101         return;
3102 
3103     virDomainDeviceInfoClear(&def->info);
3104 
3105     if (def->accel)
3106         VIR_FREE(def->accel->rendernode);
3107     VIR_FREE(def->accel);
3108     VIR_FREE(def->res);
3109     VIR_FREE(def->virtio);
3110     if (def->driver)
3111         VIR_FREE(def->driver->vhost_user_binary);
3112     VIR_FREE(def->driver);
3113     virObjectUnref(def->privateData);
3114 
3115     memset(def, 0, sizeof(*def));
3116 }
3117 
3118 
virDomainVideoDefFree(virDomainVideoDef * def)3119 void virDomainVideoDefFree(virDomainVideoDef *def)
3120 {
3121     if (!def)
3122         return;
3123 
3124     virDomainVideoDefClear(def);
3125     g_free(def);
3126 }
3127 
3128 
3129 virDomainHostdevDef *
virDomainHostdevDefNew(void)3130 virDomainHostdevDefNew(void)
3131 {
3132     virDomainHostdevDef *def;
3133 
3134     def = g_new0(virDomainHostdevDef, 1);
3135 
3136     def->info = g_new0(virDomainDeviceInfo, 1);
3137 
3138     return def;
3139 }
3140 
3141 
3142 static void
virDomainHostdevSubsysSCSIClear(virDomainHostdevSubsysSCSI * scsisrc)3143 virDomainHostdevSubsysSCSIClear(virDomainHostdevSubsysSCSI *scsisrc)
3144 {
3145     if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
3146         virObjectUnref(scsisrc->u.iscsi.src);
3147         scsisrc->u.iscsi.src = NULL;
3148     } else {
3149         VIR_FREE(scsisrc->u.host.adapter);
3150         virObjectUnref(scsisrc->u.host.src);
3151         scsisrc->u.host.src = NULL;
3152     }
3153 }
3154 
3155 
virDomainHostdevDefClear(virDomainHostdevDef * def)3156 void virDomainHostdevDefClear(virDomainHostdevDef *def)
3157 {
3158     if (!def)
3159         return;
3160 
3161     /* Free all resources in the hostdevdef. Currently the only
3162      * such resource is the virDomainDeviceInfo.
3163      */
3164 
3165     /* If there is a parentnet device object, it will handle freeing
3166      * def->info.
3167      */
3168     if (!def->parentnet)
3169         virDomainDeviceInfoFree(def->info);
3170 
3171     virDomainNetTeamingInfoFree(def->teaming);
3172 
3173     switch (def->mode) {
3174     case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
3175         switch ((virDomainHostdevCapsType) def->source.caps.type) {
3176         case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
3177             VIR_FREE(def->source.caps.u.storage.block);
3178             break;
3179         case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
3180             VIR_FREE(def->source.caps.u.misc.chardev);
3181             break;
3182         case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
3183             VIR_FREE(def->source.caps.u.net.ifname);
3184             virNetDevIPInfoClear(&def->source.caps.u.net.ip);
3185             break;
3186         case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST:
3187             break;
3188         }
3189         break;
3190     case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
3191         switch ((virDomainHostdevSubsysType) def->source.subsys.type) {
3192         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
3193             virDomainHostdevSubsysSCSIClear(&def->source.subsys.u.scsi);
3194             break;
3195         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
3196             VIR_FREE(def->source.subsys.u.scsi_host.wwpn);
3197             break;
3198         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
3199         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
3200         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
3201         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
3202             break;
3203         }
3204         break;
3205     }
3206 }
3207 
virDomainTPMDefFree(virDomainTPMDef * def)3208 void virDomainTPMDefFree(virDomainTPMDef *def)
3209 {
3210     if (!def)
3211         return;
3212 
3213     switch (def->type) {
3214     case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
3215         virObjectUnref(def->data.passthrough.source);
3216         break;
3217     case VIR_DOMAIN_TPM_TYPE_EMULATOR:
3218         virObjectUnref(def->data.emulator.source);
3219         g_free(def->data.emulator.storagepath);
3220         g_free(def->data.emulator.logfile);
3221         break;
3222     case VIR_DOMAIN_TPM_TYPE_LAST:
3223         break;
3224     }
3225 
3226     virDomainDeviceInfoClear(&def->info);
3227     g_free(def);
3228 }
3229 
virDomainHostdevDefFree(virDomainHostdevDef * def)3230 void virDomainHostdevDefFree(virDomainHostdevDef *def)
3231 {
3232     if (!def)
3233         return;
3234 
3235     /* free all subordinate objects */
3236     virDomainHostdevDefClear(def);
3237 
3238     /* If there is a parentnet device object, it will handle freeing
3239      * the memory.
3240      */
3241     if (!def->parentnet)
3242         g_free(def);
3243 }
3244 
virDomainHubDefFree(virDomainHubDef * def)3245 void virDomainHubDefFree(virDomainHubDef *def)
3246 {
3247     if (!def)
3248         return;
3249 
3250     virDomainDeviceInfoClear(&def->info);
3251     g_free(def);
3252 }
3253 
virDomainRedirdevDefFree(virDomainRedirdevDef * def)3254 void virDomainRedirdevDefFree(virDomainRedirdevDef *def)
3255 {
3256     if (!def)
3257         return;
3258 
3259     virObjectUnref(def->source);
3260     virDomainDeviceInfoClear(&def->info);
3261 
3262     g_free(def);
3263 }
3264 
virDomainRedirFilterDefFree(virDomainRedirFilterDef * def)3265 void virDomainRedirFilterDefFree(virDomainRedirFilterDef *def)
3266 {
3267     size_t i;
3268 
3269     if (!def)
3270         return;
3271 
3272     for (i = 0; i < def->nusbdevs; i++)
3273         g_free(def->usbdevs[i]);
3274 
3275     g_free(def->usbdevs);
3276     g_free(def);
3277 }
3278 
virDomainMemoryDefFree(virDomainMemoryDef * def)3279 void virDomainMemoryDefFree(virDomainMemoryDef *def)
3280 {
3281     if (!def)
3282         return;
3283 
3284     g_free(def->nvdimmPath);
3285     virBitmapFree(def->sourceNodes);
3286     g_free(def->uuid);
3287     virDomainDeviceInfoClear(&def->info);
3288     g_free(def);
3289 }
3290 
virDomainDeviceDefFree(virDomainDeviceDef * def)3291 void virDomainDeviceDefFree(virDomainDeviceDef *def)
3292 {
3293     if (!def)
3294         return;
3295 
3296     switch ((virDomainDeviceType) def->type) {
3297     case VIR_DOMAIN_DEVICE_DISK:
3298         virDomainDiskDefFree(def->data.disk);
3299         break;
3300     case VIR_DOMAIN_DEVICE_LEASE:
3301         virDomainLeaseDefFree(def->data.lease);
3302         break;
3303     case VIR_DOMAIN_DEVICE_NET:
3304         virDomainNetDefFree(def->data.net);
3305         break;
3306     case VIR_DOMAIN_DEVICE_INPUT:
3307         virDomainInputDefFree(def->data.input);
3308         break;
3309     case VIR_DOMAIN_DEVICE_SOUND:
3310         virDomainSoundDefFree(def->data.sound);
3311         break;
3312     case VIR_DOMAIN_DEVICE_VIDEO:
3313         virDomainVideoDefFree(def->data.video);
3314         break;
3315     case VIR_DOMAIN_DEVICE_HOSTDEV:
3316         virDomainHostdevDefFree(def->data.hostdev);
3317         break;
3318     case VIR_DOMAIN_DEVICE_WATCHDOG:
3319         virDomainWatchdogDefFree(def->data.watchdog);
3320         break;
3321     case VIR_DOMAIN_DEVICE_CONTROLLER:
3322         virDomainControllerDefFree(def->data.controller);
3323         break;
3324     case VIR_DOMAIN_DEVICE_GRAPHICS:
3325         virDomainGraphicsDefFree(def->data.graphics);
3326         break;
3327     case VIR_DOMAIN_DEVICE_HUB:
3328         virDomainHubDefFree(def->data.hub);
3329         break;
3330     case VIR_DOMAIN_DEVICE_REDIRDEV:
3331         virDomainRedirdevDefFree(def->data.redirdev);
3332         break;
3333     case VIR_DOMAIN_DEVICE_RNG:
3334         virDomainRNGDefFree(def->data.rng);
3335         break;
3336     case VIR_DOMAIN_DEVICE_CHR:
3337         virDomainChrDefFree(def->data.chr);
3338         break;
3339     case VIR_DOMAIN_DEVICE_FS:
3340         virDomainFSDefFree(def->data.fs);
3341         break;
3342     case VIR_DOMAIN_DEVICE_SMARTCARD:
3343         virDomainSmartcardDefFree(def->data.smartcard);
3344         break;
3345     case VIR_DOMAIN_DEVICE_MEMBALLOON:
3346         virDomainMemballoonDefFree(def->data.memballoon);
3347         break;
3348     case VIR_DOMAIN_DEVICE_NVRAM:
3349         virDomainNVRAMDefFree(def->data.nvram);
3350         break;
3351     case VIR_DOMAIN_DEVICE_SHMEM:
3352         virDomainShmemDefFree(def->data.shmem);
3353         break;
3354     case VIR_DOMAIN_DEVICE_TPM:
3355         virDomainTPMDefFree(def->data.tpm);
3356         break;
3357     case VIR_DOMAIN_DEVICE_PANIC:
3358         virDomainPanicDefFree(def->data.panic);
3359         break;
3360     case VIR_DOMAIN_DEVICE_MEMORY:
3361         virDomainMemoryDefFree(def->data.memory);
3362         break;
3363     case VIR_DOMAIN_DEVICE_IOMMU:
3364         virDomainIOMMUDefFree(def->data.iommu);
3365         break;
3366     case VIR_DOMAIN_DEVICE_VSOCK:
3367         virDomainVsockDefFree(def->data.vsock);
3368         break;
3369     case VIR_DOMAIN_DEVICE_AUDIO:
3370         virDomainAudioDefFree(def->data.audio);
3371         break;
3372     case VIR_DOMAIN_DEVICE_LAST:
3373     case VIR_DOMAIN_DEVICE_NONE:
3374         break;
3375     }
3376 
3377     g_free(def);
3378 }
3379 
3380 static void
virDomainClockDefClear(virDomainClockDef * def)3381 virDomainClockDefClear(virDomainClockDef *def)
3382 {
3383     size_t i;
3384 
3385     if (def->offset == VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE)
3386         VIR_FREE(def->data.timezone);
3387 
3388     for (i = 0; i < def->ntimers; i++)
3389         VIR_FREE(def->timers[i]);
3390     VIR_FREE(def->timers);
3391 }
3392 
3393 
3394 static bool
virDomainIOThreadIDArrayHasPin(virDomainDef * def)3395 virDomainIOThreadIDArrayHasPin(virDomainDef *def)
3396 {
3397     size_t i;
3398 
3399     for (i = 0; i < def->niothreadids; i++) {
3400         if (def->iothreadids[i]->cpumask)
3401             return true;
3402     }
3403     return false;
3404 }
3405 
3406 
3407 void
virDomainIOThreadIDDefFree(virDomainIOThreadIDDef * def)3408 virDomainIOThreadIDDefFree(virDomainIOThreadIDDef *def)
3409 {
3410     if (!def)
3411         return;
3412     virBitmapFree(def->cpumask);
3413     g_free(def);
3414 }
3415 
3416 
3417 static void
virDomainIOThreadIDDefArrayFree(virDomainIOThreadIDDef ** def,int nids)3418 virDomainIOThreadIDDefArrayFree(virDomainIOThreadIDDef **def,
3419                                 int nids)
3420 {
3421     size_t i;
3422 
3423     if (!def)
3424         return;
3425 
3426     for (i = 0; i < nids; i++)
3427         virDomainIOThreadIDDefFree(def[i]);
3428 
3429     g_free(def);
3430 }
3431 
3432 
3433 static int
virDomainIOThreadIDDefArrayInit(virDomainDef * def,unsigned int iothreads)3434 virDomainIOThreadIDDefArrayInit(virDomainDef *def,
3435                                 unsigned int iothreads)
3436 {
3437     size_t i;
3438     ssize_t nxt = -1;
3439     virDomainIOThreadIDDef *iothrid = NULL;
3440     g_autoptr(virBitmap) thrmap = NULL;
3441 
3442     /* Same value (either 0 or some number), then we have none to fill in or
3443      * the iothreadid array was filled from the XML
3444      */
3445     if (iothreads == def->niothreadids)
3446         return 0;
3447 
3448     /* iothread's are numbered starting at 1, account for that */
3449     thrmap = virBitmapNew(iothreads + 1);
3450     virBitmapSetAll(thrmap);
3451 
3452     /* Clear 0 since we don't use it, then mark those which are
3453      * already provided by the user */
3454     ignore_value(virBitmapClearBit(thrmap, 0));
3455     for (i = 0; i < def->niothreadids; i++)
3456         ignore_value(virBitmapClearBit(thrmap,
3457                                        def->iothreadids[i]->iothread_id));
3458 
3459     /* resize array */
3460     VIR_REALLOC_N(def->iothreadids, iothreads);
3461 
3462     /* Populate iothreadids[] using the set bit number from thrmap */
3463     while (def->niothreadids < iothreads) {
3464         if ((nxt = virBitmapNextSetBit(thrmap, nxt)) < 0) {
3465             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3466                            _("failed to populate iothreadids"));
3467             return -1;
3468         }
3469         iothrid = g_new0(virDomainIOThreadIDDef, 1);
3470         iothrid->iothread_id = nxt;
3471         iothrid->autofill = true;
3472         def->iothreadids[def->niothreadids++] = iothrid;
3473     }
3474 
3475     return 0;
3476 }
3477 
3478 
3479 void
virDomainResourceDefFree(virDomainResourceDef * resource)3480 virDomainResourceDefFree(virDomainResourceDef *resource)
3481 {
3482     if (!resource)
3483         return;
3484 
3485     g_free(resource->partition);
3486     g_free(resource->appid);
3487     g_free(resource);
3488 }
3489 
3490 void
virDomainPanicDefFree(virDomainPanicDef * panic)3491 virDomainPanicDefFree(virDomainPanicDef *panic)
3492 {
3493     if (!panic)
3494         return;
3495 
3496     virDomainDeviceInfoClear(&panic->info);
3497     g_free(panic);
3498 }
3499 
3500 void
virDomainLoaderDefFree(virDomainLoaderDef * loader)3501 virDomainLoaderDefFree(virDomainLoaderDef *loader)
3502 {
3503     if (!loader)
3504         return;
3505 
3506     g_free(loader->path);
3507     g_free(loader->nvram);
3508     g_free(loader->templt);
3509     g_free(loader);
3510 }
3511 
3512 
3513 static void
virDomainResctrlMonDefFree(virDomainResctrlMonDef * domresmon)3514 virDomainResctrlMonDefFree(virDomainResctrlMonDef *domresmon)
3515 {
3516     if (!domresmon)
3517         return;
3518 
3519     virBitmapFree(domresmon->vcpus);
3520     virObjectUnref(domresmon->instance);
3521     g_free(domresmon);
3522 }
3523 
3524 
3525 static void
virDomainResctrlDefFree(virDomainResctrlDef * resctrl)3526 virDomainResctrlDefFree(virDomainResctrlDef *resctrl)
3527 {
3528     size_t i = 0;
3529 
3530     if (!resctrl)
3531         return;
3532 
3533     for (i = 0; i < resctrl->nmonitors; i++)
3534         virDomainResctrlMonDefFree(resctrl->monitors[i]);
3535 
3536     virObjectUnref(resctrl->alloc);
3537     virBitmapFree(resctrl->vcpus);
3538     g_free(resctrl->monitors);
3539     g_free(resctrl);
3540 }
3541 
3542 
3543 void
virDomainSecDefFree(virDomainSecDef * def)3544 virDomainSecDefFree(virDomainSecDef *def)
3545 {
3546     if (!def)
3547         return;
3548 
3549     switch ((virDomainLaunchSecurity) def->sectype) {
3550     case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
3551         g_free(def->data.sev.dh_cert);
3552         g_free(def->data.sev.session);
3553         break;
3554     case VIR_DOMAIN_LAUNCH_SECURITY_PV:
3555     case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
3556     case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
3557         break;
3558     }
3559 
3560     g_free(def);
3561 }
3562 
3563 static void
virDomainOSDefClear(virDomainOSDef * os)3564 virDomainOSDefClear(virDomainOSDef *os)
3565 {
3566     size_t i;
3567 
3568     g_free(os->firmwareFeatures);
3569     g_free(os->machine);
3570     g_free(os->init);
3571     for (i = 0; os->initargv && os->initargv[i]; i++)
3572         g_free(os->initargv[i]);
3573     g_free(os->initargv);
3574     for (i = 0; os->initenv && os->initenv[i]; i++) {
3575         g_free(os->initenv[i]->name);
3576         g_free(os->initenv[i]->value);
3577         g_free(os->initenv[i]);
3578     }
3579     g_free(os->initdir);
3580     g_free(os->inituser);
3581     g_free(os->initgroup);
3582     g_free(os->initenv);
3583     g_free(os->kernel);
3584     g_free(os->initrd);
3585     g_free(os->cmdline);
3586     g_free(os->dtb);
3587     g_free(os->root);
3588     g_free(os->slic_table);
3589     virDomainLoaderDefFree(os->loader);
3590     g_free(os->bootloader);
3591     g_free(os->bootloaderArgs);
3592 }
3593 
3594 
virDomainDefFree(virDomainDef * def)3595 void virDomainDefFree(virDomainDef *def)
3596 {
3597     size_t i;
3598 
3599     if (!def)
3600         return;
3601 
3602     virDomainResourceDefFree(def->resource);
3603 
3604     for (i = 0; i < def->maxvcpus; i++)
3605         virDomainVcpuDefFree(def->vcpus[i]);
3606     g_free(def->vcpus);
3607 
3608     /* hostdevs must be freed before nets (or any future "intelligent
3609      * hostdevs") because the pointer to the hostdev is really
3610      * pointing into the middle of the higher level device's object,
3611      * so the original object must still be available during the call
3612      * to virDomainHostdevDefFree().
3613      */
3614     for (i = 0; i < def->nhostdevs; i++)
3615         virDomainHostdevDefFree(def->hostdevs[i]);
3616     g_free(def->hostdevs);
3617 
3618     for (i = 0; i < def->nleases; i++)
3619         virDomainLeaseDefFree(def->leases[i]);
3620     g_free(def->leases);
3621 
3622     for (i = 0; i < def->ngraphics; i++)
3623         virDomainGraphicsDefFree(def->graphics[i]);
3624     g_free(def->graphics);
3625 
3626     for (i = 0; i < def->ninputs; i++)
3627         virDomainInputDefFree(def->inputs[i]);
3628     g_free(def->inputs);
3629 
3630     for (i = 0; i < def->ndisks; i++)
3631         virDomainDiskDefFree(def->disks[i]);
3632     g_free(def->disks);
3633 
3634     for (i = 0; i < def->ncontrollers; i++)
3635         virDomainControllerDefFree(def->controllers[i]);
3636     g_free(def->controllers);
3637 
3638     for (i = 0; i < def->nfss; i++)
3639         virDomainFSDefFree(def->fss[i]);
3640     g_free(def->fss);
3641 
3642     for (i = 0; i < def->nnets; i++)
3643         virDomainNetDefFree(def->nets[i]);
3644     g_free(def->nets);
3645 
3646     for (i = 0; i < def->nsmartcards; i++)
3647         virDomainSmartcardDefFree(def->smartcards[i]);
3648     g_free(def->smartcards);
3649 
3650     for (i = 0; i < def->nserials; i++)
3651         virDomainChrDefFree(def->serials[i]);
3652     g_free(def->serials);
3653 
3654     for (i = 0; i < def->nparallels; i++)
3655         virDomainChrDefFree(def->parallels[i]);
3656     g_free(def->parallels);
3657 
3658     for (i = 0; i < def->nchannels; i++)
3659         virDomainChrDefFree(def->channels[i]);
3660     g_free(def->channels);
3661 
3662     for (i = 0; i < def->nconsoles; i++)
3663         virDomainChrDefFree(def->consoles[i]);
3664     g_free(def->consoles);
3665 
3666     for (i = 0; i < def->nsounds; i++)
3667         virDomainSoundDefFree(def->sounds[i]);
3668     g_free(def->sounds);
3669 
3670     for (i = 0; i < def->naudios; i++)
3671         virDomainAudioDefFree(def->audios[i]);
3672     g_free(def->audios);
3673 
3674     for (i = 0; i < def->nvideos; i++)
3675         virDomainVideoDefFree(def->videos[i]);
3676     g_free(def->videos);
3677 
3678     for (i = 0; i < def->nhubs; i++)
3679         virDomainHubDefFree(def->hubs[i]);
3680     g_free(def->hubs);
3681 
3682     for (i = 0; i < def->nredirdevs; i++)
3683         virDomainRedirdevDefFree(def->redirdevs[i]);
3684     g_free(def->redirdevs);
3685 
3686     for (i = 0; i < def->nrngs; i++)
3687         virDomainRNGDefFree(def->rngs[i]);
3688     g_free(def->rngs);
3689 
3690     for (i = 0; i < def->nmems; i++)
3691         virDomainMemoryDefFree(def->mems[i]);
3692     g_free(def->mems);
3693 
3694     for (i = 0; i < def->ntpms; i++)
3695         virDomainTPMDefFree(def->tpms[i]);
3696     g_free(def->tpms);
3697 
3698     for (i = 0; i < def->npanics; i++)
3699         virDomainPanicDefFree(def->panics[i]);
3700     g_free(def->panics);
3701 
3702     virDomainIOMMUDefFree(def->iommu);
3703 
3704     g_free(def->idmap.uidmap);
3705     g_free(def->idmap.gidmap);
3706 
3707     virDomainOSDefClear(&def->os);
3708 
3709     virDomainClockDefClear(&def->clock);
3710 
3711     g_free(def->name);
3712     virBitmapFree(def->cpumask);
3713     g_free(def->emulator);
3714     g_free(def->description);
3715     g_free(def->title);
3716     g_free(def->hyperv_vendor_id);
3717 
3718     virBlkioDeviceArrayClear(def->blkio.devices,
3719                              def->blkio.ndevices);
3720     g_free(def->blkio.devices);
3721 
3722     virDomainWatchdogDefFree(def->watchdog);
3723 
3724     virDomainMemballoonDefFree(def->memballoon);
3725     virDomainNVRAMDefFree(def->nvram);
3726     virDomainVsockDefFree(def->vsock);
3727 
3728     for (i = 0; i < def->mem.nhugepages; i++)
3729         virBitmapFree(def->mem.hugepages[i].nodemask);
3730     g_free(def->mem.hugepages);
3731 
3732     for (i = 0; i < def->nseclabels; i++)
3733         virSecurityLabelDefFree(def->seclabels[i]);
3734     g_free(def->seclabels);
3735 
3736     virCPUDefFree(def->cpu);
3737 
3738     virDomainIOThreadIDDefArrayFree(def->iothreadids, def->niothreadids);
3739 
3740     virBitmapFree(def->cputune.emulatorpin);
3741     g_free(def->cputune.emulatorsched);
3742 
3743     virDomainNumaFree(def->numa);
3744 
3745     for (i = 0; i < def->nsysinfo; i++)
3746         virSysinfoDefFree(def->sysinfo[i]);
3747     g_free(def->sysinfo);
3748 
3749     virDomainRedirFilterDefFree(def->redirfilter);
3750 
3751     for (i = 0; i < def->nshmems; i++)
3752         virDomainShmemDefFree(def->shmems[i]);
3753     g_free(def->shmems);
3754 
3755     for (i = 0; i < def->nresctrls; i++)
3756         virDomainResctrlDefFree(def->resctrls[i]);
3757     g_free(def->resctrls);
3758 
3759     g_free(def->keywrap);
3760 
3761     if (def->namespaceData && def->ns.free)
3762         (def->ns.free)(def->namespaceData);
3763 
3764     virDomainSecDefFree(def->sec);
3765 
3766     xmlFreeNode(def->metadata);
3767 
3768     g_free(def);
3769 }
3770 
3771 static void
virDomainObjDeprecationFree(virDomainObj * dom)3772 virDomainObjDeprecationFree(virDomainObj *dom)
3773 {
3774     size_t i = 0;
3775     for (i = 0; i < dom->ndeprecations; i++) {
3776         g_free(dom->deprecations[i]);
3777     }
3778     g_free(dom->deprecations);
3779 }
3780 
virDomainObjDispose(void * obj)3781 static void virDomainObjDispose(void *obj)
3782 {
3783     virDomainObj *dom = obj;
3784 
3785     VIR_DEBUG("obj=%p", dom);
3786     virCondDestroy(&dom->cond);
3787     virDomainDefFree(dom->def);
3788     virDomainDefFree(dom->newDef);
3789 
3790     if (dom->privateDataFreeFunc)
3791         (dom->privateDataFreeFunc)(dom->privateData);
3792 
3793     virDomainObjDeprecationFree(dom);
3794     virDomainSnapshotObjListFree(dom->snapshots);
3795     virDomainCheckpointObjListFree(dom->checkpoints);
3796 }
3797 
3798 virDomainObj *
virDomainObjNew(virDomainXMLOption * xmlopt)3799 virDomainObjNew(virDomainXMLOption *xmlopt)
3800 {
3801     virDomainObj *domain;
3802 
3803     if (virDomainObjInitialize() < 0)
3804         return NULL;
3805 
3806     if (!(domain = virObjectLockableNew(virDomainObjClass)))
3807         return NULL;
3808 
3809     if (virCondInit(&domain->cond) < 0) {
3810         virReportSystemError(errno, "%s",
3811                              _("failed to initialize domain condition"));
3812         goto error;
3813     }
3814 
3815     if (xmlopt->privateData.alloc) {
3816         domain->privateData = (xmlopt->privateData.alloc)(xmlopt->config.priv);
3817         if (!domain->privateData)
3818             goto error;
3819         domain->privateDataFreeFunc = xmlopt->privateData.free;
3820     }
3821 
3822     if (!(domain->snapshots = virDomainSnapshotObjListNew()))
3823         goto error;
3824 
3825     if (!(domain->checkpoints = virDomainCheckpointObjListNew()))
3826         goto error;
3827 
3828     virObjectLock(domain);
3829     virDomainObjSetState(domain, VIR_DOMAIN_SHUTOFF,
3830                                  VIR_DOMAIN_SHUTOFF_UNKNOWN);
3831 
3832     VIR_DEBUG("obj=%p", domain);
3833     return domain;
3834 
3835  error:
3836     virObjectUnref(domain);
3837     return NULL;
3838 }
3839 
3840 
3841 virDomainDef *
virDomainDefNew(virDomainXMLOption * xmlopt)3842 virDomainDefNew(virDomainXMLOption *xmlopt)
3843 {
3844     virDomainDef *ret;
3845 
3846     ret = g_new0(virDomainDef, 1);
3847 
3848     if (!(ret->numa = virDomainNumaNew()))
3849         goto error;
3850 
3851     ret->mem.hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
3852     ret->mem.soft_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
3853     ret->mem.swap_hard_limit = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
3854 
3855     if (xmlopt && xmlopt->config.features & VIR_DOMAIN_DEF_FEATURE_WIDE_SCSI)
3856         ret->scsiBusMaxUnit = SCSI_WIDE_BUS_MAX_CONT_UNIT;
3857     else
3858         ret->scsiBusMaxUnit = SCSI_NARROW_BUS_MAX_CONT_UNIT;
3859 
3860     return ret;
3861 
3862  error:
3863     virDomainDefFree(ret);
3864     return NULL;
3865 }
3866 
3867 
virDomainObjAssignDef(virDomainObj * domain,virDomainDef ** def,bool live,virDomainDef ** oldDef)3868 void virDomainObjAssignDef(virDomainObj *domain,
3869                            virDomainDef **def,
3870                            bool live,
3871                            virDomainDef **oldDef)
3872 {
3873     if (oldDef)
3874         *oldDef = NULL;
3875     if (virDomainObjIsActive(domain)) {
3876         if (oldDef)
3877             *oldDef = domain->newDef;
3878         else
3879             virDomainDefFree(domain->newDef);
3880         domain->newDef = g_steal_pointer(def);
3881     } else {
3882         if (live) {
3883             /* save current configuration to be restored on domain shutdown */
3884             if (!domain->newDef)
3885                 domain->newDef = domain->def;
3886             else
3887                 virDomainDefFree(domain->def);
3888             domain->def = g_steal_pointer(def);
3889         } else {
3890             if (oldDef)
3891                 *oldDef = domain->def;
3892             else
3893                 virDomainDefFree(domain->def);
3894             domain->def = g_steal_pointer(def);
3895         }
3896     }
3897 }
3898 
3899 
3900 /**
3901  * virDomainObjEndAPI:
3902  * @vm: domain object
3903  *
3904  * Finish working with a domain object in an API.  This function
3905  * clears whatever was left of a domain that was gathered using
3906  * virDomainObjListFindByUUID(). Currently that means only unlocking and
3907  * decrementing the reference counter of that domain.  And in order to
3908  * make sure the caller does not access the domain, the pointer is
3909  * cleared.
3910  */
3911 void
virDomainObjEndAPI(virDomainObj ** vm)3912 virDomainObjEndAPI(virDomainObj **vm)
3913 {
3914     if (!*vm)
3915         return;
3916 
3917     virObjectUnlock(*vm);
3918     virObjectUnref(*vm);
3919     *vm = NULL;
3920 }
3921 
3922 
3923 void
virDomainObjBroadcast(virDomainObj * vm)3924 virDomainObjBroadcast(virDomainObj *vm)
3925 {
3926     virCondBroadcast(&vm->cond);
3927 }
3928 
3929 
3930 int
virDomainObjWait(virDomainObj * vm)3931 virDomainObjWait(virDomainObj *vm)
3932 {
3933     if (virCondWait(&vm->cond, &vm->parent.lock) < 0) {
3934         virReportSystemError(errno, "%s",
3935                              _("failed to wait for domain condition"));
3936         return -1;
3937     }
3938 
3939     if (!virDomainObjIsActive(vm)) {
3940         virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3941                        _("domain is not running"));
3942         return -1;
3943     }
3944 
3945     return 0;
3946 }
3947 
3948 
3949 /**
3950  * Waits for domain condition to be triggered for a specific period of time.
3951  *
3952  * Returns:
3953  *  -1 in case of error
3954  *  0 on success
3955  *  1 on timeout
3956  */
3957 int
virDomainObjWaitUntil(virDomainObj * vm,unsigned long long whenms)3958 virDomainObjWaitUntil(virDomainObj *vm,
3959                       unsigned long long whenms)
3960 {
3961     if (virCondWaitUntil(&vm->cond, &vm->parent.lock, whenms) < 0) {
3962         if (errno != ETIMEDOUT) {
3963             virReportSystemError(errno, "%s",
3964                                  _("failed to wait for domain condition"));
3965             return -1;
3966         }
3967         return 1;
3968     }
3969     return 0;
3970 }
3971 
3972 
3973 /*
3974  * Mark the current VM config as transient. Ensures transient hotplug
3975  * operations do not persist past shutdown.
3976  *
3977  * @param caps pointer to capabilities info
3978  * @param xmlopt pointer to XML parser configuration object
3979  * @param domain domain object pointer
3980  * @return 0 on success, -1 on failure
3981  */
3982 int
virDomainObjSetDefTransient(virDomainXMLOption * xmlopt,virDomainObj * domain,void * parseOpaque)3983 virDomainObjSetDefTransient(virDomainXMLOption *xmlopt,
3984                             virDomainObj *domain,
3985                             void *parseOpaque)
3986 {
3987     if (!domain->persistent)
3988         return 0;
3989 
3990     if (domain->newDef)
3991         return 0;
3992 
3993     if (!(domain->newDef = virDomainDefCopy(domain->def, xmlopt,
3994                                             parseOpaque, false)))
3995         return -1;
3996 
3997     return 0;
3998 }
3999 
4000 
4001 /*
4002  * Remove the running configuration and replace it with the persistent one.
4003  *
4004  * @param domain domain object pointer
4005  */
4006 void
virDomainObjRemoveTransientDef(virDomainObj * domain)4007 virDomainObjRemoveTransientDef(virDomainObj *domain)
4008 {
4009     if (!domain->newDef)
4010         return;
4011 
4012     virDomainDefFree(domain->def);
4013     domain->def = g_steal_pointer(&domain->newDef);
4014     domain->def->id = -1;
4015 }
4016 
4017 
4018 /*
4019  * Return the persistent domain configuration. If domain is transient,
4020  * return the running config.
4021  *
4022  * @param caps pointer to capabilities info
4023  * @param xmlopt pointer to XML parser configuration object
4024  * @param domain domain object pointer
4025  * @return NULL on error, virDomainDef * on success
4026  */
4027 virDomainDef *
virDomainObjGetPersistentDef(virDomainXMLOption * xmlopt,virDomainObj * domain,void * parseOpaque)4028 virDomainObjGetPersistentDef(virDomainXMLOption *xmlopt,
4029                              virDomainObj *domain,
4030                              void *parseOpaque)
4031 {
4032     if (virDomainObjIsActive(domain) &&
4033         virDomainObjSetDefTransient(xmlopt, domain, parseOpaque) < 0)
4034         return NULL;
4035 
4036     if (domain->newDef)
4037         return domain->newDef;
4038     else
4039         return domain->def;
4040 }
4041 
4042 
4043 /**
4044  * virDomainObjUpdateModificationImpact:
4045  *
4046  * @vm: domain object
4047  * @flags: flags to update the modification impact on
4048  *
4049  * Resolves virDomainModificationImpact flags in @flags so that they correctly
4050  * apply to the actual state of @vm. @flags may be modified after call to this
4051  * function.
4052  *
4053  * Returns 0 on success if @flags point to a valid combination for @vm or -1 on
4054  * error.
4055  */
4056 int
virDomainObjUpdateModificationImpact(virDomainObj * vm,unsigned int * flags)4057 virDomainObjUpdateModificationImpact(virDomainObj *vm,
4058                                      unsigned int *flags)
4059 {
4060     bool isActive = virDomainObjIsActive(vm);
4061 
4062     if ((*flags & (VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG)) ==
4063         VIR_DOMAIN_AFFECT_CURRENT) {
4064         if (isActive)
4065             *flags |= VIR_DOMAIN_AFFECT_LIVE;
4066         else
4067             *flags |= VIR_DOMAIN_AFFECT_CONFIG;
4068     }
4069 
4070     if (!isActive && (*flags & VIR_DOMAIN_AFFECT_LIVE)) {
4071         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4072                        _("domain is not running"));
4073         return -1;
4074     }
4075 
4076     if (!vm->persistent && (*flags & VIR_DOMAIN_AFFECT_CONFIG)) {
4077         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
4078                        _("transient domains do not have any "
4079                          "persistent config"));
4080         return -1;
4081     }
4082 
4083     return 0;
4084 }
4085 
4086 
4087 /**
4088  * virDomainObjGetDefs:
4089  *
4090  * @vm: domain object
4091  * @flags: for virDomainModificationImpact
4092  * @liveDef: Set to the pointer to the live definition of @vm.
4093  * @persDef: Set to the pointer to the config definition of @vm.
4094  *
4095  * Helper function to resolve @flags and retrieve correct domain pointer
4096  * objects. This function should be used only when the hypervisor driver always
4097  * creates vm->newDef once the vm is started. (qemu driver does that)
4098  *
4099  * If @liveDef or @persDef are set it implies that @flags request modification
4100  * of thereof.
4101  *
4102  * Returns 0 on success and sets @liveDef and @persDef; -1 if @flags are
4103  * inappropriate.
4104  */
4105 int
virDomainObjGetDefs(virDomainObj * vm,unsigned int flags,virDomainDef ** liveDef,virDomainDef ** persDef)4106 virDomainObjGetDefs(virDomainObj *vm,
4107                     unsigned int flags,
4108                     virDomainDef **liveDef,
4109                     virDomainDef **persDef)
4110 {
4111     if (liveDef)
4112         *liveDef = NULL;
4113 
4114     if (persDef)
4115         *persDef = NULL;
4116 
4117     if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
4118         return -1;
4119 
4120     if (virDomainObjIsActive(vm)) {
4121         if (liveDef && (flags & VIR_DOMAIN_AFFECT_LIVE))
4122             *liveDef = vm->def;
4123 
4124         if (persDef && (flags & VIR_DOMAIN_AFFECT_CONFIG))
4125             *persDef = vm->newDef;
4126     } else {
4127         if (persDef)
4128             *persDef = vm->def;
4129     }
4130 
4131     return 0;
4132 }
4133 
4134 
4135 /**
4136  * virDomainObjGetOneDefState:
4137  *
4138  * @vm: Domain object
4139  * @flags: for virDomainModificationImpact
4140  * @live: set to true if live config was returned (may be omitted)
4141  *
4142  * Helper function to resolve @flags and return the correct domain pointer
4143  * object. This function returns one of @vm->def or @vm->persistentDef
4144  * according to @flags. @live is set to true if the live vm config will be
4145  * returned. This helper should be used only in APIs that guarantee
4146  * that @flags contains exactly one of VIR_DOMAIN_AFFECT_LIVE or
4147  * VIR_DOMAIN_AFFECT_CONFIG and not both.
4148  *
4149  * Returns the correct definition pointer or NULL on error.
4150  */
4151 virDomainDef *
virDomainObjGetOneDefState(virDomainObj * vm,unsigned int flags,bool * live)4152 virDomainObjGetOneDefState(virDomainObj *vm,
4153                            unsigned int flags,
4154                            bool *live)
4155 {
4156     if (flags & VIR_DOMAIN_AFFECT_LIVE &&
4157         flags & VIR_DOMAIN_AFFECT_CONFIG) {
4158         virReportInvalidArg(flags, "%s",
4159                             _("Flags 'VIR_DOMAIN_AFFECT_LIVE' and "
4160                               "'VIR_DOMAIN_AFFECT_CONFIG' are mutually "
4161                               "exclusive"));
4162         return NULL;
4163     }
4164 
4165     if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
4166         return NULL;
4167 
4168     if (live) {
4169         if (flags & VIR_DOMAIN_AFFECT_LIVE)
4170             *live = true;
4171         else
4172             *live = false;
4173     }
4174 
4175     if (virDomainObjIsActive(vm) && flags & VIR_DOMAIN_AFFECT_CONFIG)
4176         return vm->newDef;
4177     else
4178         return vm->def;
4179 }
4180 
4181 
4182 /**
4183  * virDomainObjGetOneDef:
4184  *
4185  * @vm: Domain object
4186  * @flags: for virDomainModificationImpact
4187  *
4188  * Helper function to resolve @flags and return the correct domain pointer
4189  * object. This function returns one of @vm->def or @vm->persistentDef
4190  * according to @flags. This helper should be used only in APIs that guarantee
4191  * that @flags contains exactly one of VIR_DOMAIN_AFFECT_LIVE or
4192  * VIR_DOMAIN_AFFECT_CONFIG and not both.
4193  *
4194  * Returns the correct definition pointer or NULL on error.
4195  */
4196 virDomainDef *
virDomainObjGetOneDef(virDomainObj * vm,unsigned int flags)4197 virDomainObjGetOneDef(virDomainObj *vm,
4198                       unsigned int flags)
4199 {
4200     return virDomainObjGetOneDefState(vm, flags, NULL);
4201 }
4202 
4203 virDomainDeviceInfo *
virDomainDeviceGetInfo(const virDomainDeviceDef * device)4204 virDomainDeviceGetInfo(const virDomainDeviceDef *device)
4205 {
4206     switch ((virDomainDeviceType) device->type) {
4207     case VIR_DOMAIN_DEVICE_DISK:
4208         return &device->data.disk->info;
4209     case VIR_DOMAIN_DEVICE_FS:
4210         return &device->data.fs->info;
4211     case VIR_DOMAIN_DEVICE_NET:
4212         return &device->data.net->info;
4213     case VIR_DOMAIN_DEVICE_INPUT:
4214         return &device->data.input->info;
4215     case VIR_DOMAIN_DEVICE_SOUND:
4216         return &device->data.sound->info;
4217     case VIR_DOMAIN_DEVICE_VIDEO:
4218         return &device->data.video->info;
4219     case VIR_DOMAIN_DEVICE_HOSTDEV:
4220         return device->data.hostdev->info;
4221     case VIR_DOMAIN_DEVICE_WATCHDOG:
4222         return &device->data.watchdog->info;
4223     case VIR_DOMAIN_DEVICE_CONTROLLER:
4224         return &device->data.controller->info;
4225     case VIR_DOMAIN_DEVICE_HUB:
4226         return &device->data.hub->info;
4227     case VIR_DOMAIN_DEVICE_REDIRDEV:
4228         return &device->data.redirdev->info;
4229     case VIR_DOMAIN_DEVICE_SMARTCARD:
4230         return &device->data.smartcard->info;
4231     case VIR_DOMAIN_DEVICE_CHR:
4232         return &device->data.chr->info;
4233     case VIR_DOMAIN_DEVICE_MEMBALLOON:
4234         return &device->data.memballoon->info;
4235     case VIR_DOMAIN_DEVICE_NVRAM:
4236         return &device->data.nvram->info;
4237     case VIR_DOMAIN_DEVICE_SHMEM:
4238         return &device->data.shmem->info;
4239     case VIR_DOMAIN_DEVICE_RNG:
4240         return &device->data.rng->info;
4241     case VIR_DOMAIN_DEVICE_TPM:
4242         return &device->data.tpm->info;
4243     case VIR_DOMAIN_DEVICE_PANIC:
4244         return &device->data.panic->info;
4245     case VIR_DOMAIN_DEVICE_MEMORY:
4246         return &device->data.memory->info;
4247     case VIR_DOMAIN_DEVICE_VSOCK:
4248         return &device->data.vsock->info;
4249 
4250     /* The following devices do not contain virDomainDeviceInfo */
4251     case VIR_DOMAIN_DEVICE_LEASE:
4252     case VIR_DOMAIN_DEVICE_GRAPHICS:
4253     case VIR_DOMAIN_DEVICE_IOMMU:
4254     case VIR_DOMAIN_DEVICE_AUDIO:
4255     case VIR_DOMAIN_DEVICE_LAST:
4256     case VIR_DOMAIN_DEVICE_NONE:
4257         break;
4258     }
4259     return NULL;
4260 }
4261 
4262 
4263 /**
4264  * virDomainDeviceSetData
4265  * @device: virDomainDeviceDef * with ->type filled in
4266  * @devicedata: *Def * data for a device. Ex: virDomainDiskDef *
4267  *
4268  * Set the data.X variable for the device->type value. Basically
4269  * a mapping of virDomainDeviceType to the associated name in
4270  * the virDomainDeviceDef union
4271  */
4272 void
virDomainDeviceSetData(virDomainDeviceDef * device,void * devicedata)4273 virDomainDeviceSetData(virDomainDeviceDef *device,
4274                        void *devicedata)
4275 {
4276     switch ((virDomainDeviceType) device->type) {
4277     case VIR_DOMAIN_DEVICE_DISK:
4278         device->data.disk = devicedata;
4279         break;
4280     case VIR_DOMAIN_DEVICE_NET:
4281         device->data.net = devicedata;
4282         break;
4283     case VIR_DOMAIN_DEVICE_SOUND:
4284         device->data.sound = devicedata;
4285         break;
4286     case VIR_DOMAIN_DEVICE_HOSTDEV:
4287         device->data.hostdev = devicedata;
4288         break;
4289     case VIR_DOMAIN_DEVICE_VIDEO:
4290         device->data.video = devicedata;
4291         break;
4292     case VIR_DOMAIN_DEVICE_CONTROLLER:
4293         device->data.controller = devicedata;
4294         break;
4295     case VIR_DOMAIN_DEVICE_GRAPHICS:
4296         device->data.graphics = devicedata;
4297         break;
4298     case VIR_DOMAIN_DEVICE_SMARTCARD:
4299         device->data.smartcard = devicedata;
4300         break;
4301     case VIR_DOMAIN_DEVICE_CHR:
4302         device->data.chr = devicedata;
4303         break;
4304     case VIR_DOMAIN_DEVICE_INPUT:
4305         device->data.input = devicedata;
4306         break;
4307     case VIR_DOMAIN_DEVICE_FS:
4308         device->data.fs = devicedata;
4309         break;
4310     case VIR_DOMAIN_DEVICE_WATCHDOG:
4311         device->data.watchdog = devicedata;
4312         break;
4313     case VIR_DOMAIN_DEVICE_MEMBALLOON:
4314         device->data.memballoon = devicedata;
4315         break;
4316     case VIR_DOMAIN_DEVICE_RNG:
4317         device->data.rng = devicedata;
4318         break;
4319     case VIR_DOMAIN_DEVICE_NVRAM:
4320         device->data.nvram = devicedata;
4321         break;
4322     case VIR_DOMAIN_DEVICE_HUB:
4323         device->data.hub = devicedata;
4324         break;
4325     case VIR_DOMAIN_DEVICE_SHMEM:
4326         device->data.shmem = devicedata;
4327         break;
4328     case VIR_DOMAIN_DEVICE_TPM:
4329         device->data.tpm = devicedata;
4330         break;
4331     case VIR_DOMAIN_DEVICE_PANIC:
4332         device->data.panic = devicedata;
4333         break;
4334     case VIR_DOMAIN_DEVICE_MEMORY:
4335         device->data.memory = devicedata;
4336         break;
4337     case VIR_DOMAIN_DEVICE_REDIRDEV:
4338         device->data.redirdev = devicedata;
4339         break;
4340     case VIR_DOMAIN_DEVICE_VSOCK:
4341         device->data.vsock = devicedata;
4342         break;
4343     case VIR_DOMAIN_DEVICE_IOMMU:
4344         device->data.iommu = devicedata;
4345         break;
4346     case VIR_DOMAIN_DEVICE_LEASE:
4347         device->data.lease = devicedata;
4348         break;
4349     case VIR_DOMAIN_DEVICE_AUDIO:
4350         device->data.audio = devicedata;
4351         break;
4352     case VIR_DOMAIN_DEVICE_NONE:
4353     case VIR_DOMAIN_DEVICE_LAST:
4354         break;
4355     }
4356 }
4357 
4358 
4359 static int
virDomainDefHasDeviceAddressIterator(virDomainDef * def G_GNUC_UNUSED,virDomainDeviceDef * dev G_GNUC_UNUSED,virDomainDeviceInfo * info,void * opaque)4360 virDomainDefHasDeviceAddressIterator(virDomainDef *def G_GNUC_UNUSED,
4361                                      virDomainDeviceDef *dev G_GNUC_UNUSED,
4362                                      virDomainDeviceInfo *info,
4363                                      void *opaque)
4364 {
4365     virDomainDeviceInfo *needle = opaque;
4366 
4367     /* break iteration if the info was found */
4368     if (virDomainDeviceInfoAddressIsEqual(info, needle))
4369         return -1;
4370 
4371     return 0;
4372 }
4373 
4374 
4375 static bool
virDomainSkipBackcompatConsole(virDomainDef * def,size_t idx,bool all)4376 virDomainSkipBackcompatConsole(virDomainDef *def,
4377                                size_t idx,
4378                                bool all)
4379 {
4380     virDomainChrDef *console = def->consoles[idx];
4381 
4382     if (!all && idx == 0 &&
4383         (console->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL ||
4384          console->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE) &&
4385         def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
4386         return true;
4387     }
4388 
4389     return false;
4390 }
4391 
4392 
4393 /*
4394  * Iterates over domain devices calling @cb on each device. The default
4395  * behaviour can be altered with virDomainDeviceIterateFlags.
4396  */
4397 int
virDomainDeviceInfoIterateFlags(virDomainDef * def,virDomainDeviceInfoCallback cb,unsigned int iteratorFlags,void * opaque)4398 virDomainDeviceInfoIterateFlags(virDomainDef *def,
4399                                 virDomainDeviceInfoCallback cb,
4400                                 unsigned int iteratorFlags,
4401                                 void *opaque)
4402 {
4403     size_t i;
4404     int rc;
4405     virDomainDeviceDef device;
4406 
4407     device.type = VIR_DOMAIN_DEVICE_DISK;
4408     for (i = 0; i < def->ndisks; i++) {
4409         device.data.disk = def->disks[i];
4410         if ((rc = cb(def, &device, &def->disks[i]->info, opaque)) != 0)
4411             return rc;
4412     }
4413     device.type = VIR_DOMAIN_DEVICE_NET;
4414     for (i = 0; i < def->nnets; i++) {
4415         device.data.net = def->nets[i];
4416         if ((rc = cb(def, &device, &def->nets[i]->info, opaque)) != 0)
4417             return rc;
4418     }
4419     device.type = VIR_DOMAIN_DEVICE_SOUND;
4420     for (i = 0; i < def->nsounds; i++) {
4421         device.data.sound = def->sounds[i];
4422         if ((rc = cb(def, &device, &def->sounds[i]->info, opaque)) != 0)
4423             return rc;
4424     }
4425     device.type = VIR_DOMAIN_DEVICE_HOSTDEV;
4426     for (i = 0; i < def->nhostdevs; i++) {
4427         device.data.hostdev = def->hostdevs[i];
4428         if ((rc = cb(def, &device, def->hostdevs[i]->info, opaque)) != 0)
4429             return rc;
4430     }
4431     device.type = VIR_DOMAIN_DEVICE_VIDEO;
4432     for (i = 0; i < def->nvideos; i++) {
4433         device.data.video = def->videos[i];
4434         if ((rc = cb(def, &device, &def->videos[i]->info, opaque)) != 0)
4435             return rc;
4436     }
4437     device.type = VIR_DOMAIN_DEVICE_CONTROLLER;
4438     for (i = 0; i < def->ncontrollers; i++) {
4439         device.data.controller = def->controllers[i];
4440         if ((rc = cb(def, &device, &def->controllers[i]->info, opaque)) != 0)
4441             return rc;
4442     }
4443     device.type = VIR_DOMAIN_DEVICE_SMARTCARD;
4444     for (i = 0; i < def->nsmartcards; i++) {
4445         device.data.smartcard = def->smartcards[i];
4446         if ((rc = cb(def, &device, &def->smartcards[i]->info, opaque)) != 0)
4447             return rc;
4448     }
4449     device.type = VIR_DOMAIN_DEVICE_CHR;
4450     for (i = 0; i < def->nserials; i++) {
4451         device.data.chr = def->serials[i];
4452         if ((rc = cb(def, &device, &def->serials[i]->info, opaque)) != 0)
4453             return rc;
4454     }
4455     for (i = 0; i < def->nparallels; i++) {
4456         device.data.chr = def->parallels[i];
4457         if ((rc = cb(def, &device, &def->parallels[i]->info, opaque)) != 0)
4458             return rc;
4459     }
4460     for (i = 0; i < def->nchannels; i++) {
4461         device.data.chr = def->channels[i];
4462         if ((rc = cb(def, &device, &def->channels[i]->info, opaque)) != 0)
4463             return rc;
4464     }
4465     for (i = 0; i < def->nconsoles; i++) {
4466         bool all = iteratorFlags & DOMAIN_DEVICE_ITERATE_ALL_CONSOLES;
4467 
4468         if (virDomainSkipBackcompatConsole(def, i, all))
4469             continue;
4470         device.data.chr = def->consoles[i];
4471         if ((rc = cb(def, &device, &def->consoles[i]->info, opaque)) != 0)
4472             return rc;
4473     }
4474     device.type = VIR_DOMAIN_DEVICE_INPUT;
4475     for (i = 0; i < def->ninputs; i++) {
4476         device.data.input = def->inputs[i];
4477         if ((rc = cb(def, &device, &def->inputs[i]->info, opaque)) != 0)
4478             return rc;
4479     }
4480     device.type = VIR_DOMAIN_DEVICE_FS;
4481     for (i = 0; i < def->nfss; i++) {
4482         device.data.fs = def->fss[i];
4483         if ((rc = cb(def, &device, &def->fss[i]->info, opaque)) != 0)
4484             return rc;
4485     }
4486     if (def->watchdog) {
4487         device.type = VIR_DOMAIN_DEVICE_WATCHDOG;
4488         device.data.watchdog = def->watchdog;
4489         if ((rc = cb(def, &device, &def->watchdog->info, opaque)) != 0)
4490             return rc;
4491     }
4492     if (def->memballoon) {
4493         device.type = VIR_DOMAIN_DEVICE_MEMBALLOON;
4494         device.data.memballoon = def->memballoon;
4495         if ((rc = cb(def, &device, &def->memballoon->info, opaque)) != 0)
4496             return rc;
4497     }
4498     device.type = VIR_DOMAIN_DEVICE_RNG;
4499     for (i = 0; i < def->nrngs; i++) {
4500         device.data.rng = def->rngs[i];
4501         if ((rc = cb(def, &device, &def->rngs[i]->info, opaque)) != 0)
4502             return rc;
4503     }
4504     if (def->nvram) {
4505         device.type = VIR_DOMAIN_DEVICE_NVRAM;
4506         device.data.nvram = def->nvram;
4507         if ((rc = cb(def, &device, &def->nvram->info, opaque)) != 0)
4508             return rc;
4509     }
4510     device.type = VIR_DOMAIN_DEVICE_HUB;
4511     for (i = 0; i < def->nhubs; i++) {
4512         device.data.hub = def->hubs[i];
4513         if ((rc = cb(def, &device, &def->hubs[i]->info, opaque)) != 0)
4514             return rc;
4515     }
4516     device.type = VIR_DOMAIN_DEVICE_SHMEM;
4517     for (i = 0; i < def->nshmems; i++) {
4518         device.data.shmem = def->shmems[i];
4519         if ((rc = cb(def, &device, &def->shmems[i]->info, opaque)) != 0)
4520             return rc;
4521     }
4522     device.type = VIR_DOMAIN_DEVICE_TPM;
4523     for (i = 0; i < def->ntpms; i++) {
4524         device.data.tpm = def->tpms[i];
4525         if ((rc = cb(def, &device, &def->tpms[i]->info, opaque)) != 0)
4526             return rc;
4527     }
4528     device.type = VIR_DOMAIN_DEVICE_PANIC;
4529     for (i = 0; i < def->npanics; i++) {
4530         device.data.panic = def->panics[i];
4531         if ((rc = cb(def, &device, &def->panics[i]->info, opaque)) != 0)
4532             return rc;
4533     }
4534 
4535     device.type = VIR_DOMAIN_DEVICE_MEMORY;
4536     for (i = 0; i < def->nmems; i++) {
4537         device.data.memory = def->mems[i];
4538         if ((rc = cb(def, &device, &def->mems[i]->info, opaque)) != 0)
4539             return rc;
4540     }
4541 
4542     device.type = VIR_DOMAIN_DEVICE_REDIRDEV;
4543     for (i = 0; i < def->nredirdevs; i++) {
4544         device.data.redirdev = def->redirdevs[i];
4545         if ((rc = cb(def, &device, &def->redirdevs[i]->info, opaque)) != 0)
4546             return rc;
4547     }
4548 
4549     device.type = VIR_DOMAIN_DEVICE_VSOCK;
4550     if (def->vsock) {
4551         device.data.vsock = def->vsock;
4552         if ((rc = cb(def, &device, &def->vsock->info, opaque)) != 0)
4553             return rc;
4554     }
4555 
4556     /* If the flag below is set, make sure @cb can handle @info being NULL */
4557     if (iteratorFlags & DOMAIN_DEVICE_ITERATE_MISSING_INFO) {
4558         device.type = VIR_DOMAIN_DEVICE_GRAPHICS;
4559         for (i = 0; i < def->ngraphics; i++) {
4560             device.data.graphics = def->graphics[i];
4561             if ((rc = cb(def, &device, NULL, opaque)) != 0)
4562                 return rc;
4563         }
4564         device.type = VIR_DOMAIN_DEVICE_AUDIO;
4565         for (i = 0; i < def->naudios; i++) {
4566             device.data.audio = def->audios[i];
4567             if ((rc = cb(def, &device, NULL, opaque)) != 0)
4568                 return rc;
4569         }
4570         device.type = VIR_DOMAIN_DEVICE_LEASE;
4571         for (i = 0; i < def->nleases; i++) {
4572             device.data.lease = def->leases[i];
4573             if ((rc = cb(def, &device, NULL, opaque)) != 0)
4574                 return rc;
4575         }
4576         device.type = VIR_DOMAIN_DEVICE_IOMMU;
4577         if (def->iommu) {
4578             device.data.iommu = def->iommu;
4579             if ((rc = cb(def, &device, NULL, opaque)) != 0)
4580                 return rc;
4581         }
4582     }
4583 
4584     /* Coverity is not very happy with this - all dead_error_condition */
4585 #if !STATIC_ANALYSIS
4586     /* This switch statement is here to trigger compiler warning when adding
4587      * a new device type. When you are adding a new field to the switch you
4588      * also have to add an iteration statement above. Otherwise the switch
4589      * statement has no real function here and should be optimized out by the
4590      * compiler. */
4591     i = VIR_DOMAIN_DEVICE_LAST;
4592     switch ((virDomainDeviceType) i) {
4593     case VIR_DOMAIN_DEVICE_DISK:
4594     case VIR_DOMAIN_DEVICE_LEASE:
4595     case VIR_DOMAIN_DEVICE_FS:
4596     case VIR_DOMAIN_DEVICE_NET:
4597     case VIR_DOMAIN_DEVICE_INPUT:
4598     case VIR_DOMAIN_DEVICE_SOUND:
4599     case VIR_DOMAIN_DEVICE_VIDEO:
4600     case VIR_DOMAIN_DEVICE_HOSTDEV:
4601     case VIR_DOMAIN_DEVICE_WATCHDOG:
4602     case VIR_DOMAIN_DEVICE_CONTROLLER:
4603     case VIR_DOMAIN_DEVICE_GRAPHICS:
4604     case VIR_DOMAIN_DEVICE_HUB:
4605     case VIR_DOMAIN_DEVICE_REDIRDEV:
4606     case VIR_DOMAIN_DEVICE_NONE:
4607     case VIR_DOMAIN_DEVICE_SMARTCARD:
4608     case VIR_DOMAIN_DEVICE_CHR:
4609     case VIR_DOMAIN_DEVICE_MEMBALLOON:
4610     case VIR_DOMAIN_DEVICE_NVRAM:
4611     case VIR_DOMAIN_DEVICE_SHMEM:
4612     case VIR_DOMAIN_DEVICE_TPM:
4613     case VIR_DOMAIN_DEVICE_PANIC:
4614     case VIR_DOMAIN_DEVICE_LAST:
4615     case VIR_DOMAIN_DEVICE_RNG:
4616     case VIR_DOMAIN_DEVICE_MEMORY:
4617     case VIR_DOMAIN_DEVICE_IOMMU:
4618     case VIR_DOMAIN_DEVICE_VSOCK:
4619     case VIR_DOMAIN_DEVICE_AUDIO:
4620         break;
4621     }
4622 #endif
4623 
4624     return 0;
4625 }
4626 
4627 
4628 int
virDomainDeviceInfoIterate(virDomainDef * def,virDomainDeviceInfoCallback cb,void * opaque)4629 virDomainDeviceInfoIterate(virDomainDef *def,
4630                            virDomainDeviceInfoCallback cb,
4631                            void *opaque)
4632 {
4633     return virDomainDeviceInfoIterateFlags(def, cb, 0, opaque);
4634 }
4635 
4636 
4637 bool
virDomainDefHasDeviceAddress(virDomainDef * def,virDomainDeviceInfo * info)4638 virDomainDefHasDeviceAddress(virDomainDef *def,
4639                              virDomainDeviceInfo *info)
4640 {
4641     if (virDomainDeviceInfoIterateFlags(def,
4642                                         virDomainDefHasDeviceAddressIterator,
4643                                         DOMAIN_DEVICE_ITERATE_ALL_CONSOLES,
4644                                         info) < 0)
4645         return true;
4646 
4647     return false;
4648 }
4649 
4650 
4651 static int
virDomainDefRejectDuplicateControllers(virDomainDef * def)4652 virDomainDefRejectDuplicateControllers(virDomainDef *def)
4653 {
4654     int max_idx[VIR_DOMAIN_CONTROLLER_TYPE_LAST];
4655     virBitmap *bitmaps[VIR_DOMAIN_CONTROLLER_TYPE_LAST] = { NULL };
4656     virDomainControllerDef *cont;
4657     size_t nbitmaps = 0;
4658     int ret = -1;
4659     size_t i;
4660 
4661     memset(max_idx, -1, sizeof(max_idx));
4662 
4663     for (i = 0; i < def->ncontrollers; i++) {
4664         cont = def->controllers[i];
4665         if (cont->idx > max_idx[cont->type])
4666             max_idx[cont->type] = cont->idx;
4667     }
4668 
4669     /* multiple USB controllers with the same index are allowed */
4670     max_idx[VIR_DOMAIN_CONTROLLER_TYPE_USB] = -1;
4671 
4672     for (i = 0; i < VIR_DOMAIN_CONTROLLER_TYPE_LAST; i++) {
4673         if (max_idx[i] >= 0)
4674             bitmaps[i] = virBitmapNew(max_idx[i] + 1);
4675         nbitmaps++;
4676     }
4677 
4678     for (i = 0; i < def->ncontrollers; i++) {
4679         cont = def->controllers[i];
4680 
4681         if (max_idx[cont->type] == -1)
4682             continue;
4683 
4684         if (virBitmapIsBitSet(bitmaps[cont->type], cont->idx)) {
4685             virReportError(VIR_ERR_XML_ERROR,
4686                            _("Multiple '%s' controllers with index '%d'"),
4687                            virDomainControllerTypeToString(cont->type),
4688                            cont->idx);
4689             goto cleanup;
4690         }
4691         ignore_value(virBitmapSetBit(bitmaps[cont->type], cont->idx));
4692     }
4693 
4694     ret = 0;
4695  cleanup:
4696     for (i = 0; i < nbitmaps; i++)
4697         virBitmapFree(bitmaps[i]);
4698     return ret;
4699 }
4700 
4701 static int
virDomainDefRejectDuplicatePanics(virDomainDef * def)4702 virDomainDefRejectDuplicatePanics(virDomainDef *def)
4703 {
4704     bool exists[VIR_DOMAIN_PANIC_MODEL_LAST];
4705     size_t i;
4706 
4707     for (i = 0; i < VIR_DOMAIN_PANIC_MODEL_LAST; i++)
4708          exists[i] = false;
4709 
4710     for (i = 0; i < def->npanics; i++) {
4711         virDomainPanicModel model = def->panics[i]->model;
4712         if (exists[model]) {
4713             virReportError(VIR_ERR_XML_ERROR,
4714                            _("Multiple panic devices with model '%s'"),
4715                            virDomainPanicModelTypeToString(model));
4716             return -1;
4717         }
4718         exists[model] = true;
4719     }
4720 
4721     return 0;
4722 }
4723 
4724 
4725 static int
virDomainDefPostParseMemory(virDomainDef * def,unsigned int parseFlags)4726 virDomainDefPostParseMemory(virDomainDef *def,
4727                             unsigned int parseFlags)
4728 {
4729     size_t i;
4730     unsigned long long numaMemory = 0;
4731     unsigned long long hotplugMemory = 0;
4732 
4733     /* Attempt to infer the initial memory size from the sum NUMA memory sizes
4734      * in case ABI updates are allowed or the <memory> element wasn't specified */
4735     if (def->mem.total_memory == 0 ||
4736         parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE ||
4737         parseFlags & VIR_DOMAIN_DEF_PARSE_ABI_UPDATE_MIGRATION)
4738         numaMemory = virDomainNumaGetMemorySize(def->numa);
4739 
4740     /* calculate the sizes of hotplug memory */
4741     for (i = 0; i < def->nmems; i++)
4742         hotplugMemory += def->mems[i]->size;
4743 
4744     if (numaMemory) {
4745         /* update the sizes in XML if nothing was set in the XML or ABI update
4746          * is supported */
4747         virDomainDefSetMemoryTotal(def, numaMemory + hotplugMemory);
4748     } else {
4749         /* verify that the sum of memory modules doesn't exceed the total
4750          * memory. This is necessary for virDomainDefGetMemoryInitial to work
4751          * properly. */
4752         if (hotplugMemory > def->mem.total_memory) {
4753             virReportError(VIR_ERR_XML_ERROR, "%s",
4754                            _("Total size of memory devices exceeds the total "
4755                              "memory size"));
4756             return -1;
4757         }
4758     }
4759 
4760     if (virDomainDefGetMemoryInitial(def) == 0) {
4761         virReportError(VIR_ERR_XML_ERROR, "%s",
4762                        _("Memory size must be specified via <memory> or in the "
4763                          "<numa> configuration"));
4764         return -1;
4765     }
4766 
4767     if (def->mem.cur_balloon > virDomainDefGetMemoryTotal(def) ||
4768         def->mem.cur_balloon == 0)
4769         def->mem.cur_balloon = virDomainDefGetMemoryTotal(def);
4770 
4771     if ((def->mem.max_memory || def->mem.memory_slots) &&
4772         !(def->mem.max_memory && def->mem.memory_slots)) {
4773         virReportError(VIR_ERR_XML_ERROR, "%s",
4774                        _("both maximum memory size and "
4775                          "memory slot count must be specified"));
4776         return -1;
4777     }
4778 
4779     if (def->mem.max_memory &&
4780         def->mem.max_memory < virDomainDefGetMemoryTotal(def)) {
4781         virReportError(VIR_ERR_XML_ERROR, "%s",
4782                        _("maximum memory size must be equal or greater than "
4783                          "the actual memory size"));
4784         return -1;
4785     }
4786 
4787     return 0;
4788 }
4789 
4790 
4791 static void
virDomainDefPostParseOs(virDomainDef * def)4792 virDomainDefPostParseOs(virDomainDef *def)
4793 {
4794     if (!def->os.loader)
4795         return;
4796 
4797     if (def->os.loader->path &&
4798         def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_NONE) {
4799         /* By default, loader is type of 'rom' */
4800         def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM;
4801     }
4802 }
4803 
4804 
4805 static void
virDomainDefPostParseMemtune(virDomainDef * def)4806 virDomainDefPostParseMemtune(virDomainDef *def)
4807 {
4808     size_t i;
4809 
4810     if (virDomainNumaGetNodeCount(def->numa) == 0) {
4811         /* If guest NUMA is not configured and any hugepage page has nodemask
4812          * set to "0" free and clear that nodemas, otherwise we would rise
4813          * an error that there is no guest NUMA node configured. */
4814         for (i = 0; i < def->mem.nhugepages; i++) {
4815             ssize_t nextBit;
4816 
4817             if (!def->mem.hugepages[i].nodemask)
4818                 continue;
4819 
4820             nextBit = virBitmapNextSetBit(def->mem.hugepages[i].nodemask, 0);
4821             if (nextBit < 0) {
4822                 virBitmapFree(def->mem.hugepages[i].nodemask);
4823                 def->mem.hugepages[i].nodemask = NULL;
4824             }
4825         }
4826     }
4827 }
4828 
4829 
4830 static int
virDomainDefAddConsoleCompat(virDomainDef * def)4831 virDomainDefAddConsoleCompat(virDomainDef *def)
4832 {
4833     size_t i;
4834 
4835     /*
4836      * Some really crazy backcompat stuff for consoles
4837      *
4838      * Historically the first (and only) '<console>' element in an HVM guest
4839      * was treated as being an alias for a <serial> device.
4840      *
4841      * So if we see that this console device should be a serial device, then we
4842      * move the config over to def->serials[0] (or discard it if that already
4843      * exists). However, given console can already be filled with aliased data
4844      * of def->serials[0]. Keep it then.
4845      *
4846      * We then fill def->consoles[0] with a stub just so we get sequencing
4847      * correct for consoles > 0
4848      */
4849 
4850     /* Only the first console (if there are any) can be of type serial,
4851      * verify that no other console is of type serial
4852      */
4853     for (i = 1; i < def->nconsoles; i++) {
4854         virDomainChrDef *cons = def->consoles[i];
4855 
4856         if (cons->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
4857             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
4858                            _("Only the first console can be a serial port"));
4859             return -1;
4860         }
4861     }
4862     if (def->nconsoles > 0 && def->os.type == VIR_DOMAIN_OSTYPE_HVM &&
4863         (def->consoles[0]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL ||
4864          def->consoles[0]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE)) {
4865 
4866         /* If there isn't a corresponding serial port:
4867          *  - create one and set, the console to be an alias for it
4868          *
4869          * If there is a corresponding serial port:
4870          * - Check if the source definition is equal:
4871          *    - if yes: leave it as-is
4872          *    - if no: change the console to be alias of the serial port
4873          */
4874 
4875         /* create the serial port definition from the console definition */
4876         if (def->nserials == 0) {
4877             VIR_APPEND_ELEMENT(def->serials, def->nserials, def->consoles[0]);
4878 
4879             /* modify it to be a serial port */
4880             def->serials[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
4881             def->serials[0]->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE;
4882             def->serials[0]->target.port = 0;
4883         } else {
4884             /* if the console source doesn't match */
4885             if (!virDomainChrSourceDefIsEqual(def->serials[0]->source,
4886                                               def->consoles[0]->source)) {
4887                 virDomainChrDefFree(def->consoles[0]);
4888                 def->consoles[0] = NULL;
4889             }
4890         }
4891 
4892         if (!def->consoles[0]) {
4893             /* allocate a new console type for the stolen one */
4894             if (!(def->consoles[0] = virDomainChrDefNew(NULL)))
4895                 return -1;
4896 
4897             /* Create an console alias for the serial port */
4898             def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
4899             def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
4900         }
4901     } else if (def->os.type == VIR_DOMAIN_OSTYPE_HVM && def->nserials > 0 &&
4902                def->serials[0]->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
4903 
4904         switch ((virDomainChrSerialTargetType) def->serials[0]->targetType) {
4905         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA:
4906         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO:
4907         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM:
4908         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP:
4909         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE: {
4910 
4911             /* Create a stub console to match the serial port.
4912              * console[0] either does not exist
4913              *                or has a different type than SERIAL or NONE.
4914              */
4915             virDomainChrDef *chr;
4916             if (!(chr = virDomainChrDefNew(NULL)))
4917                 return -1;
4918 
4919             if (VIR_INSERT_ELEMENT(def->consoles,
4920                                    0,
4921                                    def->nconsoles,
4922                                    chr) < 0) {
4923                 virDomainChrDefFree(chr);
4924                 return -1;
4925             }
4926 
4927             def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
4928             def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
4929 
4930             break;
4931         }
4932 
4933         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_PCI:
4934         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB:
4935         case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST:
4936             /* Nothing to do */
4937             break;
4938         }
4939     }
4940 
4941     return 0;
4942 }
4943 
4944 
4945 static int
virDomainDefPostParseTimer(virDomainDef * def)4946 virDomainDefPostParseTimer(virDomainDef *def)
4947 {
4948     size_t i;
4949 
4950     /* verify settings of guest timers */
4951     for (i = 0; i < def->clock.ntimers; i++) {
4952         virDomainTimerDef *timer = def->clock.timers[i];
4953 
4954         if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK ||
4955             timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK) {
4956             if (timer->tickpolicy != -1) {
4957                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4958                                _("timer %s doesn't support setting of "
4959                                  "timer tickpolicy"),
4960                                virDomainTimerNameTypeToString(timer->name));
4961                 return -1;
4962             }
4963         }
4964 
4965         if (timer->tickpolicy != VIR_DOMAIN_TIMER_TICKPOLICY_CATCHUP &&
4966             (timer->catchup.threshold != 0 ||
4967              timer->catchup.limit != 0 ||
4968              timer->catchup.slew != 0)) {
4969             virReportError(VIR_ERR_XML_ERROR, "%s",
4970                            _("setting of timer catchup policies is only "
4971                              "supported with tickpolicy='catchup'"));
4972             return -1;
4973         }
4974 
4975         if (timer->name != VIR_DOMAIN_TIMER_NAME_TSC) {
4976             if (timer->frequency != 0) {
4977                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4978                                _("timer %s doesn't support setting of "
4979                                  "timer frequency"),
4980                                virDomainTimerNameTypeToString(timer->name));
4981                 return -1;
4982              }
4983 
4984             if (timer->mode != -1) {
4985                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4986                                _("timer %s doesn't support setting of "
4987                                  "timer mode"),
4988                                virDomainTimerNameTypeToString(timer->name));
4989                 return -1;
4990              }
4991         }
4992 
4993         if (timer->name != VIR_DOMAIN_TIMER_NAME_PLATFORM &&
4994             timer->name != VIR_DOMAIN_TIMER_NAME_RTC) {
4995             if (timer->track != -1) {
4996                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
4997                                _("timer %s doesn't support setting of "
4998                                  "timer track"),
4999                                virDomainTimerNameTypeToString(timer->name));
5000                 return -1;
5001             }
5002         }
5003     }
5004 
5005     return 0;
5006 }
5007 
5008 
5009 static void
virDomainDefPostParseGraphics(virDomainDef * def)5010 virDomainDefPostParseGraphics(virDomainDef *def)
5011 {
5012     size_t i;
5013 
5014     for (i = 0; i < def->ngraphics; i++) {
5015         virDomainGraphicsDef *graphics = def->graphics[i];
5016 
5017         /* If spice graphics is configured without ports and with autoport='no'
5018          * then we start qemu with Spice to not listen anywhere.  Let's convert
5019          * this configuration to the new listen type='none' which does the
5020          * same. */
5021         if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
5022             virDomainGraphicsListenDef *glisten = &graphics->listens[0];
5023 
5024             if (glisten->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS &&
5025                 graphics->data.spice.port == 0 &&
5026                 graphics->data.spice.tlsPort == 0 &&
5027                 !graphics->data.spice.autoport) {
5028                 VIR_FREE(glisten->address);
5029                 glisten->type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE;
5030             }
5031         }
5032     }
5033 }
5034 
5035 
5036 /**
5037  * virDomainDriveAddressIsUsedByDisk:
5038  * @def: domain definition containing the disks to check
5039  * @bus_type: bus type
5040  * @addr: address to check for duplicates
5041  *
5042  * Return true if any disk is already using the given address on the
5043  * given bus, false otherwise.
5044  */
5045 bool
virDomainDriveAddressIsUsedByDisk(const virDomainDef * def,virDomainDiskBus bus_type,const virDomainDeviceDriveAddress * addr)5046 virDomainDriveAddressIsUsedByDisk(const virDomainDef *def,
5047                                   virDomainDiskBus bus_type,
5048                                   const virDomainDeviceDriveAddress *addr)
5049 {
5050     virDomainDiskDef *disk;
5051     size_t i;
5052 
5053     for (i = 0; i < def->ndisks; i++) {
5054         disk = def->disks[i];
5055 
5056         if (disk->bus != bus_type ||
5057             disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
5058             continue;
5059 
5060         if (disk->info.addr.drive.controller == addr->controller &&
5061             disk->info.addr.drive.unit == addr->unit &&
5062             disk->info.addr.drive.bus == addr->bus &&
5063             disk->info.addr.drive.target == addr->target)
5064             return true;
5065     }
5066 
5067     return false;
5068 }
5069 
5070 
5071 /**
5072  * virDomainDriveAddressIsUsedByHostdev:
5073  * @def: domain definition containing the hostdevs to check
5074  * @type: bus type
5075  * @addr: address to check for duplicates
5076  *
5077  * Return true if any hostdev is already using the given address on the
5078  * given bus, false otherwise.
5079  */
5080 static bool
virDomainDriveAddressIsUsedByHostdev(const virDomainDef * def,virDomainHostdevSubsysType type,const virDomainDeviceDriveAddress * addr)5081 virDomainDriveAddressIsUsedByHostdev(const virDomainDef *def,
5082                                      virDomainHostdevSubsysType type,
5083                                      const virDomainDeviceDriveAddress *addr)
5084 {
5085     virDomainHostdevDef *hostdev;
5086     size_t i;
5087 
5088     for (i = 0; i < def->nhostdevs; i++) {
5089         hostdev = def->hostdevs[i];
5090 
5091         if (hostdev->source.subsys.type != type ||
5092             hostdev->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
5093             continue;
5094 
5095         if (hostdev->info->addr.drive.controller == addr->controller &&
5096             hostdev->info->addr.drive.unit == addr->unit &&
5097             hostdev->info->addr.drive.bus == addr->bus &&
5098             hostdev->info->addr.drive.target == addr->target)
5099             return true;
5100     }
5101 
5102     return false;
5103 }
5104 
5105 
5106 /**
5107  * virDomainSCSIDriveAddressIsUsed:
5108  * @def: domain definition to check against
5109  * @addr: address to check for duplicates
5110  *
5111  * Return true if the SCSI drive address is already in use, false
5112  * otherwise.
5113  */
5114 bool
virDomainSCSIDriveAddressIsUsed(const virDomainDef * def,const virDomainDeviceDriveAddress * addr)5115 virDomainSCSIDriveAddressIsUsed(const virDomainDef *def,
5116                                 const virDomainDeviceDriveAddress *addr)
5117 {
5118     const virDomainControllerDef *cont;
5119 
5120     cont = virDomainDeviceFindSCSIController(def, addr);
5121     if (cont) {
5122         int max = -1;
5123         int reserved = -1;
5124 
5125         /* Different controllers have different limits. These limits here are
5126          * taken from QEMU source code, but nevertheless they should apply to
5127          * other hypervisors too. */
5128         switch ((virDomainControllerModelSCSI) cont->model) {
5129         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI:
5130         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL:
5131         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL:
5132             max = 16383;
5133             break;
5134         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_IBMVSCSI:
5135             max = 31;
5136             reserved = 7;
5137             break;
5138         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1068:
5139             max = 1;
5140             break;
5141         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSISAS1078:
5142             max = 255;
5143             break;
5144         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LSILOGIC:
5145             reserved = 7;
5146             break;
5147         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VMPVSCSI:
5148             reserved = 7;
5149             break;
5150         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_BUSLOGIC:
5151             reserved = 7;
5152             break;
5153         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_NCR53C90:
5154         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DC390:
5155         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AM53C974:
5156             max = 6;
5157             break;
5158         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT:
5159         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_AUTO:
5160         case VIR_DOMAIN_CONTROLLER_MODEL_SCSI_LAST:
5161             break;
5162         }
5163 
5164         if (max != -1 && addr->unit > max)
5165             return true;
5166         if (reserved != -1 && addr->unit == reserved)
5167             return true;
5168     }
5169 
5170     if (virDomainDriveAddressIsUsedByDisk(def, VIR_DOMAIN_DISK_BUS_SCSI,
5171                                           addr) ||
5172         virDomainDriveAddressIsUsedByHostdev(def,
5173                                              VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI,
5174                                              addr))
5175         return true;
5176 
5177     return false;
5178 }
5179 
5180 
5181 /* Find out the next usable "unit" of a specific controller */
5182 static int
virDomainControllerSCSINextUnit(const virDomainDef * def,unsigned int controller)5183 virDomainControllerSCSINextUnit(const virDomainDef *def,
5184                                 unsigned int controller)
5185 {
5186     size_t i;
5187 
5188     for (i = 0; i < def->scsiBusMaxUnit; i++) {
5189         /* Default to assigning addresses using bus = target = 0 */
5190         const virDomainDeviceDriveAddress addr = {controller, 0, 0, i, 0};
5191 
5192         if (!virDomainSCSIDriveAddressIsUsed(def, &addr))
5193             return i;
5194     }
5195 
5196     return -1;
5197 }
5198 
5199 
5200 static void
virDomainHostdevAssignAddress(virDomainXMLOption * xmlopt G_GNUC_UNUSED,const virDomainDef * def,virDomainHostdevDef * hostdev)5201 virDomainHostdevAssignAddress(virDomainXMLOption *xmlopt G_GNUC_UNUSED,
5202                               const virDomainDef *def,
5203                               virDomainHostdevDef *hostdev)
5204 {
5205     int next_unit = 0;
5206     int controller = 0;
5207 
5208     /* NB: Do not attempt calling virDomainDefMaybeAddController to
5209      * automagically add a "new" controller. Doing so will result in
5210      * qemuDomainFindOrCreateSCSIDiskController "finding" the controller
5211      * in the domain def list and thus not hotplugging the controller as
5212      * well as the hostdev in the event that there are either no SCSI
5213      * controllers defined or there was no space on an existing one.
5214      *
5215      * Because we cannot add a controller, then we should not walk the
5216      * defined controllers list in order to find empty space. Doing
5217      * so fails to return the valid next unit number for the 2nd
5218      * hostdev being added to the as yet to be created controller.
5219      */
5220     do {
5221         next_unit = virDomainControllerSCSINextUnit(def, controller);
5222         if (next_unit < 0)
5223             controller++;
5224     } while (next_unit < 0);
5225 
5226 
5227     hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
5228     hostdev->info->addr.drive.controller = controller;
5229     hostdev->info->addr.drive.bus = 0;
5230     hostdev->info->addr.drive.target = 0;
5231     hostdev->info->addr.drive.unit = next_unit;
5232 }
5233 
5234 
5235 /**
5236  * virDomainPostParseCheckISCSIPath
5237  * @srcpath: Source path read (a/k/a, IQN) either disk or hostdev
5238  *
5239  * The details of an IQN is defined by RFC 3720 and 3721, but
5240  * we just need to make sure there's a lun provided. If not
5241  * provided, then default to zero. For an ISCSI LUN that is
5242  * is provided by /dev/disk/by-path/... , then that path will
5243  * have the specific lun requested.
5244  */
5245 static void
virDomainPostParseCheckISCSIPath(char ** srcpath)5246 virDomainPostParseCheckISCSIPath(char **srcpath)
5247 {
5248     char *path = NULL;
5249 
5250     if (strchr(*srcpath, '/'))
5251         return;
5252 
5253     path = g_strdup_printf("%s/0", *srcpath);
5254     g_free(*srcpath);
5255     *srcpath = g_steal_pointer(&path);
5256 }
5257 
5258 
5259 static int
virDomainHostdevDefPostParse(virDomainHostdevDef * dev,const virDomainDef * def,virDomainXMLOption * xmlopt)5260 virDomainHostdevDefPostParse(virDomainHostdevDef *dev,
5261                              const virDomainDef *def,
5262                              virDomainXMLOption *xmlopt)
5263 {
5264     virDomainHostdevSubsysSCSI *scsisrc;
5265     virDomainDeviceDriveAddress *addr = NULL;
5266 
5267     if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
5268         return 0;
5269 
5270     switch (dev->source.subsys.type) {
5271     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
5272         scsisrc = &dev->source.subsys.u.scsi;
5273         if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
5274             virDomainHostdevSubsysSCSIiSCSI *iscsisrc = &scsisrc->u.iscsi;
5275             virDomainPostParseCheckISCSIPath(&iscsisrc->src->path);
5276         }
5277 
5278         if (dev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
5279             virDomainHostdevAssignAddress(xmlopt, def, dev);
5280 
5281         /* Ensure provided address doesn't conflict with existing
5282          * scsi disk drive address
5283          */
5284         addr = &dev->info->addr.drive;
5285         if (virDomainDriveAddressIsUsedByDisk(def,
5286                                               VIR_DOMAIN_DISK_BUS_SCSI,
5287                                               addr)) {
5288             virReportError(VIR_ERR_XML_ERROR,
5289                            _("SCSI host address controller='%u' "
5290                              "bus='%u' target='%u' unit='%u' in "
5291                              "use by a SCSI disk"),
5292                            addr->controller, addr->bus,
5293                            addr->target, addr->unit);
5294             return -1;
5295         }
5296         break;
5297     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: {
5298         int model = dev->source.subsys.u.mdev.model;
5299 
5300         if (dev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
5301             return 0;
5302 
5303         if ((model == VIR_MDEV_MODEL_TYPE_VFIO_PCI &&
5304              dev->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) ||
5305             (model == VIR_MDEV_MODEL_TYPE_VFIO_CCW &&
5306              dev->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW)) {
5307             virReportError(VIR_ERR_XML_ERROR,
5308                            _("Unsupported address type '%s' with mediated "
5309                              "device model '%s'"),
5310                            virDomainDeviceAddressTypeToString(dev->info->type),
5311                            virMediatedDeviceModelTypeToString(model));
5312             return -1;
5313         }
5314     }
5315 
5316     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
5317     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
5318     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
5319     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
5320         break;
5321     }
5322 
5323     return 0;
5324 }
5325 
5326 
5327 static void
virDomainChrDefPostParse(virDomainChrDef * chr,const virDomainDef * def)5328 virDomainChrDefPostParse(virDomainChrDef *chr,
5329                          const virDomainDef *def)
5330 {
5331     const virDomainChrDef **arrPtr;
5332     size_t i, cnt;
5333 
5334     virDomainChrGetDomainPtrs(def, chr->deviceType, &arrPtr, &cnt);
5335 
5336     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
5337         chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE) {
5338         chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
5339     }
5340 
5341     if (chr->target.port == -1 &&
5342         (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL ||
5343          chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL ||
5344          chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE)) {
5345         int maxport = -1;
5346 
5347         for (i = 0; i < cnt; i++) {
5348             if (arrPtr[i]->target.port > maxport)
5349                 maxport = arrPtr[i]->target.port;
5350         }
5351 
5352         chr->target.port = maxport + 1;
5353     }
5354 }
5355 
5356 
5357 static void
virDomainRNGDefPostParse(virDomainRNGDef * rng)5358 virDomainRNGDefPostParse(virDomainRNGDef *rng)
5359 {
5360     /* set default path for virtio-rng "random" backend to /dev/random */
5361     if (rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM &&
5362         !rng->source.file) {
5363         rng->source.file = g_strdup("/dev/random");
5364     }
5365 }
5366 
5367 
5368 static void
virDomainDiskExpandGroupIoTune(virDomainDiskDef * disk,const virDomainDef * def)5369 virDomainDiskExpandGroupIoTune(virDomainDiskDef *disk,
5370                                const virDomainDef *def)
5371 {
5372     size_t i;
5373 
5374     if (!disk->blkdeviotune.group_name ||
5375         virDomainBlockIoTuneInfoHasAny(&disk->blkdeviotune))
5376         return;
5377 
5378     for (i = 0; i < def->ndisks; i++) {
5379         virDomainDiskDef *d = def->disks[i];
5380 
5381         if (STRNEQ_NULLABLE(disk->blkdeviotune.group_name, d->blkdeviotune.group_name) ||
5382             !virDomainBlockIoTuneInfoHasAny(&d->blkdeviotune))
5383             continue;
5384 
5385 
5386         VIR_FREE(disk->blkdeviotune.group_name);
5387         virDomainBlockIoTuneInfoCopy(&d->blkdeviotune, &disk->blkdeviotune);
5388 
5389         return;
5390     }
5391 }
5392 
5393 
5394 static int
virDomainDiskDefPostParse(virDomainDiskDef * disk,const virDomainDef * def,virDomainXMLOption * xmlopt)5395 virDomainDiskDefPostParse(virDomainDiskDef *disk,
5396                           const virDomainDef *def,
5397                           virDomainXMLOption *xmlopt)
5398 {
5399     if (disk->dst) {
5400         char *newdst;
5401 
5402         /* Work around for compat with Xen driver in previous libvirt releases */
5403         if ((newdst = g_strdup(STRSKIP(disk->dst, "ioemu:")))) {
5404             g_free(disk->dst);
5405             disk->dst = newdst;
5406         }
5407     }
5408 
5409     /* Force CDROM to be listed as read only */
5410     if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
5411         disk->src->readonly = true;
5412 
5413     if (disk->bus == VIR_DOMAIN_DISK_BUS_NONE) {
5414         disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
5415 
5416         if (disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
5417             disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
5418         } else if (disk->dst) {
5419             if (STRPREFIX(disk->dst, "hd"))
5420                 disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
5421             else if (STRPREFIX(disk->dst, "sd"))
5422                 disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
5423             else if (STRPREFIX(disk->dst, "vd"))
5424                 disk->bus = VIR_DOMAIN_DISK_BUS_VIRTIO;
5425             else if (STRPREFIX(disk->dst, "xvd"))
5426                 disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
5427             else if (STRPREFIX(disk->dst, "ubd"))
5428                 disk->bus = VIR_DOMAIN_DISK_BUS_UML;
5429         }
5430     }
5431 
5432     if (disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT &&
5433         disk->src->readonly)
5434         disk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
5435 
5436     if (disk->src->type == VIR_STORAGE_TYPE_NETWORK &&
5437         disk->src->protocol == VIR_STORAGE_NET_PROTOCOL_ISCSI) {
5438         virDomainPostParseCheckISCSIPath(&disk->src->path);
5439     }
5440 
5441     if (disk->src->type == VIR_STORAGE_TYPE_NVME) {
5442         if (disk->src->nvme->managed == VIR_TRISTATE_BOOL_ABSENT)
5443             disk->src->nvme->managed = VIR_TRISTATE_BOOL_YES;
5444     }
5445 
5446     /* vhost-user doesn't allow us to snapshot, disable snapshots by default */
5447     if (disk->src->type == VIR_STORAGE_TYPE_VHOST_USER &&
5448         disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_DEFAULT) {
5449         disk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE;
5450     }
5451 
5452     if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
5453         disk->dst &&
5454         virDomainDiskDefAssignAddress(xmlopt, disk, def) < 0) {
5455         return -1;
5456     }
5457 
5458     virDomainDiskExpandGroupIoTune(disk, def);
5459 
5460     return 0;
5461 }
5462 
5463 
5464 static void
virDomainVideoDefPostParse(virDomainVideoDef * video,const virDomainDef * def)5465 virDomainVideoDefPostParse(virDomainVideoDef *video,
5466                            const virDomainDef *def)
5467 {
5468     /* Fill out (V)RAM if the driver-specific callback did not do so */
5469     if (video->ram == 0 && video->type == VIR_DOMAIN_VIDEO_TYPE_QXL)
5470         video->ram = virDomainVideoDefaultRAM(def, video->type);
5471     if (video->vram == 0)
5472         video->vram = virDomainVideoDefaultRAM(def, video->type);
5473 
5474     video->ram = VIR_ROUND_UP_POWER_OF_TWO(video->ram);
5475     video->vram = VIR_ROUND_UP_POWER_OF_TWO(video->vram);
5476 }
5477 
5478 
5479 static int
virDomainControllerDefPostParse(virDomainControllerDef * cdev)5480 virDomainControllerDefPostParse(virDomainControllerDef *cdev)
5481 {
5482     if (cdev->iothread &&
5483         cdev->model != VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI &&
5484         cdev->model != VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_TRANSITIONAL &&
5485         cdev->model != VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_NON_TRANSITIONAL) {
5486         virReportError(VIR_ERR_XML_ERROR, "%s",
5487                        _("'iothread' attribute only supported for "
5488                          "virtio scsi controllers"));
5489         return -1;
5490     }
5491 
5492     return 0;
5493 }
5494 
5495 
5496 static void
virDomainVsockDefPostParse(virDomainVsockDef * vsock)5497 virDomainVsockDefPostParse(virDomainVsockDef *vsock)
5498 {
5499     if (vsock->auto_cid == VIR_TRISTATE_BOOL_ABSENT) {
5500         if (vsock->guest_cid != 0)
5501             vsock->auto_cid = VIR_TRISTATE_BOOL_NO;
5502         else
5503             vsock->auto_cid = VIR_TRISTATE_BOOL_YES;
5504     }
5505 }
5506 
5507 
5508 static int
virDomainMemoryDefPostParse(virDomainMemoryDef * mem,const virDomainDef * def)5509 virDomainMemoryDefPostParse(virDomainMemoryDef *mem,
5510                             const virDomainDef *def)
5511 {
5512     switch (mem->model) {
5513     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
5514         /* Virtio-pmem mandates shared access so that guest writes get
5515          * reflected in the underlying file. */
5516         if (mem->access == VIR_DOMAIN_MEMORY_ACCESS_DEFAULT)
5517             mem->access = VIR_DOMAIN_MEMORY_ACCESS_SHARED;
5518         break;
5519 
5520     case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
5521         /* If no NVDIMM UUID was provided in XML, generate one. */
5522         if (ARCH_IS_PPC64(def->os.arch) &&
5523             !mem->uuid) {
5524 
5525             mem->uuid = g_new0(unsigned char, VIR_UUID_BUFLEN);
5526             if (virUUIDGenerate(mem->uuid) < 0) {
5527                 virReportError(VIR_ERR_INTERNAL_ERROR,
5528                                "%s", _("Failed to generate UUID"));
5529                 return -1;
5530             }
5531         }
5532         break;
5533 
5534     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
5535     case VIR_DOMAIN_MEMORY_MODEL_DIMM:
5536     case VIR_DOMAIN_MEMORY_MODEL_NONE:
5537     case VIR_DOMAIN_MEMORY_MODEL_LAST:
5538         break;
5539     }
5540 
5541     return 0;
5542 }
5543 
5544 
5545 static int
virDomainFSDefPostParse(virDomainFSDef * fs)5546 virDomainFSDefPostParse(virDomainFSDef *fs)
5547 {
5548     if (fs->accessmode == VIR_DOMAIN_FS_ACCESSMODE_DEFAULT && !fs->sock)
5549         fs->accessmode = VIR_DOMAIN_FS_ACCESSMODE_PASSTHROUGH;
5550 
5551     return 0;
5552 }
5553 
5554 
5555 static int
virDomainDeviceDefPostParseCommon(virDomainDeviceDef * dev,const virDomainDef * def,unsigned int parseFlags G_GNUC_UNUSED,virDomainXMLOption * xmlopt)5556 virDomainDeviceDefPostParseCommon(virDomainDeviceDef *dev,
5557                                   const virDomainDef *def,
5558                                   unsigned int parseFlags G_GNUC_UNUSED,
5559                                   virDomainXMLOption *xmlopt)
5560 {
5561     int ret = -1;
5562 
5563     switch ((virDomainDeviceType)dev->type) {
5564     case VIR_DOMAIN_DEVICE_CHR:
5565         virDomainChrDefPostParse(dev->data.chr, def);
5566         ret = 0;
5567         break;
5568 
5569     case VIR_DOMAIN_DEVICE_RNG:
5570         virDomainRNGDefPostParse(dev->data.rng);
5571         ret = 0;
5572         break;
5573 
5574     case VIR_DOMAIN_DEVICE_DISK:
5575         ret = virDomainDiskDefPostParse(dev->data.disk, def, xmlopt);
5576         break;
5577 
5578     case VIR_DOMAIN_DEVICE_VIDEO:
5579         virDomainVideoDefPostParse(dev->data.video, def);
5580         ret = 0;
5581         break;
5582 
5583     case VIR_DOMAIN_DEVICE_HOSTDEV:
5584         ret = virDomainHostdevDefPostParse(dev->data.hostdev, def, xmlopt);
5585         break;
5586 
5587     case VIR_DOMAIN_DEVICE_CONTROLLER:
5588         ret = virDomainControllerDefPostParse(dev->data.controller);
5589         break;
5590 
5591     case VIR_DOMAIN_DEVICE_VSOCK:
5592         virDomainVsockDefPostParse(dev->data.vsock);
5593         ret = 0;
5594         break;
5595 
5596     case VIR_DOMAIN_DEVICE_MEMORY:
5597         ret = virDomainMemoryDefPostParse(dev->data.memory, def);
5598         break;
5599 
5600     case VIR_DOMAIN_DEVICE_FS:
5601         ret = virDomainFSDefPostParse(dev->data.fs);
5602         break;
5603 
5604     case VIR_DOMAIN_DEVICE_LEASE:
5605     case VIR_DOMAIN_DEVICE_NET:
5606     case VIR_DOMAIN_DEVICE_INPUT:
5607     case VIR_DOMAIN_DEVICE_SOUND:
5608     case VIR_DOMAIN_DEVICE_WATCHDOG:
5609     case VIR_DOMAIN_DEVICE_GRAPHICS:
5610     case VIR_DOMAIN_DEVICE_HUB:
5611     case VIR_DOMAIN_DEVICE_REDIRDEV:
5612     case VIR_DOMAIN_DEVICE_SMARTCARD:
5613     case VIR_DOMAIN_DEVICE_MEMBALLOON:
5614     case VIR_DOMAIN_DEVICE_NVRAM:
5615     case VIR_DOMAIN_DEVICE_SHMEM:
5616     case VIR_DOMAIN_DEVICE_TPM:
5617     case VIR_DOMAIN_DEVICE_PANIC:
5618     case VIR_DOMAIN_DEVICE_IOMMU:
5619     case VIR_DOMAIN_DEVICE_AUDIO:
5620         ret = 0;
5621         break;
5622 
5623     case VIR_DOMAIN_DEVICE_NONE:
5624         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
5625                        _("unexpected VIR_DOMAIN_DEVICE_NONE"));
5626         break;
5627 
5628     case VIR_DOMAIN_DEVICE_LAST:
5629     default:
5630         virReportEnumRangeError(virDomainDeviceType, dev->type);
5631         break;
5632     }
5633 
5634     return ret;
5635 }
5636 
5637 
5638 /**
5639  * virDomainDefRemoveOfflineVcpuPin:
5640  * @def: domain definition
5641  *
5642  * This function removes vcpu pinning information from offline vcpus. This is
5643  * designed to be used for drivers which don't support offline vcpupin.
5644  */
5645 static void
virDomainDefRemoveOfflineVcpuPin(virDomainDef * def)5646 virDomainDefRemoveOfflineVcpuPin(virDomainDef *def)
5647 {
5648     size_t i;
5649     virDomainVcpuDef *vcpu;
5650 
5651     for (i = 0; i < virDomainDefGetVcpusMax(def); i++) {
5652         vcpu = virDomainDefGetVcpu(def, i);
5653 
5654         if (vcpu && !vcpu->online && vcpu->cpumask) {
5655             virBitmapFree(vcpu->cpumask);
5656             vcpu->cpumask = NULL;
5657 
5658             VIR_WARN("Ignoring unsupported vcpupin for offline vcpu '%zu'", i);
5659         }
5660     }
5661 }
5662 
5663 
5664 static void
virDomainAssignControllerIndexes(virDomainDef * def)5665 virDomainAssignControllerIndexes(virDomainDef *def)
5666 {
5667     /* the index attribute of a controller is optional in the XML, but
5668      * is required to be valid at any time after parse. When no index
5669      * is provided for a controller, assign one automatically by
5670      * looking at what indexes are already used for that controller
5671      * type in the domain - the unindexed controller gets the lowest
5672      * unused index.
5673      */
5674     size_t outer;
5675 
5676     for (outer = 0; outer < def->ncontrollers; outer++) {
5677         virDomainControllerDef *cont = def->controllers[outer];
5678         virDomainControllerDef *prev = NULL;
5679         size_t inner;
5680 
5681         if (cont->idx != -1)
5682             continue;
5683 
5684         if (outer > 0 && IS_USB2_CONTROLLER(cont)) {
5685             /* USB2 controllers are the only exception to the simple
5686              * "assign the lowest unused index". A group of USB2
5687              * "companions" should all be at the same index as other
5688              * USB2 controllers in the group, but only do this
5689              * automatically if it appears to be the intent. To prove
5690              * intent: the USB controller on the list just prior to
5691              * this one must also be a USB2 controller, and there must
5692              * not yet be a controller with the exact same model of
5693              * this one and the same index as the previously added
5694              * controller (e.g., if this controller is a UHCI1, then
5695              * the previous controller must be an EHCI1 or a UHCI[23],
5696              * and there must not already be a UHCI1 controller with
5697              * the same index as the previous controller). If all of
5698              * these are satisfied, set this controller to the same
5699              * index as the previous controller.
5700              */
5701             int prevIdx;
5702 
5703             prevIdx = outer - 1;
5704             while (prevIdx >= 0 &&
5705                    def->controllers[prevIdx]->type != VIR_DOMAIN_CONTROLLER_TYPE_USB)
5706                 prevIdx--;
5707             if (prevIdx >= 0)
5708                 prev = def->controllers[prevIdx];
5709             /* if the last USB controller isn't USB2, that breaks
5710              * the chain, so we need a new index for this new
5711              * controller
5712              */
5713             if (prev && !IS_USB2_CONTROLLER(prev))
5714                 prev = NULL;
5715 
5716             /* if prev != NULL, we've found a potential index to
5717              * use. Make sure this index isn't already used by an
5718              * existing USB2 controller of the same model as the new
5719              * one.
5720              */
5721             for (inner = 0; prev && inner < def->ncontrollers; inner++) {
5722                 if (def->controllers[inner]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
5723                     def->controllers[inner]->idx == prev->idx &&
5724                     def->controllers[inner]->model == cont->model) {
5725                     /* we already have a controller of this model with
5726                      * the proposed index, so we need to move to a new
5727                      * index for this controller
5728                      */
5729                     prev = NULL;
5730                 }
5731             }
5732             if (prev)
5733                 cont->idx = prev->idx;
5734         }
5735         /* if none of the above applied, prev will be NULL */
5736         if (!prev)
5737             cont->idx = virDomainControllerFindUnusedIndex(def, cont->type);
5738     }
5739 }
5740 
5741 
5742 #define UNSUPPORTED(FEATURE) (!((FEATURE) & xmlopt->config.features))
5743 /**
5744  * virDomainDefPostParseCheckFeatures:
5745  * @def: domain definition
5746  * @xmlopt: XML parser option object
5747  *
5748  * This function checks that the domain configuration is supported according to
5749  * the supported features for a given hypervisor. See virDomainDefFeatures and
5750  * virDomainDefParserConfig.
5751  *
5752  * Returns 0 on success and -1 on error with an appropriate libvirt error.
5753  */
5754 static int
virDomainDefPostParseCheckFeatures(virDomainDef * def,virDomainXMLOption * xmlopt)5755 virDomainDefPostParseCheckFeatures(virDomainDef *def,
5756                                    virDomainXMLOption *xmlopt)
5757 {
5758     if (UNSUPPORTED(VIR_DOMAIN_DEF_FEATURE_MEMORY_HOTPLUG) &&
5759         virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
5760         return -1;
5761 
5762     if (UNSUPPORTED(VIR_DOMAIN_DEF_FEATURE_OFFLINE_VCPUPIN))
5763         virDomainDefRemoveOfflineVcpuPin(def);
5764 
5765     if (UNSUPPORTED(VIR_DOMAIN_DEF_FEATURE_NAME_SLASH)) {
5766         if (def->name && strchr(def->name, '/')) {
5767             virReportError(VIR_ERR_XML_ERROR,
5768                            _("name %s cannot contain '/'"), def->name);
5769             return -1;
5770         }
5771     }
5772 
5773     if (UNSUPPORTED(VIR_DOMAIN_DEF_FEATURE_INDIVIDUAL_VCPUS) &&
5774         def->individualvcpus) {
5775         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5776                        _("individual CPU state configuration is not supported"));
5777         return -1;
5778     }
5779 
5780     return 0;
5781 }
5782 
5783 
5784 /**
5785  * virDomainDeviceDefPostParseCheckFeatures:
5786  * @dev: device definition
5787  * @xmlopt: XML parser option object
5788  *
5789  * This function checks that the device configuration is supported according to
5790  * the supported features for a given hypervisor. See virDomainDefFeatures and
5791  * virDomainDefParserConfig.
5792  *
5793  * Returns 0 on success and -1 on error with an appropriate libvirt error.
5794  */
5795 static int
virDomainDeviceDefPostParseCheckFeatures(virDomainDeviceDef * dev,virDomainXMLOption * xmlopt)5796 virDomainDeviceDefPostParseCheckFeatures(virDomainDeviceDef *dev,
5797                                          virDomainXMLOption *xmlopt)
5798 {
5799     if (UNSUPPORTED(VIR_DOMAIN_DEF_FEATURE_MEMORY_HOTPLUG) &&
5800         virDomainDeviceDefCheckUnsupportedMemoryDevice(dev) < 0)
5801         return -1;
5802 
5803     if (UNSUPPORTED(VIR_DOMAIN_DEF_FEATURE_NET_MODEL_STRING) &&
5804         dev->type == VIR_DOMAIN_DEVICE_NET &&
5805         dev->data.net->modelstr) {
5806         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5807                        _("driver does not support net model '%s'"),
5808                        dev->data.net->modelstr);
5809         return -1;
5810     }
5811 
5812     return 0;
5813 }
5814 #undef UNSUPPORTED
5815 
5816 
5817 static int
virDomainDeviceDefPostParse(virDomainDeviceDef * dev,const virDomainDef * def,unsigned int flags,virDomainXMLOption * xmlopt,void * parseOpaque)5818 virDomainDeviceDefPostParse(virDomainDeviceDef *dev,
5819                             const virDomainDef *def,
5820                             unsigned int flags,
5821                             virDomainXMLOption *xmlopt,
5822                             void *parseOpaque)
5823 {
5824     int ret;
5825 
5826     if (xmlopt->config.devicesPostParseCallback) {
5827         ret = xmlopt->config.devicesPostParseCallback(dev, def, flags,
5828                                                       xmlopt->config.priv,
5829                                                       parseOpaque);
5830         if (ret < 0)
5831             return ret;
5832     }
5833 
5834     if ((ret = virDomainDeviceDefPostParseCommon(dev, def, flags, xmlopt)) < 0)
5835         return ret;
5836 
5837     if (virDomainDeviceDefPostParseCheckFeatures(dev, xmlopt) < 0)
5838         return -1;
5839 
5840     return 0;
5841 }
5842 
5843 static int
virDomainDeviceDefPostParseOne(virDomainDeviceDef * dev,const virDomainDef * def,unsigned int flags,virDomainXMLOption * xmlopt,void * parseOpaque)5844 virDomainDeviceDefPostParseOne(virDomainDeviceDef *dev,
5845                                const virDomainDef *def,
5846                                unsigned int flags,
5847                                virDomainXMLOption *xmlopt,
5848                                void *parseOpaque)
5849 {
5850     void *data = NULL;
5851     int ret;
5852 
5853     if (!parseOpaque && xmlopt->config.domainPostParseDataAlloc) {
5854         if (xmlopt->config.domainPostParseDataAlloc(def, flags,
5855                                                     xmlopt->config.priv,
5856                                                     &data) < 0)
5857             return -1;
5858         parseOpaque = data;
5859     }
5860 
5861     ret = virDomainDeviceDefPostParse(dev, def, flags, xmlopt, parseOpaque);
5862 
5863     if (data && xmlopt->config.domainPostParseDataFree)
5864         xmlopt->config.domainPostParseDataFree(data);
5865 
5866     return ret;
5867 }
5868 
5869 
5870 static int
virDomainDefPostParseDeviceIterator(virDomainDef * def,virDomainDeviceDef * dev,virDomainDeviceInfo * info G_GNUC_UNUSED,void * opaque)5871 virDomainDefPostParseDeviceIterator(virDomainDef *def,
5872                                     virDomainDeviceDef *dev,
5873                                     virDomainDeviceInfo *info G_GNUC_UNUSED,
5874                                     void *opaque)
5875 {
5876     struct virDomainDefPostParseDeviceIteratorData *data = opaque;
5877     return virDomainDeviceDefPostParse(dev, def,
5878                                        data->parseFlags, data->xmlopt,
5879                                        data->parseOpaque);
5880 }
5881 
5882 
5883 static int
virDomainVcpuDefPostParse(virDomainDef * def)5884 virDomainVcpuDefPostParse(virDomainDef *def)
5885 {
5886     virDomainVcpuDef *vcpu;
5887     size_t maxvcpus = virDomainDefGetVcpusMax(def);
5888     size_t i;
5889 
5890     for (i = 0; i < maxvcpus; i++) {
5891         vcpu = virDomainDefGetVcpu(def, i);
5892 
5893         /* impossible but some compilers don't like it */
5894         if (!vcpu)
5895             continue;
5896 
5897         switch (vcpu->hotpluggable) {
5898         case VIR_TRISTATE_BOOL_ABSENT:
5899             if (vcpu->online)
5900                 vcpu->hotpluggable = VIR_TRISTATE_BOOL_NO;
5901             else
5902                 vcpu->hotpluggable = VIR_TRISTATE_BOOL_YES;
5903             break;
5904 
5905         case VIR_TRISTATE_BOOL_NO:
5906             if (!vcpu->online) {
5907                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5908                                _("vcpu '%zu' is both offline and not "
5909                                  "hotpluggable"), i);
5910                 return -1;
5911             }
5912             break;
5913 
5914         case VIR_TRISTATE_BOOL_YES:
5915         case VIR_TRISTATE_BOOL_LAST:
5916             break;
5917         }
5918     }
5919 
5920     return 0;
5921 }
5922 
5923 
5924 static int
virDomainDefPostParseCPU(virDomainDef * def)5925 virDomainDefPostParseCPU(virDomainDef *def)
5926 {
5927     if (!def->cpu)
5928         return 0;
5929 
5930     if (def->cpu->mode == VIR_CPU_MODE_CUSTOM &&
5931         !def->cpu->model &&
5932         def->cpu->check != VIR_CPU_CHECK_DEFAULT) {
5933         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5934                        _("check attribute specified for CPU with no model"));
5935         return -1;
5936     }
5937 
5938     return 0;
5939 }
5940 
5941 
5942 static int
virDomainDefCollectBootOrder(virDomainDef * def G_GNUC_UNUSED,virDomainDeviceDef * dev G_GNUC_UNUSED,virDomainDeviceInfo * info,void * data)5943 virDomainDefCollectBootOrder(virDomainDef *def G_GNUC_UNUSED,
5944                              virDomainDeviceDef *dev G_GNUC_UNUSED,
5945                              virDomainDeviceInfo *info,
5946                              void *data)
5947 {
5948     GHashTable *bootHash = data;
5949     g_autofree char *order = NULL;
5950 
5951     if (info->bootIndex == 0)
5952         return 0;
5953 
5954     if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
5955         dev->data.hostdev->parentnet) {
5956         /* This hostdev is a child of a higher level device
5957          * (e.g. interface), and thus already being counted on the
5958          * list for the other device type.
5959          */
5960         return 0;
5961     }
5962     order = g_strdup_printf("%u", info->bootIndex);
5963 
5964     if (virHashLookup(bootHash, order)) {
5965         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
5966                        _("boot order '%s' used for more than one device"),
5967                        order);
5968         return -1;
5969     }
5970 
5971     if (virHashAddEntry(bootHash, order, (void *) 1) < 0)
5972         return -1;
5973 
5974     return 0;
5975 }
5976 
5977 
5978 static int
virDomainDefBootOrderPostParse(virDomainDef * def)5979 virDomainDefBootOrderPostParse(virDomainDef *def)
5980 {
5981     g_autoptr(GHashTable) bootHash = virHashNew(NULL);
5982 
5983     if (virDomainDeviceInfoIterate(def, virDomainDefCollectBootOrder, bootHash) < 0)
5984         return -1;
5985 
5986     if (def->os.nBootDevs > 0 && virHashSize(bootHash) > 0) {
5987         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
5988                        _("per-device boot elements cannot be used"
5989                          " together with os/boot elements"));
5990         return -1;
5991     }
5992 
5993     if (def->os.nBootDevs == 0 && virHashSize(bootHash) == 0) {
5994         def->os.nBootDevs = 1;
5995         def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
5996     }
5997 
5998     return 0;
5999 }
6000 
6001 
6002 static int
virDomainDefPostParseVideo(virDomainDef * def,void * opaque)6003 virDomainDefPostParseVideo(virDomainDef *def,
6004                            void *opaque)
6005 {
6006     if (def->nvideos == 0)
6007         return 0;
6008 
6009     if (def->videos[0]->type == VIR_DOMAIN_VIDEO_TYPE_NONE) {
6010         char *alias;
6011 
6012         /* we don't want to format any values we automatically fill in for
6013          * videos into the XML, so clear them, but retain any user-assigned
6014          * alias */
6015         alias = g_steal_pointer(&def->videos[0]->info.alias);
6016         virDomainVideoDefClear(def->videos[0]);
6017         def->videos[0]->type = VIR_DOMAIN_VIDEO_TYPE_NONE;
6018         def->videos[0]->info.alias = g_steal_pointer(&alias);
6019     } else {
6020         virDomainDeviceDef device = {
6021             .type = VIR_DOMAIN_DEVICE_VIDEO,
6022             .data.video = def->videos[0],
6023         };
6024 
6025         /* Mark the first video as primary. If the user specified
6026          * primary="yes", the parser already inserted the device at
6027          * def->videos[0]
6028          */
6029         def->videos[0]->primary = true;
6030 
6031         /* videos[0] might have been added in AddImplicitDevices, after we've
6032          * done the per-device post-parse */
6033         if (virDomainDefPostParseDeviceIterator(def, &device,
6034                                                 NULL, opaque) < 0)
6035             return -1;
6036     }
6037 
6038     return 0;
6039 }
6040 
6041 
6042 static int
virDomainDefPostParseCommon(virDomainDef * def,struct virDomainDefPostParseDeviceIteratorData * data,virDomainXMLOption * xmlopt)6043 virDomainDefPostParseCommon(virDomainDef *def,
6044                             struct virDomainDefPostParseDeviceIteratorData *data,
6045                             virDomainXMLOption *xmlopt)
6046 {
6047     size_t i;
6048 
6049     /* verify init path for container based domains */
6050     if (def->os.type == VIR_DOMAIN_OSTYPE_EXE && !def->os.init) {
6051         virReportError(VIR_ERR_XML_ERROR, "%s",
6052                        _("init binary must be specified"));
6053         return -1;
6054     }
6055 
6056     if (virDomainVcpuDefPostParse(def) < 0)
6057         return -1;
6058 
6059     if (virDomainDefPostParseMemory(def, data->parseFlags) < 0)
6060         return -1;
6061 
6062     virDomainDefPostParseOs(def);
6063 
6064     virDomainDefPostParseMemtune(def);
6065 
6066     if (virDomainDefRejectDuplicateControllers(def) < 0)
6067         return -1;
6068 
6069     if (virDomainDefRejectDuplicatePanics(def) < 0)
6070         return -1;
6071 
6072     if (def->os.type == VIR_DOMAIN_OSTYPE_HVM &&
6073         !(data->xmlopt->config.features & VIR_DOMAIN_DEF_FEATURE_NO_BOOT_ORDER) &&
6074         virDomainDefBootOrderPostParse(def) < 0)
6075         return -1;
6076 
6077     if (virDomainDefPostParseTimer(def) < 0)
6078         return -1;
6079 
6080     if (virDomainDefAddImplicitDevices(def, xmlopt) < 0)
6081         return -1;
6082 
6083     if (virDomainDefPostParseVideo(def, data) < 0)
6084         return -1;
6085 
6086     if (def->nserials != 0) {
6087         virDomainDeviceDef device = {
6088             .type = VIR_DOMAIN_DEVICE_CHR,
6089             .data.chr = def->serials[0],
6090         };
6091 
6092         /* serials[0] might have been added in AddImplicitDevices, after we've
6093          * done the per-device post-parse */
6094         if (virDomainDefPostParseDeviceIterator(def, &device, NULL, data) < 0)
6095             return -1;
6096     }
6097 
6098     /* Implicit SCSI controllers without a defined model might have
6099      * been added in AddImplicitDevices, after we've done the per-device
6100      * post-parse. */
6101     for (i = 0; i < def->ncontrollers; i++) {
6102         if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_DEFAULT &&
6103             def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
6104             virDomainDeviceDef device = {
6105                 .type = VIR_DOMAIN_DEVICE_CONTROLLER,
6106                 .data.controller = def->controllers[i],
6107             };
6108             if (virDomainDefPostParseDeviceIterator(def, &device, NULL, data) < 0)
6109                 return -1;
6110         }
6111     }
6112 
6113     /* clean up possibly duplicated metadata entries */
6114     virXMLNodeSanitizeNamespaces(def->metadata);
6115 
6116     virDomainDefPostParseGraphics(def);
6117 
6118     if (virDomainDefPostParseCPU(def) < 0)
6119         return -1;
6120 
6121     return 0;
6122 }
6123 
6124 
6125 static int
virDomainDefPostParseCheckFailure(virDomainDef * def,unsigned int parseFlags,int ret)6126 virDomainDefPostParseCheckFailure(virDomainDef *def,
6127                                   unsigned int parseFlags,
6128                                   int ret)
6129 {
6130     if (ret != 0)
6131         def->postParseFailed = true;
6132 
6133     if (ret <= 0)
6134         return ret;
6135 
6136     if (!(parseFlags & VIR_DOMAIN_DEF_PARSE_ALLOW_POST_PARSE_FAIL))
6137         return -1;
6138 
6139     virResetLastError();
6140     return 0;
6141 }
6142 
6143 
6144 int
virDomainDefPostParse(virDomainDef * def,unsigned int parseFlags,virDomainXMLOption * xmlopt,void * parseOpaque)6145 virDomainDefPostParse(virDomainDef *def,
6146                       unsigned int parseFlags,
6147                       virDomainXMLOption *xmlopt,
6148                       void *parseOpaque)
6149 {
6150     int ret = -1;
6151     bool localParseOpaque = false;
6152     struct virDomainDefPostParseDeviceIteratorData data = {
6153         .xmlopt = xmlopt,
6154         .parseFlags = parseFlags,
6155         .parseOpaque = parseOpaque,
6156     };
6157 
6158     def->postParseFailed = false;
6159 
6160     /* call the basic post parse callback */
6161     if (xmlopt->config.domainPostParseBasicCallback) {
6162         ret = xmlopt->config.domainPostParseBasicCallback(def,
6163                                                           xmlopt->config.priv);
6164 
6165         if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
6166             goto cleanup;
6167     }
6168 
6169     if (!data.parseOpaque &&
6170         xmlopt->config.domainPostParseDataAlloc) {
6171         ret = xmlopt->config.domainPostParseDataAlloc(def, parseFlags,
6172                                                       xmlopt->config.priv,
6173                                                       &data.parseOpaque);
6174 
6175         if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
6176             goto cleanup;
6177         localParseOpaque = true;
6178     }
6179 
6180     /* this must be done before the hypervisor-specific callback,
6181      * in case presence of a controller at a specific index is checked
6182      */
6183     virDomainAssignControllerIndexes(def);
6184 
6185     /* call the domain config callback */
6186     if (xmlopt->config.domainPostParseCallback) {
6187         ret = xmlopt->config.domainPostParseCallback(def, parseFlags,
6188                                                      xmlopt->config.priv,
6189                                                      data.parseOpaque);
6190         if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
6191             goto cleanup;
6192     }
6193 
6194     /* iterate the devices */
6195     ret = virDomainDeviceInfoIterateFlags(def,
6196                                           virDomainDefPostParseDeviceIterator,
6197                                           DOMAIN_DEVICE_ITERATE_ALL_CONSOLES |
6198                                           DOMAIN_DEVICE_ITERATE_MISSING_INFO,
6199                                           &data);
6200 
6201     if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
6202         goto cleanup;
6203 
6204     if ((ret = virDomainDefPostParseCommon(def, &data, xmlopt)) < 0)
6205         goto cleanup;
6206 
6207     if (xmlopt->config.assignAddressesCallback) {
6208         ret = xmlopt->config.assignAddressesCallback(def, parseFlags,
6209                                                      xmlopt->config.priv,
6210                                                      data.parseOpaque);
6211         if (virDomainDefPostParseCheckFailure(def, parseFlags, ret) < 0)
6212             goto cleanup;
6213     }
6214 
6215     if ((ret = virDomainDefPostParseCheckFeatures(def, xmlopt)) < 0)
6216         goto cleanup;
6217 
6218     ret = 0;
6219 
6220  cleanup:
6221     if (localParseOpaque && xmlopt->config.domainPostParseDataFree)
6222         xmlopt->config.domainPostParseDataFree(data.parseOpaque);
6223 
6224     if (ret == 1)
6225         ret = -1;
6226 
6227     return ret;
6228 }
6229 
6230 
6231 bool
virDomainDefHasUSB(const virDomainDef * def)6232 virDomainDefHasUSB(const virDomainDef *def)
6233 {
6234     size_t i;
6235 
6236     for (i = 0; i < def->ncontrollers; i++) {
6237         if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
6238             def->controllers[i]->model != VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE)
6239             return true;
6240     }
6241 
6242     return false;
6243 }
6244 
6245 
6246 bool
virDomainDefLifecycleActionAllowed(virDomainLifecycle type,virDomainLifecycleAction action)6247 virDomainDefLifecycleActionAllowed(virDomainLifecycle type,
6248                                    virDomainLifecycleAction action)
6249 {
6250     switch (type) {
6251     case VIR_DOMAIN_LIFECYCLE_POWEROFF:
6252     case VIR_DOMAIN_LIFECYCLE_REBOOT:
6253         switch (action) {
6254         case VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY:
6255         case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART:
6256         case VIR_DOMAIN_LIFECYCLE_ACTION_RESTART_RENAME:
6257         case VIR_DOMAIN_LIFECYCLE_ACTION_PRESERVE:
6258         case VIR_DOMAIN_LIFECYCLE_ACTION_LAST:
6259             return true;
6260         case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_DESTROY:
6261         case VIR_DOMAIN_LIFECYCLE_ACTION_COREDUMP_RESTART:
6262             break;
6263         }
6264         break;
6265     case VIR_DOMAIN_LIFECYCLE_CRASH:
6266     case VIR_DOMAIN_LIFECYCLE_LAST:
6267         return true;
6268     }
6269 
6270     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6271                    _("Lifecycle event '%s' doesn't support '%s' action"),
6272                    virDomainLifecycleTypeToString(type),
6273                    virDomainLifecycleActionTypeToString(action));
6274     return false;
6275 }
6276 
6277 
6278 int
virDomainObjCheckActive(virDomainObj * dom)6279 virDomainObjCheckActive(virDomainObj *dom)
6280 {
6281     if (!virDomainObjIsActive(dom)) {
6282         virReportError(VIR_ERR_OPERATION_INVALID,
6283                        "%s", _("domain is not running"));
6284         return -1;
6285     }
6286     return 0;
6287 }
6288 
6289 
6290 /**
6291  * virDomainDeviceLoadparmIsValid
6292  * @loadparm : The string to validate
6293  *
6294  * The valid set of values for loadparm are [a-zA-Z0-9.]
6295  * and blank spaces.
6296  * The maximum allowed length is 8 characters.
6297  * An empty string is considered invalid
6298  */
6299 static bool
virDomainDeviceLoadparmIsValid(const char * loadparm)6300 virDomainDeviceLoadparmIsValid(const char *loadparm)
6301 {
6302     size_t i;
6303 
6304     if (virStringIsEmpty(loadparm)) {
6305         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
6306                        _("loadparm cannot be an empty string"));
6307         return false;
6308     }
6309 
6310     if (strlen(loadparm) > 8) {
6311         virReportError(VIR_ERR_INTERNAL_ERROR,
6312                        _("loadparm '%s' exceeds 8 characters"), loadparm);
6313         return false;
6314     }
6315 
6316     for (i = 0; i < strlen(loadparm); i++) {
6317         uint8_t c = loadparm[i];
6318 
6319         if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
6320             (c == '.') || (c == ' ')) {
6321             continue;
6322         } else {
6323             virReportError(VIR_ERR_INTERNAL_ERROR,
6324                            _("invalid loadparm char '%c', expecting chars"
6325                              " in set of [a-zA-Z0-9.] and blank spaces"), c);
6326             return false;
6327         }
6328     }
6329 
6330     return true;
6331 }
6332 
6333 
6334 static void
virDomainVirtioOptionsFormat(virBuffer * buf,virDomainVirtioOptions * virtio)6335 virDomainVirtioOptionsFormat(virBuffer *buf,
6336                              virDomainVirtioOptions *virtio)
6337 {
6338     if (!virtio)
6339         return;
6340 
6341     if (virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) {
6342         virBufferAsprintf(buf, " iommu='%s'",
6343                           virTristateSwitchTypeToString(virtio->iommu));
6344     }
6345     if (virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) {
6346         virBufferAsprintf(buf, " ats='%s'",
6347                           virTristateSwitchTypeToString(virtio->ats));
6348     }
6349     if (virtio->packed != VIR_TRISTATE_SWITCH_ABSENT) {
6350         virBufferAsprintf(buf, " packed='%s'",
6351                           virTristateSwitchTypeToString(virtio->packed));
6352     }
6353     if (virtio->page_per_vq != VIR_TRISTATE_SWITCH_ABSENT) {
6354         virBufferAsprintf(buf, " page_per_vq='%s'",
6355                           virTristateSwitchTypeToString(virtio->page_per_vq));
6356     }
6357 }
6358 
6359 
6360 static void ATTRIBUTE_NONNULL(2)
virDomainDeviceInfoFormat(virBuffer * buf,const virDomainDeviceInfo * info,unsigned int flags)6361 virDomainDeviceInfoFormat(virBuffer *buf,
6362                           const virDomainDeviceInfo *info,
6363                           unsigned int flags)
6364 {
6365     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
6366     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
6367 
6368     if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
6369         virBufferAsprintf(buf, "<boot order='%u'", info->bootIndex);
6370 
6371         if (info->loadparm)
6372             virBufferAsprintf(buf, " loadparm='%s'", info->loadparm);
6373 
6374         virBufferAddLit(buf, "/>\n");
6375     }
6376 
6377     if (info->alias)
6378         virBufferAsprintf(buf, "<alias name='%s'/>\n", info->alias);
6379 
6380     if (info->mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
6381         virBufferAsprintf(buf, "<master startport='%d'/>\n",
6382                           info->master.usb.startport);
6383     }
6384 
6385     if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM) &&
6386         (info->romenabled != VIR_TRISTATE_BOOL_ABSENT ||
6387          info->rombar != VIR_TRISTATE_SWITCH_ABSENT ||
6388          info->romfile)) {
6389 
6390         virBufferAddLit(buf, "<rom");
6391         if (info->romenabled != VIR_TRISTATE_BOOL_ABSENT) {
6392             const char *romenabled = virTristateBoolTypeToString(info->romenabled);
6393 
6394             if (romenabled)
6395                 virBufferAsprintf(buf, " enabled='%s'", romenabled);
6396         }
6397         if (info->rombar != VIR_TRISTATE_SWITCH_ABSENT) {
6398             const char *rombar = virTristateSwitchTypeToString(info->rombar);
6399 
6400             if (rombar)
6401                 virBufferAsprintf(buf, " bar='%s'", rombar);
6402         }
6403         if (info->romfile)
6404             virBufferEscapeString(buf, " file='%s'", info->romfile);
6405         virBufferAddLit(buf, "/>\n");
6406     }
6407 
6408     if (info->acpiIndex != 0)
6409         virBufferAsprintf(buf, "<acpi index='%u'/>\n", info->acpiIndex);
6410 
6411     if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE ||
6412         info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390)
6413         /* We're done here */
6414         return;
6415 
6416     virBufferAsprintf(&attrBuf, " type='%s'",
6417                       virDomainDeviceAddressTypeToString(info->type));
6418 
6419     switch ((virDomainDeviceAddressType) info->type) {
6420     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
6421         if (!virPCIDeviceAddressIsEmpty(&info->addr.pci)) {
6422             virBufferAsprintf(&attrBuf, " domain='0x%04x' bus='0x%02x' "
6423                               "slot='0x%02x' function='0x%d'",
6424                               info->addr.pci.domain,
6425                               info->addr.pci.bus,
6426                               info->addr.pci.slot,
6427                               info->addr.pci.function);
6428         }
6429         if (info->addr.pci.multi) {
6430             virBufferAsprintf(&attrBuf, " multifunction='%s'",
6431                               virTristateSwitchTypeToString(info->addr.pci.multi));
6432         }
6433 
6434         if (virZPCIDeviceAddressIsPresent(&info->addr.pci.zpci)) {
6435             virBufferAsprintf(&childBuf,
6436                               "<zpci uid='0x%.4x' fid='0x%.8x'/>\n",
6437                               info->addr.pci.zpci.uid.value,
6438                               info->addr.pci.zpci.fid.value);
6439         }
6440         break;
6441 
6442     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
6443         virBufferAsprintf(&attrBuf, " controller='%d' bus='%d' target='%d' unit='%d'",
6444                           info->addr.drive.controller,
6445                           info->addr.drive.bus,
6446                           info->addr.drive.target,
6447                           info->addr.drive.unit);
6448         break;
6449 
6450     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL:
6451         virBufferAsprintf(&attrBuf, " controller='%d' bus='%d' port='%d'",
6452                           info->addr.vioserial.controller,
6453                           info->addr.vioserial.bus,
6454                           info->addr.vioserial.port);
6455         break;
6456 
6457     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
6458         virBufferAsprintf(&attrBuf, " controller='%d' slot='%d'",
6459                           info->addr.ccid.controller,
6460                           info->addr.ccid.slot);
6461         break;
6462 
6463     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
6464         virBufferAsprintf(&attrBuf, " bus='%d'", info->addr.usb.bus);
6465         if (virDomainUSBAddressPortIsValid(info->addr.usb.port)) {
6466             virBufferAddLit(&attrBuf, " port='");
6467             virDomainUSBAddressPortFormatBuf(&attrBuf, info->addr.usb.port);
6468             virBufferAddLit(&attrBuf, "'");
6469         }
6470         break;
6471 
6472     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
6473         if (info->addr.spaprvio.has_reg)
6474             virBufferAsprintf(&attrBuf, " reg='0x%08llx'", info->addr.spaprvio.reg);
6475         break;
6476 
6477     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
6478         virBufferAsprintf(&attrBuf, " cssid='0x%x' ssid='0x%x' devno='0x%04x'",
6479                           info->addr.ccw.cssid,
6480                           info->addr.ccw.ssid,
6481                           info->addr.ccw.devno);
6482         break;
6483 
6484     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
6485         break;
6486 
6487     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
6488         if (info->addr.isa.iobase > 0)
6489             virBufferAsprintf(&attrBuf, " iobase='0x%x'", info->addr.isa.iobase);
6490         if (info->addr.isa.irq > 0)
6491             virBufferAsprintf(&attrBuf, " irq='0x%x'", info->addr.isa.irq);
6492         break;
6493 
6494     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
6495         virBufferAsprintf(&attrBuf, " slot='%u'", info->addr.dimm.slot);
6496         if (info->addr.dimm.base)
6497             virBufferAsprintf(&attrBuf, " base='0x%llx'", info->addr.dimm.base);
6498 
6499         break;
6500 
6501     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
6502     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
6503     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
6504     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
6505         break;
6506     }
6507 
6508     virXMLFormatElement(buf, "address", &attrBuf, &childBuf);
6509 }
6510 
6511 static int
virDomainDeviceUSBMasterParseXML(xmlNodePtr node,virDomainDeviceUSBMaster * master)6512 virDomainDeviceUSBMasterParseXML(xmlNodePtr node,
6513                                  virDomainDeviceUSBMaster *master)
6514 {
6515     memset(master, 0, sizeof(*master));
6516 
6517     if (virXMLPropUInt(node, "startport", 10, VIR_XML_PROP_NONE,
6518                        &master->startport) < 0)
6519         return -1;
6520 
6521     return 0;
6522 }
6523 
6524 static int
virDomainDeviceBootParseXML(xmlNodePtr node,virDomainDeviceInfo * info)6525 virDomainDeviceBootParseXML(xmlNodePtr node,
6526                             virDomainDeviceInfo *info)
6527 {
6528     g_autofree char *loadparm = NULL;
6529 
6530     if (virXMLPropUInt(node, "order", 10,
6531                        VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
6532                        &info->bootIndex) < 0)
6533         return -1;
6534 
6535     info->effectiveBootIndex = info->bootIndex;
6536 
6537     loadparm = virXMLPropString(node, "loadparm");
6538     if (loadparm) {
6539         if (virStringToUpper(&info->loadparm, loadparm) != 1) {
6540             virReportError(VIR_ERR_INTERNAL_ERROR,
6541                            _("Failed to convert loadparm '%s' to upper case"),
6542                            loadparm);
6543             return -1;
6544         }
6545 
6546         if (!virDomainDeviceLoadparmIsValid(info->loadparm)) {
6547             VIR_FREE(info->loadparm);
6548             return -1;
6549         }
6550     }
6551 
6552     return 0;
6553 }
6554 
6555 static int
virDomainDeviceISAAddressParseXML(xmlNodePtr node,virDomainDeviceISAAddress * addr)6556 virDomainDeviceISAAddressParseXML(xmlNodePtr node,
6557                                   virDomainDeviceISAAddress *addr)
6558 {
6559     memset(addr, 0, sizeof(*addr));
6560 
6561     if (virXMLPropUInt(node, "iobase", 16, VIR_XML_PROP_NONE,
6562                        &addr->iobase) < 0)
6563         return -1;
6564 
6565     if (virXMLPropUInt(node, "irq", 16, VIR_XML_PROP_NONE, &addr->irq) < 0)
6566         return -1;
6567 
6568     return 0;
6569 }
6570 
6571 
6572 static int
virDomainDeviceDimmAddressParseXML(xmlNodePtr node,virDomainDeviceDimmAddress * addr)6573 virDomainDeviceDimmAddressParseXML(xmlNodePtr node,
6574                                    virDomainDeviceDimmAddress *addr)
6575 {
6576     if (virXMLPropUInt(node, "slot", 10, VIR_XML_PROP_REQUIRED,
6577                        &addr->slot) < 0)
6578         return -1;
6579 
6580     if (virXMLPropULongLong(node, "base", 16, VIR_XML_PROP_NONE,
6581                             &addr->base) < 0)
6582         return -1;
6583 
6584     return 0;
6585 }
6586 
6587 
6588 static int
virDomainDeviceAddressParseXML(xmlNodePtr address,virDomainDeviceInfo * info)6589 virDomainDeviceAddressParseXML(xmlNodePtr address,
6590                                virDomainDeviceInfo *info)
6591 {
6592     g_autofree char *type = virXMLPropString(address, "type");
6593 
6594     if (type) {
6595         if ((info->type = virDomainDeviceAddressTypeFromString(type)) <= 0) {
6596             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6597                            _("unknown address type '%s'"), type);
6598             return -1;
6599         }
6600     } else {
6601         virReportError(VIR_ERR_INTERNAL_ERROR,
6602                        "%s", _("No type specified for device address"));
6603         return -1;
6604     }
6605 
6606     switch ((virDomainDeviceAddressType) info->type) {
6607     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
6608         if (virPCIDeviceAddressParseXML(address, &info->addr.pci) < 0)
6609             return -1;
6610         break;
6611 
6612     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
6613         if (virDomainDeviceDriveAddressParseXML(address, &info->addr.drive) < 0)
6614             return -1;
6615         break;
6616 
6617     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL:
6618         if (virDomainDeviceVirtioSerialAddressParseXML
6619                 (address, &info->addr.vioserial) < 0)
6620             return -1;
6621         break;
6622 
6623     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
6624         if (virDomainDeviceCcidAddressParseXML(address, &info->addr.ccid) < 0)
6625             return -1;
6626         break;
6627 
6628     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
6629         if (virDomainDeviceUSBAddressParseXML(address, &info->addr.usb) < 0)
6630             return -1;
6631         break;
6632 
6633     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
6634         if (virDomainDeviceSpaprVioAddressParseXML(address, &info->addr.spaprvio) < 0)
6635             return -1;
6636         break;
6637 
6638     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
6639         if (virDomainDeviceCCWAddressParseXML
6640                 (address, &info->addr.ccw) < 0)
6641             return -1;
6642         break;
6643 
6644     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
6645         break;
6646 
6647     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
6648         if (virDomainDeviceISAAddressParseXML(address, &info->addr.isa) < 0)
6649             return -1;
6650         break;
6651 
6652     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
6653         virReportError(VIR_ERR_XML_ERROR, "%s",
6654                        _("virtio-s390 bus doesn't have an address"));
6655         return -1;
6656 
6657     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
6658         if (virDomainDeviceDimmAddressParseXML(address, &info->addr.dimm) < 0)
6659             return -1;
6660         break;
6661 
6662     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
6663     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
6664     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
6665         break;
6666     }
6667 
6668     return 0;
6669 }
6670 
6671 
6672 #define USER_ALIAS_PREFIX "ua-"
6673 #define USER_ALIAS_CHARS \
6674     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
6675 
6676 bool
virDomainDeviceAliasIsUserAlias(const char * aliasStr)6677 virDomainDeviceAliasIsUserAlias(const char *aliasStr)
6678 {
6679     return aliasStr && STRPREFIX(aliasStr, USER_ALIAS_PREFIX);
6680 }
6681 
6682 
6683 static int
virDomainDeviceInfoParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,virDomainDeviceInfo * info,unsigned int flags)6684 virDomainDeviceInfoParseXML(virDomainXMLOption *xmlopt,
6685                             xmlNodePtr node,
6686                             xmlXPathContextPtr ctxt,
6687                             virDomainDeviceInfo *info,
6688                             unsigned int flags)
6689 {
6690     xmlNodePtr acpi = NULL;
6691     xmlNodePtr address = NULL;
6692     xmlNodePtr master = NULL;
6693     xmlNodePtr boot = NULL;
6694     xmlNodePtr rom = NULL;
6695     int ret = -1;
6696     g_autofree char *aliasStr = NULL;
6697     VIR_XPATH_NODE_AUTORESTORE(ctxt)
6698 
6699     virDomainDeviceInfoClear(info);
6700     ctxt->node = node;
6701 
6702     if ((aliasStr = virXPathString("string(./alias/@name)", ctxt)))
6703         if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) ||
6704             (xmlopt->config.features & VIR_DOMAIN_DEF_FEATURE_USER_ALIAS &&
6705              virDomainDeviceAliasIsUserAlias(aliasStr) &&
6706              strspn(aliasStr, USER_ALIAS_CHARS) == strlen(aliasStr)))
6707             info->alias = g_steal_pointer(&aliasStr);
6708 
6709     if ((master = virXPathNode("./master", ctxt))) {
6710         info->mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
6711         if (virDomainDeviceUSBMasterParseXML(master, &info->master.usb) < 0)
6712             goto cleanup;
6713     }
6714 
6715     if (flags & VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT &&
6716         (boot = virXPathNode("./boot", ctxt))) {
6717         if (virDomainDeviceBootParseXML(boot, info))
6718             goto cleanup;
6719     }
6720 
6721     if ((flags & VIR_DOMAIN_DEF_PARSE_ALLOW_ROM) &&
6722         (rom = virXPathNode("./rom", ctxt))) {
6723         if (virXMLPropTristateBool(rom, "enabled", VIR_XML_PROP_NONE,
6724                                    &info->romenabled) < 0)
6725             goto cleanup;
6726 
6727         if (virXMLPropTristateSwitch(rom, "bar", VIR_XML_PROP_NONE,
6728                                      &info->rombar) < 0)
6729             goto cleanup;
6730 
6731         info->romfile = virXMLPropString(rom, "file");
6732 
6733         if (info->romenabled == VIR_TRISTATE_BOOL_NO &&
6734             (info->rombar != VIR_TRISTATE_SWITCH_ABSENT || info->romfile)) {
6735             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
6736                            _("ROM tuning is not supported when ROM is disabled"));
6737             goto cleanup;
6738         }
6739     }
6740 
6741     if ((acpi = virXPathNode("./acpi", ctxt))) {
6742         if (virXMLPropUInt(acpi, "index", 10, VIR_XML_PROP_NONE,
6743                            &info->acpiIndex) < 0)
6744             goto cleanup;
6745     }
6746 
6747     if ((address = virXPathNode("./address", ctxt)) &&
6748         virDomainDeviceAddressParseXML(address, info) < 0)
6749         goto cleanup;
6750 
6751 
6752     ret = 0;
6753  cleanup:
6754     if (ret < 0)
6755         virDomainDeviceInfoClear(info);
6756     return ret;
6757 }
6758 
6759 static int
virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virDomainHostdevDef * def)6760 virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
6761                                      xmlXPathContextPtr ctxt,
6762                                      virDomainHostdevDef *def)
6763 {
6764     virDomainHostdevSubsysUSB *usbsrc = &def->source.subsys.u.usb;
6765     xmlNodePtr vendorNode;
6766     xmlNodePtr productNode;
6767     xmlNodePtr addressNode;
6768     virTristateBool autoAddress;
6769     VIR_XPATH_NODE_AUTORESTORE(ctxt)
6770 
6771     ctxt->node = node;
6772 
6773     if (virXMLPropEnum(node, "startupPolicy",
6774                        virDomainStartupPolicyTypeFromString,
6775                        VIR_XML_PROP_NONZERO, &def->startupPolicy) < 0)
6776         return -1;
6777 
6778     if (virXMLPropTristateBool(node, "autoAddress", VIR_XML_PROP_NONE,
6779                                &autoAddress) < 0)
6780         return -1;
6781     usbsrc->autoAddress = autoAddress == VIR_TRISTATE_BOOL_YES;
6782 
6783     /* Product can validly be 0, so we need some extra help to determine
6784      * if it is uninitialized */
6785     vendorNode = virXPathNode("./vendor", ctxt);
6786     productNode = virXPathNode("./product", ctxt);
6787 
6788     if (vendorNode) {
6789         if (virXMLPropUInt(vendorNode, "id", 0,
6790                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
6791                            &usbsrc->vendor) < 0)
6792             return -1;
6793 
6794         if (!productNode) {
6795             virReportError(VIR_ERR_INTERNAL_ERROR,
6796                            "%s", _("missing product"));
6797             return -1;
6798         }
6799     }
6800 
6801     if (productNode) {
6802         if (virXMLPropUInt(productNode, "id", 0,
6803                            VIR_XML_PROP_REQUIRED, &usbsrc->product) < 0)
6804             return -1;
6805 
6806         if (!vendorNode) {
6807             virReportError(VIR_ERR_INTERNAL_ERROR,
6808                            "%s", _("missing vendor"));
6809             return -1;
6810         }
6811     }
6812 
6813     if ((addressNode = virXPathNode("./address", ctxt))) {
6814         if (virXMLPropUInt(addressNode, "bus", 0,
6815                            VIR_XML_PROP_REQUIRED, &usbsrc->bus) < 0)
6816             return -1;
6817 
6818         if (virXMLPropUInt(addressNode, "device", 0,
6819                            VIR_XML_PROP_REQUIRED, &usbsrc->device) < 0)
6820             return -1;
6821     }
6822 
6823     return 0;
6824 }
6825 
6826 /* The internal XML for host PCI device's original states:
6827  *
6828  * <origstates>
6829  *   <unbind/>
6830  *   <removeslot/>
6831  *   <reprobe/>
6832  * </origstates>
6833  */
6834 static int
virDomainHostdevSubsysPCIOrigStatesDefParseXML(xmlNodePtr node,virDomainHostdevOrigStates * def)6835 virDomainHostdevSubsysPCIOrigStatesDefParseXML(xmlNodePtr node,
6836                                                virDomainHostdevOrigStates *def)
6837 {
6838     xmlNodePtr cur;
6839     cur = node->children;
6840 
6841     while (cur != NULL) {
6842         if (cur->type == XML_ELEMENT_NODE) {
6843             if (virXMLNodeNameEqual(cur, "unbind")) {
6844                 def->states.pci.unbind_from_stub = true;
6845             } else if (virXMLNodeNameEqual(cur, "removeslot")) {
6846                 def->states.pci.remove_slot = true;
6847             } else if (virXMLNodeNameEqual(cur, "reprobe")) {
6848                 def->states.pci.reprobe = true;
6849             } else {
6850                 virReportError(VIR_ERR_INTERNAL_ERROR,
6851                                _("unsupported element '%s' of 'origstates'"),
6852                                cur->name);
6853                 return -1;
6854             }
6855         }
6856         cur = cur->next;
6857     }
6858 
6859     return 0;
6860 }
6861 
6862 static int
virDomainHostdevSubsysPCIDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virDomainHostdevDef * def,unsigned int flags)6863 virDomainHostdevSubsysPCIDefParseXML(xmlNodePtr node,
6864                                      xmlXPathContextPtr ctxt,
6865                                      virDomainHostdevDef *def,
6866                                      unsigned int flags)
6867 {
6868     g_autofree char *filtering = NULL;
6869     xmlNodePtr address = NULL;
6870     xmlNodePtr origstates = NULL;
6871     VIR_XPATH_NODE_AUTORESTORE(ctxt)
6872 
6873     ctxt->node = node;
6874 
6875     if ((filtering = virXMLPropString(node, "writeFiltering"))) {
6876         int val;
6877         if ((val = virTristateBoolTypeFromString(filtering)) < 0) {
6878             virReportError(VIR_ERR_XML_ERROR,
6879                            _("unknown pci writeFiltering setting '%s'"),
6880                            filtering);
6881             return -1;
6882         }
6883         def->writeFiltering = val;
6884     }
6885 
6886     if ((address = virXPathNode("./address", ctxt)) &&
6887         virPCIDeviceAddressParseXML(address, &def->source.subsys.u.pci.addr) < 0)
6888         return -1;
6889 
6890     if ((flags & VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES) &&
6891         (origstates = virXPathNode("./origstates", ctxt)) &&
6892         virDomainHostdevSubsysPCIOrigStatesDefParseXML(origstates, &def->origstates) < 0)
6893         return -1;
6894 
6895     return 0;
6896 }
6897 
6898 
6899 int
virDomainStorageNetworkParseHost(xmlNodePtr hostnode,virStorageNetHostDef * host)6900 virDomainStorageNetworkParseHost(xmlNodePtr hostnode,
6901                                  virStorageNetHostDef *host)
6902 {
6903     int ret = -1;
6904     g_autofree char *transport = NULL;
6905     g_autofree char *port = NULL;
6906 
6907     memset(host, 0, sizeof(*host));
6908     host->transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
6909 
6910     /* transport can be tcp (default), unix or rdma.  */
6911     if ((transport = virXMLPropString(hostnode, "transport"))) {
6912         host->transport = virStorageNetHostTransportTypeFromString(transport);
6913         if (host->transport < 0) {
6914             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
6915                            _("unknown protocol transport type '%s'"),
6916                            transport);
6917             goto cleanup;
6918         }
6919     }
6920 
6921     host->socket = virXMLPropString(hostnode, "socket");
6922 
6923     if (host->transport == VIR_STORAGE_NET_HOST_TRANS_UNIX &&
6924         host->socket == NULL) {
6925         virReportError(VIR_ERR_XML_ERROR, "%s",
6926                        _("missing socket for unix transport"));
6927         goto cleanup;
6928     }
6929 
6930     if (host->transport != VIR_STORAGE_NET_HOST_TRANS_UNIX &&
6931         host->socket != NULL) {
6932         virReportError(VIR_ERR_XML_ERROR,
6933                        _("transport '%s' does not support "
6934                          "socket attribute"),
6935                        transport);
6936         goto cleanup;
6937     }
6938 
6939     if (host->transport != VIR_STORAGE_NET_HOST_TRANS_UNIX) {
6940         if (!(host->name = virXMLPropString(hostnode, "name"))) {
6941             virReportError(VIR_ERR_XML_ERROR, "%s",
6942                            _("missing name for host"));
6943             goto cleanup;
6944         }
6945 
6946         if ((port = virXMLPropString(hostnode, "port"))) {
6947             if (virStringParsePort(port, &host->port) < 0)
6948                 goto cleanup;
6949         }
6950     }
6951 
6952     ret = 0;
6953 
6954  cleanup:
6955     if (ret < 0)
6956         virStorageNetHostDefClear(host);
6957     return ret;
6958 }
6959 
6960 
6961 static int
virDomainStorageNetworkParseHosts(xmlNodePtr node,xmlXPathContextPtr ctxt,virStorageNetHostDef ** hosts,size_t * nhosts)6962 virDomainStorageNetworkParseHosts(xmlNodePtr node,
6963                                   xmlXPathContextPtr ctxt,
6964                                   virStorageNetHostDef **hosts,
6965                                   size_t *nhosts)
6966 {
6967     g_autofree xmlNodePtr *hostnodes = NULL;
6968     ssize_t nhostnodes;
6969     size_t i;
6970     VIR_XPATH_NODE_AUTORESTORE(ctxt)
6971 
6972     ctxt->node = node;
6973 
6974     if ((nhostnodes = virXPathNodeSet("./host", ctxt, &hostnodes)) <= 0)
6975         return nhostnodes;
6976 
6977     *hosts = g_new0(virStorageNetHostDef, nhostnodes);
6978     *nhosts = nhostnodes;
6979 
6980     for (i = 0; i < nhostnodes; i++) {
6981         if (virDomainStorageNetworkParseHost(hostnodes[i], *hosts + i) < 0)
6982             return -1;
6983     }
6984 
6985     return 0;
6986 }
6987 
6988 
6989 static void
virDomainStorageNetworkParseNFS(xmlNodePtr node,xmlXPathContextPtr ctxt,virStorageSource * src)6990 virDomainStorageNetworkParseNFS(xmlNodePtr node,
6991                                xmlXPathContextPtr ctxt,
6992                                virStorageSource *src)
6993 {
6994     xmlNodePtr nfsIdentityNode = NULL;
6995     VIR_XPATH_NODE_AUTORESTORE(ctxt);
6996 
6997     ctxt->node = node;
6998 
6999     if ((nfsIdentityNode = virXPathNode("./identity", ctxt))) {
7000         src->nfs_user = virXMLPropString(nfsIdentityNode, "user");
7001         src->nfs_group = virXMLPropString(nfsIdentityNode, "group");
7002     }
7003 }
7004 
7005 
7006 static int
virDomainHostdevSubsysSCSIHostDefParseXML(xmlNodePtr sourcenode,xmlXPathContextPtr ctxt,virDomainHostdevSubsysSCSI * scsisrc,unsigned int flags,virDomainXMLOption * xmlopt)7007 virDomainHostdevSubsysSCSIHostDefParseXML(xmlNodePtr sourcenode,
7008                                           xmlXPathContextPtr ctxt,
7009                                           virDomainHostdevSubsysSCSI *scsisrc,
7010                                           unsigned int flags,
7011                                           virDomainXMLOption *xmlopt)
7012 {
7013     virDomainHostdevSubsysSCSIHost *scsihostsrc = &scsisrc->u.host;
7014     xmlNodePtr addressnode = NULL;
7015     VIR_XPATH_NODE_AUTORESTORE(ctxt)
7016 
7017     ctxt->node = sourcenode;
7018 
7019     if (!(addressnode = virXPathNode("./address", ctxt))) {
7020         virReportError(VIR_ERR_XML_ERROR, "%s",
7021                        _("'address' must be specified for scsi hostdev source"));
7022         return -1;
7023     }
7024 
7025     if (virXMLPropUInt(addressnode, "bus", 0, VIR_XML_PROP_REQUIRED,
7026                        &scsihostsrc->bus) < 0)
7027         return -1;
7028 
7029     if (virXMLPropUInt(addressnode, "target", 0, VIR_XML_PROP_REQUIRED,
7030                        &scsihostsrc->target) < 0)
7031         return -1;
7032 
7033     if (virXMLPropULongLong(addressnode, "unit", 0, VIR_XML_PROP_REQUIRED,
7034                             &scsihostsrc->unit) < 0)
7035         return -1;
7036 
7037     if (!(scsihostsrc->adapter = virXPathString("string(./adapter/@name)", ctxt))) {
7038         virReportError(VIR_ERR_XML_ERROR, "%s",
7039                        _("'adapter' name must be specified for scsi hostdev source"));
7040         return -1;
7041     }
7042 
7043     if (flags & VIR_DOMAIN_DEF_PARSE_STATUS &&
7044         xmlopt && xmlopt->privateData.storageParse) {
7045         if ((ctxt->node = virXPathNode("./privateData", ctxt))) {
7046             if (!scsihostsrc->src)
7047                 scsihostsrc->src = virStorageSourceNew();
7048             if (xmlopt->privateData.storageParse(ctxt, scsihostsrc->src) < 0)
7049                 return -1;
7050         }
7051     }
7052     return 0;
7053 }
7054 
7055 
7056 static int
virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlNodePtr sourcenode,virDomainHostdevSubsysSCSI * def,xmlXPathContextPtr ctxt,unsigned int flags,virDomainXMLOption * xmlopt)7057 virDomainHostdevSubsysSCSIiSCSIDefParseXML(xmlNodePtr sourcenode,
7058                                            virDomainHostdevSubsysSCSI *def,
7059                                            xmlXPathContextPtr ctxt,
7060                                            unsigned int flags,
7061                                            virDomainXMLOption *xmlopt)
7062 {
7063     int auth_secret_usage = -1;
7064     virDomainHostdevSubsysSCSIiSCSI *iscsisrc = &def->u.iscsi;
7065     g_autoptr(virStorageAuthDef) authdef = NULL;
7066     xmlNodePtr node;
7067     VIR_XPATH_NODE_AUTORESTORE(ctxt)
7068 
7069     ctxt->node = sourcenode;
7070 
7071     /* For the purposes of command line creation, this needs to look
7072      * like a disk storage source */
7073     iscsisrc->src = virStorageSourceNew();
7074     iscsisrc->src->type = VIR_STORAGE_TYPE_NETWORK;
7075     iscsisrc->src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;
7076 
7077     if (!(iscsisrc->src->path = virXMLPropString(sourcenode, "name"))) {
7078         virReportError(VIR_ERR_XML_ERROR, "%s",
7079                        _("missing iSCSI hostdev source path name"));
7080         return -1;
7081     }
7082 
7083     if (virDomainStorageNetworkParseHosts(sourcenode, ctxt, &iscsisrc->src->hosts,
7084                                           &iscsisrc->src->nhosts) < 0)
7085         return -1;
7086 
7087     if (iscsisrc->src->nhosts < 1) {
7088         virReportError(VIR_ERR_XML_ERROR, "%s",
7089                        _("missing the host address for the iSCSI hostdev"));
7090         return -1;
7091     }
7092     if (iscsisrc->src->nhosts > 1) {
7093         virReportError(VIR_ERR_XML_ERROR, "%s",
7094                        _("only one source host address may be specified "
7095                          "for the iSCSI hostdev"));
7096         return -1;
7097     }
7098 
7099     if ((node = virXPathNode("./auth", ctxt))) {
7100         if (!(authdef = virStorageAuthDefParse(node, ctxt)))
7101             return -1;
7102         if ((auth_secret_usage = virSecretUsageTypeFromString(authdef->secrettype)) < 0) {
7103             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7104                            _("invalid secret type %s"),
7105                            authdef->secrettype);
7106             return -1;
7107         }
7108         if (auth_secret_usage != VIR_SECRET_USAGE_TYPE_ISCSI) {
7109             virReportError(VIR_ERR_INTERNAL_ERROR,
7110                            _("hostdev invalid secret type '%s'"),
7111                            authdef->secrettype);
7112             return -1;
7113         }
7114         iscsisrc->src->auth = g_steal_pointer(&authdef);
7115     }
7116 
7117     virStorageSourceInitiatorParseXML(ctxt, &iscsisrc->src->initiator);
7118 
7119     if (flags & VIR_DOMAIN_DEF_PARSE_STATUS &&
7120         xmlopt && xmlopt->privateData.storageParse) {
7121         if ((ctxt->node = virXPathNode("./privateData", ctxt)) &&
7122             xmlopt->privateData.storageParse(ctxt, iscsisrc->src) < 0)
7123             return -1;
7124     }
7125 
7126     return 0;
7127 }
7128 
7129 static int
virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode,virDomainHostdevSubsysSCSI * scsisrc,xmlXPathContextPtr ctxt,unsigned int flags,virDomainXMLOption * xmlopt)7130 virDomainHostdevSubsysSCSIDefParseXML(xmlNodePtr sourcenode,
7131                                       virDomainHostdevSubsysSCSI *scsisrc,
7132                                       xmlXPathContextPtr ctxt,
7133                                       unsigned int flags,
7134                                       virDomainXMLOption *xmlopt)
7135 {
7136     g_autofree char *protocol = NULL;
7137 
7138     if ((protocol = virXMLPropString(sourcenode, "protocol"))) {
7139         scsisrc->protocol =
7140             virDomainHostdevSubsysSCSIProtocolTypeFromString(protocol);
7141         if (scsisrc->protocol < 0) {
7142             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7143                            _("Unknown SCSI subsystem protocol '%s'"),
7144                            protocol);
7145             return -1;
7146         }
7147     }
7148 
7149     switch ((virDomainHostdevSCSIProtocolType) scsisrc->protocol) {
7150     case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE:
7151         return virDomainHostdevSubsysSCSIHostDefParseXML(sourcenode, ctxt, scsisrc,
7152                                                          flags, xmlopt);
7153 
7154     case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI:
7155         return virDomainHostdevSubsysSCSIiSCSIDefParseXML(sourcenode, scsisrc, ctxt,
7156                                                           flags, xmlopt);
7157 
7158     case VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST:
7159     default:
7160         virReportEnumRangeError(virDomainHostdevSCSIProtocolType, scsisrc->protocol);
7161         return -1;
7162     }
7163 
7164     return 0;
7165 }
7166 
7167 static int
virDomainHostdevSubsysSCSIVHostDefParseXML(xmlNodePtr sourcenode,virDomainHostdevDef * def)7168 virDomainHostdevSubsysSCSIVHostDefParseXML(xmlNodePtr sourcenode,
7169                                            virDomainHostdevDef *def)
7170 {
7171     virDomainHostdevSubsysSCSIVHost *hostsrc = &def->source.subsys.u.scsi_host;
7172     g_autofree char *protocol = NULL;
7173     g_autofree char *wwpn = NULL;
7174 
7175     if (!(protocol = virXMLPropString(sourcenode, "protocol"))) {
7176         virReportError(VIR_ERR_XML_ERROR, "%s",
7177                        _("Missing scsi_host subsystem protocol"));
7178         return -1;
7179     }
7180 
7181     if ((hostsrc->protocol =
7182          virDomainHostdevSubsysSCSIHostProtocolTypeFromString(protocol)) <= 0) {
7183         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7184                        _("Unknown scsi_host subsystem protocol '%s'"),
7185                        protocol);
7186         return -1;
7187     }
7188 
7189     switch ((virDomainHostdevSubsysSCSIHostProtocolType) hostsrc->protocol) {
7190     case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_VHOST:
7191         if (!(wwpn = virXMLPropString(sourcenode, "wwpn"))) {
7192             virReportError(VIR_ERR_XML_ERROR, "%s",
7193                            _("missing vhost-scsi hostdev source wwpn"));
7194             return -1;
7195         }
7196 
7197         if (!STRPREFIX(wwpn, "naa.") ||
7198             !virValidateWWN(wwpn + 4)) {
7199             virReportError(VIR_ERR_XML_ERROR, "%s", _("malformed 'wwpn' value"));
7200             return -1;
7201         }
7202         hostsrc->wwpn = g_steal_pointer(&wwpn);
7203         break;
7204     case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_NONE:
7205     case VIR_DOMAIN_HOSTDEV_SUBSYS_SCSI_HOST_PROTOCOL_TYPE_LAST:
7206         virReportError(VIR_ERR_XML_ERROR,
7207                        _("Invalid hostdev protocol '%s'"),
7208                        virDomainHostdevSubsysSCSIHostProtocolTypeToString(hostsrc->protocol));
7209         return -1;
7210     }
7211 
7212     return 0;
7213 }
7214 
7215 static int
virDomainHostdevSubsysMediatedDevDefParseXML(virDomainHostdevDef * def,xmlXPathContextPtr ctxt)7216 virDomainHostdevSubsysMediatedDevDefParseXML(virDomainHostdevDef *def,
7217                                              xmlXPathContextPtr ctxt)
7218 {
7219     unsigned char uuid[VIR_UUID_BUFLEN] = {0};
7220     xmlNodePtr node = NULL;
7221     virDomainHostdevSubsysMediatedDev *mdevsrc = &def->source.subsys.u.mdev;
7222     g_autofree char *uuidxml = NULL;
7223 
7224     if (!(node = virXPathNode("./source/address", ctxt))) {
7225         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7226                        _("Missing <address> element"));
7227         return -1;
7228     }
7229 
7230     if (!(uuidxml = virXMLPropString(node, "uuid"))) {
7231         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7232                        _("Missing 'uuid' attribute for element <address>"));
7233         return -1;
7234     }
7235 
7236     if (virUUIDParse(uuidxml, uuid) < 0) {
7237         virReportError(VIR_ERR_INTERNAL_ERROR,
7238                        "%s",
7239                        _("Cannot parse uuid attribute of element <address>"));
7240         return -1;
7241     }
7242 
7243     virUUIDFormat(uuid, mdevsrc->uuidstr);
7244     return 0;
7245 }
7246 
7247 static int
virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,xmlXPathContextPtr ctxt,const char * type,virDomainHostdevDef * def,unsigned int flags,virDomainXMLOption * xmlopt)7248 virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
7249                                   xmlXPathContextPtr ctxt,
7250                                   const char *type,
7251                                   virDomainHostdevDef *def,
7252                                   unsigned int flags,
7253                                   virDomainXMLOption *xmlopt)
7254 {
7255     xmlNodePtr sourcenode;
7256     int backend;
7257     virDomainHostdevSubsysPCI *pcisrc = &def->source.subsys.u.pci;
7258     virDomainHostdevSubsysSCSI *scsisrc = &def->source.subsys.u.scsi;
7259     virDomainHostdevSubsysSCSIVHost *scsihostsrc = &def->source.subsys.u.scsi_host;
7260     virDomainHostdevSubsysMediatedDev *mdevsrc = &def->source.subsys.u.mdev;
7261     g_autofree char *managed = NULL;
7262     g_autofree char *sgio = NULL;
7263     g_autofree char *rawio = NULL;
7264     g_autofree char *backendStr = NULL;
7265     g_autofree char *model = NULL;
7266     g_autofree char *display = NULL;
7267     g_autofree char *ramfb = NULL;
7268 
7269     /* @managed can be read from the xml document - it is always an
7270      * attribute of the toplevel element, no matter what type of
7271      * element that might be (pure hostdev, or higher level device
7272      * (e.g. <interface>) with type='hostdev')
7273      */
7274     if ((managed = virXMLPropString(node, "managed")) != NULL)
7275         ignore_value(virStringParseYesNo(managed, &def->managed));
7276 
7277     sgio = virXMLPropString(node, "sgio");
7278     rawio = virXMLPropString(node, "rawio");
7279     model = virXMLPropString(node, "model");
7280     display = virXMLPropString(node, "display");
7281     ramfb = virXMLPropString(node, "ramfb");
7282 
7283     /* @type is passed in from the caller rather than read from the
7284      * xml document, because it is specified in different places for
7285      * different kinds of defs - it is an attribute of
7286      * <source>/<address> for an intelligent hostdev (<interface>),
7287      * but an attribute of the toplevel element for a standard
7288      * <hostdev>.  (the functions we're going to call expect address
7289      * type to already be known).
7290      */
7291     if (type) {
7292         if ((def->source.subsys.type
7293              = virDomainHostdevSubsysTypeFromString(type)) < 0) {
7294             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7295                            _("unknown host device source address type '%s'"),
7296                            type);
7297             return -1;
7298         }
7299     } else {
7300         virReportError(VIR_ERR_XML_ERROR,
7301                        "%s", _("missing source address type"));
7302         return -1;
7303     }
7304 
7305     if (!(sourcenode = virXPathNode("./source", ctxt))) {
7306         virReportError(VIR_ERR_XML_ERROR, "%s",
7307                        _("Missing <source> element in hostdev device"));
7308         return -1;
7309     }
7310 
7311     if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
7312         virXPathBoolean("boolean(./source/@startupPolicy)", ctxt)) {
7313         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
7314                        _("Setting startupPolicy is only allowed for USB"
7315                          " devices"));
7316         return -1;
7317     }
7318 
7319     if (sgio) {
7320         if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
7321             virReportError(VIR_ERR_XML_ERROR, "%s",
7322                            _("sgio is only supported for scsi host device"));
7323             return -1;
7324         }
7325 
7326         if ((scsisrc->sgio = virDomainDeviceSGIOTypeFromString(sgio)) <= 0) {
7327             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7328                            _("unknown sgio mode '%s'"), sgio);
7329             return -1;
7330         }
7331     }
7332 
7333     if (rawio) {
7334         if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
7335             virReportError(VIR_ERR_XML_ERROR, "%s",
7336                            _("rawio is only supported for scsi host device"));
7337             return -1;
7338         }
7339 
7340         if ((scsisrc->rawio = virTristateBoolTypeFromString(rawio)) <= 0) {
7341             virReportError(VIR_ERR_XML_ERROR,
7342                            _("unknown hostdev rawio setting '%s'"),
7343                            rawio);
7344             return -1;
7345         }
7346     }
7347 
7348     if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV &&
7349         def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
7350         if (model) {
7351             virReportError(VIR_ERR_XML_ERROR,
7352                            _("'model' attribute in <hostdev> is only supported "
7353                              "when type='%s'"),
7354                            virDomainHostdevSubsysTypeToString(def->source.subsys.type));
7355             return -1;
7356         }
7357     }
7358 
7359     if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
7360         if (model &&
7361             ((scsihostsrc->model = virDomainHostdevSubsysSCSIVHostModelTypeFromString(model)) < 0)) {
7362             virReportError(VIR_ERR_XML_ERROR,
7363                            _("unknown hostdev model '%s'"),
7364                            model);
7365             return -1;
7366         }
7367     } else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV) {
7368         if (!model) {
7369             virReportError(VIR_ERR_XML_ERROR, "%s",
7370                            _("Missing 'model' attribute in mediated device's "
7371                              "<hostdev> element"));
7372             return -1;
7373         }
7374 
7375         if ((mdevsrc->model = virMediatedDeviceModelTypeFromString(model)) < 0) {
7376             virReportError(VIR_ERR_XML_ERROR,
7377                            _("unknown hostdev model '%s'"),
7378                            model);
7379             return -1;
7380         }
7381 
7382         if (display &&
7383             (mdevsrc->display = virTristateSwitchTypeFromString(display)) <= 0) {
7384             virReportError(VIR_ERR_XML_ERROR,
7385                            _("unknown value '%s' for <hostdev> attribute "
7386                              "'display'"),
7387                            display);
7388             return -1;
7389         }
7390 
7391         if (ramfb &&
7392             (mdevsrc->ramfb = virTristateSwitchTypeFromString(ramfb)) <= 0) {
7393             virReportError(VIR_ERR_XML_ERROR,
7394                            _("unknown value '%s' for <hostdev> attribute "
7395                              "'ramfb'"),
7396                            ramfb);
7397             return -1;
7398         }
7399     }
7400 
7401     switch (def->source.subsys.type) {
7402     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
7403         if (virDomainHostdevSubsysPCIDefParseXML(sourcenode, ctxt, def, flags) < 0)
7404             return -1;
7405 
7406         backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT;
7407         if ((backendStr = virXPathString("string(./driver/@name)", ctxt)) &&
7408             (((backend = virDomainHostdevSubsysPCIBackendTypeFromString(backendStr)) < 0) ||
7409              backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT)) {
7410             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7411                            _("Unknown PCI device <driver name='%s'/> "
7412                              "has been specified"), backendStr);
7413             return -1;
7414         }
7415         pcisrc->backend = backend;
7416 
7417         break;
7418 
7419     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
7420         if (virDomainHostdevSubsysUSBDefParseXML(sourcenode, ctxt, def) < 0)
7421             return -1;
7422         break;
7423 
7424     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
7425         if (virDomainHostdevSubsysSCSIDefParseXML(sourcenode, scsisrc, ctxt, flags, xmlopt) < 0)
7426             return -1;
7427         break;
7428 
7429     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
7430         if (virDomainHostdevSubsysSCSIVHostDefParseXML(sourcenode, def) < 0)
7431             return -1;
7432         break;
7433     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
7434         if (virDomainHostdevSubsysMediatedDevDefParseXML(def, ctxt) < 0)
7435             return -1;
7436         break;
7437 
7438     default:
7439         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7440                        _("address type='%s' not supported in hostdev interfaces"),
7441                        virDomainHostdevSubsysTypeToString(def->source.subsys.type));
7442         return -1;
7443     }
7444 
7445     return 0;
7446 }
7447 
7448 static virNetDevIPAddr *
virDomainNetIPParseXML(xmlNodePtr node)7449 virDomainNetIPParseXML(xmlNodePtr node)
7450 {
7451     /* Parse the prefix in every case */
7452     unsigned int prefixValue = 0;
7453     int family = AF_UNSPEC;
7454     g_autofree virNetDevIPAddr *ip = NULL;
7455     g_autofree char *prefixStr = NULL;
7456     g_autofree char *familyStr = NULL;
7457     g_autofree char *address = NULL;
7458     g_autofree char *peer = NULL;
7459 
7460     if (!(address = virXMLPropString(node, "address"))) {
7461         virReportError(VIR_ERR_XML_ERROR, "%s",
7462                        _("Missing required address in <ip>"));
7463         return NULL;
7464     }
7465 
7466     familyStr = virXMLPropString(node, "family");
7467     if (familyStr && STREQ(familyStr, "ipv4"))
7468         family = AF_INET;
7469     else if (familyStr && STREQ(familyStr, "ipv6"))
7470         family = AF_INET6;
7471     else
7472         family = virSocketAddrNumericFamily(address);
7473 
7474     ip = g_new0(virNetDevIPAddr, 1);
7475 
7476     if (virSocketAddrParse(&ip->address, address, family) < 0) {
7477         virReportError(VIR_ERR_XML_ERROR,
7478                        _("Invalid address '%s' in <ip>"),
7479                        address);
7480         return NULL;
7481     }
7482 
7483     prefixStr = virXMLPropString(node, "prefix");
7484     if (prefixStr &&
7485         ((virStrToLong_ui(prefixStr, NULL, 10, &prefixValue) < 0) ||
7486          (family == AF_INET6 && prefixValue > 128) ||
7487          (family == AF_INET && prefixValue > 32))) {
7488         virReportError(VIR_ERR_XML_ERROR,
7489                        _("Invalid prefix value '%s' in <ip>"),
7490                        prefixStr);
7491         return NULL;
7492     }
7493     ip->prefix = prefixValue;
7494 
7495     if ((peer = virXMLPropString(node, "peer")) != NULL &&
7496         virSocketAddrParse(&ip->peer, peer, family) < 0) {
7497         virReportError(VIR_ERR_INVALID_ARG,
7498                        _("Invalid peer '%s' in <ip>"), peer);
7499         return NULL;
7500     }
7501 
7502     return g_steal_pointer(&ip);
7503 }
7504 
7505 
7506 /* fill in a virNetDevIPInfo *from the <route> and <ip>
7507  * elements found in the given XML context.
7508  *
7509  * return 0 on success (including none found) and -1 on failure.
7510  */
7511 static int
virDomainNetIPInfoParseXML(const char * source,xmlXPathContextPtr ctxt,virNetDevIPInfo * def)7512 virDomainNetIPInfoParseXML(const char *source,
7513                            xmlXPathContextPtr ctxt,
7514                            virNetDevIPInfo *def)
7515 {
7516     g_autoptr(virNetDevIPRoute) route = NULL;
7517     int nnodes;
7518     int ret = -1;
7519     size_t i;
7520     g_autofree xmlNodePtr *nodes = NULL;
7521     g_autofree virNetDevIPAddr *ip = NULL;
7522 
7523     if ((nnodes = virXPathNodeSet("./ip", ctxt, &nodes)) < 0)
7524         goto cleanup;
7525 
7526     for (i = 0; i < nnodes; i++) {
7527         if (!(ip = virDomainNetIPParseXML(nodes[i])))
7528             goto cleanup;
7529 
7530         VIR_APPEND_ELEMENT(def->ips, def->nips, ip);
7531     }
7532     VIR_FREE(nodes);
7533 
7534     if ((nnodes = virXPathNodeSet("./route", ctxt, &nodes)) < 0)
7535         goto cleanup;
7536 
7537     for (i = 0; i < nnodes; i++) {
7538         if (!(route = virNetDevIPRouteParseXML(source, nodes[i], ctxt)))
7539             goto cleanup;
7540 
7541         VIR_APPEND_ELEMENT(def->routes, def->nroutes, route);
7542     }
7543 
7544     ret = 0;
7545  cleanup:
7546     if (ret < 0)
7547         virNetDevIPInfoClear(def);
7548     return ret;
7549 }
7550 
7551 
7552 static int
virDomainNetDefCoalesceParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virNetDevCoalesce ** coalesce)7553 virDomainNetDefCoalesceParseXML(xmlNodePtr node,
7554                                 xmlXPathContextPtr ctxt,
7555                                 virNetDevCoalesce **coalesce)
7556 {
7557     VIR_XPATH_NODE_AUTORESTORE(ctxt)
7558     unsigned long long tmp = 0;
7559     g_autofree char *str = NULL;
7560 
7561     ctxt->node = node;
7562 
7563     str = virXPathString("string(./rx/frames/@max)", ctxt);
7564     if (!str)
7565         return 0;
7566 
7567     if (virStrToLong_ullp(str, NULL, 10, &tmp) < 0) {
7568         virReportError(VIR_ERR_XML_DETAIL,
7569                        _("cannot parse value '%s' for coalesce parameter"),
7570                        str);
7571         return -1;
7572     }
7573 
7574     if (tmp > UINT32_MAX) {
7575         virReportError(VIR_ERR_OVERFLOW,
7576                        _("value '%llu' is too big for coalesce "
7577                          "parameter, maximum is '%lu'"),
7578                        tmp, (unsigned long) UINT32_MAX);
7579         return -1;
7580     }
7581 
7582     *coalesce = g_new0(virNetDevCoalesce, 1);
7583     (*coalesce)->rx_max_coalesced_frames = tmp;
7584 
7585     return 0;
7586 }
7587 
7588 static void
virDomainNetDefCoalesceFormatXML(virBuffer * buf,virNetDevCoalesce * coalesce)7589 virDomainNetDefCoalesceFormatXML(virBuffer *buf,
7590                                  virNetDevCoalesce *coalesce)
7591 {
7592     if (!coalesce || !coalesce->rx_max_coalesced_frames)
7593         return;
7594 
7595     virBufferAddLit(buf, "<coalesce>\n");
7596     virBufferAdjustIndent(buf, 2);
7597 
7598     virBufferAddLit(buf, "<rx>\n");
7599     virBufferAdjustIndent(buf, 2);
7600 
7601     virBufferAsprintf(buf, "<frames max='%u'/>\n",
7602                       coalesce->rx_max_coalesced_frames);
7603 
7604     virBufferAdjustIndent(buf, -2);
7605     virBufferAddLit(buf, "</rx>\n");
7606 
7607     virBufferAdjustIndent(buf, -2);
7608     virBufferAddLit(buf, "</coalesce>\n");
7609 }
7610 
7611 
7612 static int
virDomainHostdevDefParseXMLCaps(xmlNodePtr node G_GNUC_UNUSED,xmlXPathContextPtr ctxt,const char * type,virDomainHostdevDef * def)7613 virDomainHostdevDefParseXMLCaps(xmlNodePtr node G_GNUC_UNUSED,
7614                                 xmlXPathContextPtr ctxt,
7615                                 const char *type,
7616                                 virDomainHostdevDef *def)
7617 {
7618     /* @type is passed in from the caller rather than read from the
7619      * xml document, because it is specified in different places for
7620      * different kinds of defs - it is an attribute of
7621      * <source>/<address> for an intelligent hostdev (<interface>),
7622      * but an attribute of the toplevel element for a standard
7623      * <hostdev>.  (the functions we're going to call expect address
7624      * type to already be known).
7625      */
7626     if (type) {
7627         if ((def->source.caps.type
7628              = virDomainHostdevCapsTypeFromString(type)) < 0) {
7629             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7630                            _("unknown host device source address type '%s'"),
7631                            type);
7632             return -1;
7633         }
7634     } else {
7635         virReportError(VIR_ERR_XML_ERROR,
7636                        "%s", _("missing source address type"));
7637         return -1;
7638     }
7639 
7640     if (!virXPathNode("./source", ctxt)) {
7641         virReportError(VIR_ERR_XML_ERROR, "%s",
7642                        _("Missing <source> element in hostdev device"));
7643         return -1;
7644     }
7645 
7646     switch (def->source.caps.type) {
7647     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
7648         if (!(def->source.caps.u.storage.block =
7649               virXPathString("string(./source/block[1])", ctxt))) {
7650             virReportError(VIR_ERR_XML_ERROR, "%s",
7651                            _("Missing <block> element in hostdev storage device"));
7652             return -1;
7653         }
7654         break;
7655     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
7656         if (!(def->source.caps.u.misc.chardev =
7657               virXPathString("string(./source/char[1])", ctxt))) {
7658             virReportError(VIR_ERR_XML_ERROR, "%s",
7659                            _("Missing <char> element in hostdev character device"));
7660             return -1;
7661         }
7662         break;
7663     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
7664         if (!(def->source.caps.u.net.ifname =
7665               virXPathString("string(./source/interface[1])", ctxt))) {
7666             virReportError(VIR_ERR_XML_ERROR, "%s",
7667                            _("Missing <interface> element in hostdev net device"));
7668             return -1;
7669         }
7670         if (virDomainNetIPInfoParseXML(_("Domain hostdev device"),
7671                                        ctxt, &def->source.caps.u.net.ip) < 0)
7672             return -1;
7673         break;
7674     default:
7675         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7676                        _("address type='%s' not supported in hostdev interfaces"),
7677                        virDomainHostdevCapsTypeToString(def->source.caps.type));
7678         return -1;
7679     }
7680 
7681     return 0;
7682 }
7683 
7684 
7685 virDomainControllerDef *
virDomainDeviceFindSCSIController(const virDomainDef * def,const virDomainDeviceDriveAddress * addr)7686 virDomainDeviceFindSCSIController(const virDomainDef *def,
7687                                   const virDomainDeviceDriveAddress *addr)
7688 {
7689     size_t i;
7690 
7691     for (i = 0; i < def->ncontrollers; i++) {
7692         if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI &&
7693             def->controllers[i]->idx == addr->controller)
7694             return def->controllers[i];
7695     }
7696 
7697     return NULL;
7698 }
7699 
7700 int
virDomainDiskDefAssignAddress(virDomainXMLOption * xmlopt G_GNUC_UNUSED,virDomainDiskDef * def,const virDomainDef * vmdef)7701 virDomainDiskDefAssignAddress(virDomainXMLOption *xmlopt G_GNUC_UNUSED,
7702                               virDomainDiskDef *def,
7703                               const virDomainDef *vmdef)
7704 {
7705     int idx = virDiskNameToIndex(def->dst);
7706     if (idx < 0) {
7707         virReportError(VIR_ERR_XML_ERROR,
7708                        _("Unknown disk name '%s' and no address specified"),
7709                        def->dst);
7710         return -1;
7711     }
7712 
7713     switch (def->bus) {
7714     case VIR_DOMAIN_DISK_BUS_SCSI: {
7715         virDomainDeviceDriveAddress addr = {0, 0, 0, 0, 0};
7716         unsigned int controller;
7717         unsigned int unit;
7718 
7719         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
7720 
7721         if (vmdef->scsiBusMaxUnit > SCSI_NARROW_BUS_MAX_CONT_UNIT) {
7722             /* For a wide SCSI bus we define the default mapping to be
7723              * 16 units per bus, 1 bus per controller, many controllers.
7724              * Unit 7 is the SCSI controller itself. Therefore unit 7
7725              * cannot be assigned to disks and is skipped.
7726              */
7727             controller = idx / (vmdef->scsiBusMaxUnit - 1);
7728             unit = idx % (vmdef->scsiBusMaxUnit - 1);
7729 
7730             /* Skip the SCSI controller at unit 7 */
7731             if (unit >= 7)
7732                 ++unit;
7733         } else {
7734             /* For a narrow SCSI bus we define the default mapping to be
7735              * 7 units per bus, 1 bus per controller, many controllers */
7736             controller = idx / 7;
7737             unit = idx % 7;
7738         }
7739 
7740         addr.controller = controller;
7741         addr.unit = unit;
7742 
7743         if (virDomainDriveAddressIsUsedByHostdev(vmdef,
7744                                                  VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI,
7745                                                  &addr)) {
7746             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7747                            _("using disk target name '%s' conflicts with "
7748                              "SCSI host device address controller='%u' "
7749                              "bus='%u' target='%u' unit='%u"),
7750                            def->dst, controller, 0, 0, unit);
7751             return -1;
7752         }
7753 
7754         memcpy(&def->info.addr.drive, &addr, sizeof(addr));
7755         break;
7756     }
7757 
7758     case VIR_DOMAIN_DISK_BUS_IDE:
7759         /* For IDE we define the default mapping to be 2 units
7760          * per bus, 2 bus per controller, many controllers */
7761         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
7762         def->info.addr.drive.controller = idx / 4;
7763         def->info.addr.drive.bus = (idx % 4) / 2;
7764         def->info.addr.drive.unit = (idx % 2);
7765         break;
7766 
7767     case VIR_DOMAIN_DISK_BUS_SATA:
7768         /* For SATA we define the default mapping to be 6 units
7769          * per bus, 1 bus per controller, many controllers */
7770         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
7771         def->info.addr.drive.controller = idx / 6;
7772         def->info.addr.drive.bus = 0;
7773         def->info.addr.drive.unit = idx % 6;
7774         break;
7775 
7776     case VIR_DOMAIN_DISK_BUS_FDC:
7777         /* For FDC we define the default mapping to be 2 units
7778          * per bus, 1 bus per controller, many controllers */
7779         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
7780         def->info.addr.drive.controller = idx / 2;
7781         def->info.addr.drive.bus = 0;
7782         def->info.addr.drive.unit = idx % 2;
7783         break;
7784 
7785     case VIR_DOMAIN_DISK_BUS_NONE:
7786     case VIR_DOMAIN_DISK_BUS_VIRTIO:
7787     case VIR_DOMAIN_DISK_BUS_XEN:
7788     case VIR_DOMAIN_DISK_BUS_USB:
7789     case VIR_DOMAIN_DISK_BUS_UML:
7790     case VIR_DOMAIN_DISK_BUS_SD:
7791     case VIR_DOMAIN_DISK_BUS_LAST:
7792     default:
7793         /* Other disk bus's aren't controller based */
7794         break;
7795     }
7796 
7797     return 0;
7798 }
7799 
7800 static virSecurityLabelDef *
virSecurityLabelDefParseXML(xmlXPathContextPtr ctxt,unsigned int flags)7801 virSecurityLabelDefParseXML(xmlXPathContextPtr ctxt,
7802                             unsigned int flags)
7803 {
7804     g_autofree char *model = NULL;
7805     g_autofree char *relabel = NULL;
7806     g_autoptr(virSecurityLabelDef) seclabel = NULL;
7807 
7808     if ((model = virXMLPropString(ctxt->node, "model")) &&
7809         strlen(model) >= VIR_SECURITY_MODEL_BUFLEN - 1)
7810         g_clear_pointer(&model, g_free);
7811 
7812     if (!(seclabel = virSecurityLabelDefNew(model)))
7813         return NULL;
7814 
7815     /* set default value */
7816     seclabel->type = VIR_DOMAIN_SECLABEL_DYNAMIC;
7817 
7818     if (virXMLPropEnum(ctxt->node, "type",
7819                        virDomainSeclabelTypeFromString,
7820                        VIR_XML_PROP_NONZERO,
7821                        &seclabel->type) < 0)
7822         return NULL;
7823 
7824     if (seclabel->type == VIR_DOMAIN_SECLABEL_STATIC ||
7825         seclabel->type == VIR_DOMAIN_SECLABEL_NONE)
7826         seclabel->relabel = false;
7827 
7828     if ((relabel = virXMLPropString(ctxt->node, "relabel"))) {
7829         if (virStringParseYesNo(relabel, &seclabel->relabel) < 0) {
7830             virReportError(VIR_ERR_XML_ERROR,
7831                            _("invalid security relabel value '%s'"), relabel);
7832             return NULL;
7833         }
7834     }
7835 
7836     if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
7837         !seclabel->relabel) {
7838         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7839                        "%s", _("dynamic label type must use resource relabeling"));
7840         return NULL;
7841     }
7842     if (seclabel->type == VIR_DOMAIN_SECLABEL_NONE &&
7843         seclabel->relabel) {
7844         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7845                        "%s", _("resource relabeling is not compatible with 'none' label type"));
7846         return NULL;
7847     }
7848 
7849     /* For the model 'none' none of the following labels is going to be
7850      * present. Hence, return now. */
7851 
7852     if (STREQ_NULLABLE(seclabel->model, "none")) {
7853         if (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) {
7854             /* Fix older configurations */
7855             seclabel->type = VIR_DOMAIN_SECLABEL_NONE;
7856             seclabel->relabel = false;
7857         } else {
7858             if (seclabel->type != VIR_DOMAIN_SECLABEL_NONE) {
7859                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
7860                                _("unsupported type='%s' to model 'none'"),
7861                                virDomainSeclabelTypeToString(seclabel->type));
7862                 return NULL;
7863             }
7864             /* combination of relabel='yes' and type='static'
7865              * is checked a few lines above. */
7866         }
7867         return g_steal_pointer(&seclabel);
7868     }
7869 
7870     /* Only parse label, if using static labels, or
7871      * if the 'live' VM XML is requested
7872      */
7873     if (seclabel->type == VIR_DOMAIN_SECLABEL_STATIC ||
7874         (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
7875          seclabel->type != VIR_DOMAIN_SECLABEL_NONE)) {
7876         seclabel->label = virXPathString("string(./label[1])", ctxt);
7877         if (!seclabel->label ||
7878             strlen(seclabel->label) >= VIR_SECURITY_LABEL_BUFLEN - 1) {
7879             virReportError(VIR_ERR_XML_ERROR,
7880                            "%s", _("security label is missing"));
7881             return NULL;
7882         }
7883     }
7884 
7885     /* Only parse imagelabel, if requested live XML with relabeling */
7886     if (seclabel->relabel &&
7887         (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
7888          seclabel->type != VIR_DOMAIN_SECLABEL_NONE)) {
7889         seclabel->imagelabel = virXPathString("string(./imagelabel[1])", ctxt);
7890 
7891         if (!seclabel->imagelabel ||
7892             strlen(seclabel->imagelabel) >= VIR_SECURITY_LABEL_BUFLEN - 1) {
7893             virReportError(VIR_ERR_XML_ERROR,
7894                            "%s", _("security imagelabel is missing"));
7895             return NULL;
7896         }
7897     }
7898 
7899     /* Only parse baselabel for dynamic label type */
7900     if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
7901         seclabel->baselabel = virXPathString("string(./baselabel[1])", ctxt);
7902 
7903         if (seclabel->baselabel &&
7904             strlen(seclabel->baselabel) >= VIR_SECURITY_LABEL_BUFLEN - 1)
7905             g_clear_pointer(&seclabel->baselabel, g_free);
7906     }
7907 
7908     return g_steal_pointer(&seclabel);
7909 }
7910 
7911 static int
virSecurityLabelDefsParseXML(virDomainDef * def,xmlXPathContextPtr ctxt,virDomainXMLOption * xmlopt,unsigned int flags)7912 virSecurityLabelDefsParseXML(virDomainDef *def,
7913                              xmlXPathContextPtr ctxt,
7914                              virDomainXMLOption *xmlopt,
7915                              unsigned int flags)
7916 {
7917     VIR_XPATH_NODE_AUTORESTORE(ctxt)
7918     size_t i = 0, j;
7919     int n;
7920     g_autofree xmlNodePtr *list = NULL;
7921 
7922     /* Allocate a security labels based on XML */
7923     if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) < 0)
7924         goto error;
7925     if (n == 0)
7926         return 0;
7927 
7928     def->seclabels = g_new0(virSecurityLabelDef *, n);
7929 
7930     /* Parse each "seclabel" tag */
7931     for (i = 0; i < n; i++) {
7932         virSecurityLabelDef *seclabel;
7933 
7934         ctxt->node = list[i];
7935         if (!(seclabel = virSecurityLabelDefParseXML(ctxt, flags)))
7936             goto error;
7937 
7938         for (j = 0; j < i; j++) {
7939             if (STREQ_NULLABLE(seclabel->model, def->seclabels[j]->model)) {
7940                 virReportError(VIR_ERR_XML_DETAIL,
7941                                _("seclabel for model %s is already provided"),
7942                                seclabel->model);
7943                 virSecurityLabelDefFree(seclabel);
7944                 goto error;
7945             }
7946         }
7947 
7948         def->seclabels[i] = seclabel;
7949     }
7950     def->nseclabels = n;
7951 
7952     /* libvirt versions prior to 0.10.0 support just a single seclabel element
7953      * in guest's XML and model attribute can be suppressed if type is none or
7954      * type is dynamic, baselabel is not defined and INACTIVE flag is set.
7955      *
7956      * To avoid compatibility issues, for this specific case the first model
7957      * defined in host's capabilities is used as model for the seclabel.
7958      */
7959     if (def->nseclabels == 1 &&
7960         !def->seclabels[0]->model &&
7961         xmlopt != NULL &&
7962         xmlopt->config.defSecModel != NULL) {
7963         if (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_NONE ||
7964             (def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
7965              !def->seclabels[0]->baselabel &&
7966              (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))) {
7967             /* Copy model from host. */
7968             VIR_DEBUG("Found seclabel without a model, using '%s'",
7969                       xmlopt->config.defSecModel);
7970             def->seclabels[0]->model = g_strdup(xmlopt->config.defSecModel);
7971 
7972             if (STREQ(def->seclabels[0]->model, "none") &&
7973                 flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) {
7974                 /* Fix older configurations */
7975                 def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE;
7976                 def->seclabels[0]->relabel = false;
7977             }
7978         } else {
7979             virReportError(VIR_ERR_XML_ERROR, "%s",
7980                            _("missing security model in domain seclabel"));
7981             goto error;
7982         }
7983     }
7984 
7985     /* Checking missing model information */
7986     if (def->nseclabels > 1) {
7987         for (; n; n--) {
7988             if (def->seclabels[n - 1]->model == NULL) {
7989                 virReportError(VIR_ERR_XML_ERROR, "%s",
7990                                _("missing security model "
7991                                  "when using multiple labels"));
7992                 goto error;
7993             }
7994         }
7995     }
7996 
7997     return 0;
7998 
7999  error:
8000     for (; i > 0; i--)
8001         virSecurityLabelDefFree(def->seclabels[i - 1]);
8002     VIR_FREE(def->seclabels);
8003     def->nseclabels = 0;
8004     return -1;
8005 }
8006 
8007 /* Parse the <seclabel> from a disk or character device. */
8008 static int
virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDef *** seclabels_rtn,size_t * nseclabels_rtn,xmlXPathContextPtr ctxt,unsigned int flags)8009 virSecurityDeviceLabelDefParseXML(virSecurityDeviceLabelDef ***seclabels_rtn,
8010                                   size_t *nseclabels_rtn,
8011                                   xmlXPathContextPtr ctxt,
8012                                   unsigned int flags)
8013 {
8014     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8015     virSecurityDeviceLabelDef **seclabels = NULL;
8016     size_t nseclabels = 0;
8017     int n;
8018     size_t i, j;
8019     g_autofree xmlNodePtr *list = NULL;
8020 
8021     if ((n = virXPathNodeSet("./seclabel", ctxt, &list)) < 0)
8022         goto error;
8023     if (n == 0)
8024         return 0;
8025 
8026     seclabels = g_new0(virSecurityDeviceLabelDef *, n);
8027     nseclabels = n;
8028     for (i = 0; i < n; i++)
8029         seclabels[i] = g_new0(virSecurityDeviceLabelDef, 1);
8030 
8031     for (i = 0; i < n; i++) {
8032         g_autofree char *model = NULL;
8033         g_autofree char *relabel = NULL;
8034         g_autofree char *label = NULL;
8035         g_autofree char *labelskip = NULL;
8036 
8037         /* get model associated to this override */
8038         model = virXMLPropString(list[i], "model");
8039         if (model) {
8040             /* check for duplicate seclabels */
8041             for (j = 0; j < i; j++) {
8042                 if (STREQ_NULLABLE(model, seclabels[j]->model)) {
8043                     virReportError(VIR_ERR_XML_DETAIL,
8044                                    _("seclabel for model %s is already provided"), model);
8045                     goto error;
8046                 }
8047             }
8048             seclabels[i]->model = g_steal_pointer(&model);
8049         }
8050 
8051         relabel = virXMLPropString(list[i], "relabel");
8052         if (relabel != NULL) {
8053             if (virStringParseYesNo(relabel, &seclabels[i]->relabel) < 0) {
8054                 virReportError(VIR_ERR_XML_ERROR,
8055                                _("invalid security relabel value %s"),
8056                                relabel);
8057                 goto error;
8058             }
8059         } else {
8060             seclabels[i]->relabel = true;
8061         }
8062 
8063         /* labelskip is only parsed on live images */
8064         labelskip = virXMLPropString(list[i], "labelskip");
8065         seclabels[i]->labelskip = false;
8066         if (labelskip && !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
8067             ignore_value(virStringParseYesNo(labelskip, &seclabels[i]->labelskip));
8068 
8069         ctxt->node = list[i];
8070         label = virXPathString("string(./label)", ctxt);
8071 
8072         if (label && strlen(label) < VIR_SECURITY_LABEL_BUFLEN)
8073             seclabels[i]->label = g_steal_pointer(&label);
8074 
8075         if (seclabels[i]->label && !seclabels[i]->relabel) {
8076             virReportError(VIR_ERR_XML_ERROR,
8077                            _("Cannot specify a label if relabelling is "
8078                              "turned off. model=%s"),
8079                              NULLSTR(seclabels[i]->model));
8080             goto error;
8081         }
8082     }
8083 
8084     *nseclabels_rtn = nseclabels;
8085     *seclabels_rtn = seclabels;
8086 
8087     return 0;
8088 
8089  error:
8090     for (i = 0; i < nseclabels; i++)
8091         virSecurityDeviceLabelDefFree(seclabels[i]);
8092     VIR_FREE(seclabels);
8093     return -1;
8094 }
8095 
8096 
8097 /* Parse the XML definition for a lease
8098  */
8099 static virDomainLeaseDef *
virDomainLeaseDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt)8100 virDomainLeaseDefParseXML(xmlNodePtr node,
8101                           xmlXPathContextPtr ctxt)
8102 {
8103     virDomainLeaseDef *def;
8104     g_autofree char *lockspace = NULL;
8105     g_autofree char *key = NULL;
8106     g_autofree char *path = NULL;
8107     xmlNodePtr targetNode = NULL;
8108     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8109 
8110     ctxt->node = node;
8111     def = g_new0(virDomainLeaseDef, 1);
8112 
8113     if (!(key = virXPathString("string(./key)", ctxt))) {
8114         virReportError(VIR_ERR_XML_ERROR, "%s",
8115                        _("Missing 'key' element for lease"));
8116         goto error;
8117     }
8118 
8119     if (!(lockspace = virXPathString("string(./lockspace)", ctxt)))
8120         goto error;
8121 
8122     if (!(targetNode = virXPathNode("./target", ctxt))) {
8123         virReportError(VIR_ERR_XML_ERROR, "%s",
8124                        _("Missing 'target' element for lease"));
8125         goto error;
8126     }
8127 
8128     if (!(path = virXMLPropString(targetNode, "path"))) {
8129         virReportError(VIR_ERR_XML_ERROR, "%s",
8130                        _("Missing 'path' attribute to 'target' element for lease"));
8131         goto error;
8132     }
8133 
8134     if (virXMLPropULongLong(targetNode, "offset", 10,
8135                             VIR_XML_PROP_NONE, &def->offset) < 0)
8136         goto error;
8137 
8138     def->key = g_steal_pointer(&key);
8139     def->lockspace = g_steal_pointer(&lockspace);
8140     def->path = g_steal_pointer(&path);
8141 
8142     return def;
8143 
8144  error:
8145     virDomainLeaseDefFree(def);
8146     return NULL;
8147 }
8148 
8149 static int
virDomainDiskSourcePoolDefParse(xmlNodePtr node,virStorageSourcePoolDef ** srcpool)8150 virDomainDiskSourcePoolDefParse(xmlNodePtr node,
8151                                 virStorageSourcePoolDef **srcpool)
8152 {
8153     virStorageSourcePoolDef *source;
8154     int ret = -1;
8155     g_autofree char *mode = NULL;
8156 
8157     *srcpool = NULL;
8158 
8159     source = g_new0(virStorageSourcePoolDef, 1);
8160 
8161     source->pool = virXMLPropString(node, "pool");
8162     source->volume = virXMLPropString(node, "volume");
8163     mode = virXMLPropString(node, "mode");
8164 
8165     /* CD-ROM and Floppy allows no source */
8166     if (!source->pool && !source->volume) {
8167         ret = 0;
8168         goto cleanup;
8169     }
8170 
8171     if (!source->pool || !source->volume) {
8172         virReportError(VIR_ERR_XML_ERROR, "%s",
8173                        _("'pool' and 'volume' must be specified together "
8174                          "for 'pool' type source"));
8175         goto cleanup;
8176     }
8177 
8178     if (mode &&
8179         (source->mode = virStorageSourcePoolModeTypeFromString(mode)) <= 0) {
8180         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
8181                        _("unknown source mode '%s' for volume type disk"),
8182                        mode);
8183         goto cleanup;
8184     }
8185 
8186     *srcpool = g_steal_pointer(&source);
8187     ret = 0;
8188 
8189  cleanup:
8190     virStorageSourcePoolDefFree(source);
8191     return ret;
8192 }
8193 
8194 
8195 static virStorageNetCookieDef *
virDomainStorageNetCookieParse(xmlNodePtr node,xmlXPathContextPtr ctxt)8196 virDomainStorageNetCookieParse(xmlNodePtr node,
8197                                xmlXPathContextPtr ctxt)
8198 {
8199     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8200     g_autoptr(virStorageNetCookieDef) cookie = NULL;
8201 
8202     ctxt->node = node;
8203 
8204     cookie = g_new0(virStorageNetCookieDef, 1);
8205 
8206     if (!(cookie->name = virXPathString("string(./@name)", ctxt))) {
8207         virReportError(VIR_ERR_XML_ERROR, "%s", _("missing cookie name"));
8208         return NULL;
8209     }
8210 
8211     if (!(cookie->value = virXPathString("string(.)", ctxt))) {
8212         virReportError(VIR_ERR_XML_ERROR, _("missing value for cookie '%s'"),
8213                        cookie->name);
8214         return NULL;
8215     }
8216 
8217     return g_steal_pointer(&cookie);
8218 }
8219 
8220 
8221 static int
virDomainStorageNetCookiesParse(xmlNodePtr node,xmlXPathContextPtr ctxt,virStorageSource * src)8222 virDomainStorageNetCookiesParse(xmlNodePtr node,
8223                                 xmlXPathContextPtr ctxt,
8224                                 virStorageSource *src)
8225 {
8226     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8227     g_autofree xmlNodePtr *nodes = NULL;
8228     ssize_t nnodes;
8229     size_t i;
8230 
8231     ctxt->node = node;
8232 
8233     if ((nnodes = virXPathNodeSet("./cookie", ctxt, &nodes)) < 0)
8234         return -1;
8235 
8236     src->cookies = g_new0(virStorageNetCookieDef *, nnodes);
8237     src->ncookies = nnodes;
8238 
8239     for (i = 0; i < nnodes; i++) {
8240         if (!(src->cookies[i] = virDomainStorageNetCookieParse(nodes[i], ctxt)))
8241             return -1;
8242     }
8243 
8244     if (virStorageSourceNetCookiesValidate(src) < 0)
8245         return -1;
8246 
8247     return 0;
8248 }
8249 
8250 
8251 static int
virDomainDiskSourceNetworkParse(xmlNodePtr node,xmlXPathContextPtr ctxt,virStorageSource * src,unsigned int flags)8252 virDomainDiskSourceNetworkParse(xmlNodePtr node,
8253                                 xmlXPathContextPtr ctxt,
8254                                 virStorageSource *src,
8255                                 unsigned int flags)
8256 {
8257     virStorageNetProtocol protocol;
8258     xmlNodePtr tmpnode;
8259 
8260     if (virXMLPropEnum(node, "protocol", virStorageNetProtocolTypeFromString,
8261                        VIR_XML_PROP_REQUIRED, &protocol) < 0)
8262         return -1;
8263 
8264     src->protocol = protocol;
8265 
8266     if (!(src->path = virXMLPropString(node, "name")) &&
8267         src->protocol != VIR_STORAGE_NET_PROTOCOL_NBD) {
8268         virReportError(VIR_ERR_XML_ERROR, "%s",
8269                        _("missing name for disk source"));
8270         return -1;
8271     }
8272 
8273     if (virXMLPropTristateBool(node, "tls", VIR_XML_PROP_NONE,
8274                                &src->haveTLS) < 0)
8275         return -1;
8276 
8277     if (flags & VIR_DOMAIN_DEF_PARSE_STATUS) {
8278         int value;
8279         if (virXMLPropInt(node, "tlsFromConfig", 10, VIR_XML_PROP_NONE,
8280                           &value, 0) < 0)
8281             return -1;
8282         src->tlsFromConfig = !!value;
8283     }
8284 
8285     /* for historical reasons we store the volume and image name in one XML
8286      * element although it complicates thing when attempting to access them. */
8287     if (src->path &&
8288         (src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER ||
8289          src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD)) {
8290         char *tmp;
8291         if (!(tmp = strchr(src->path, '/')) ||
8292             tmp == src->path) {
8293             virReportError(VIR_ERR_XML_ERROR,
8294                            _("can't split path '%s' into pool name and image "
8295                              "name"), src->path);
8296             return -1;
8297         }
8298 
8299         src->volume = src->path;
8300 
8301         src->path = g_strdup(tmp + 1);
8302 
8303         tmp[0] = '\0';
8304     }
8305 
8306     /* snapshot currently works only for remote disks */
8307     src->snapshot = virXPathString("string(./snapshot/@name)", ctxt);
8308 
8309     /* config file currently only works with remote disks */
8310     src->configFile = virXPathString("string(./config/@file)", ctxt);
8311 
8312     if (src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
8313         src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS)
8314         src->query = virXMLPropString(node, "query");
8315 
8316     if (virDomainStorageNetworkParseHosts(node, ctxt, &src->hosts, &src->nhosts) < 0)
8317         return -1;
8318 
8319     if (src->protocol == VIR_STORAGE_NET_PROTOCOL_NFS)
8320         virDomainStorageNetworkParseNFS(node, ctxt, src);
8321 
8322     virStorageSourceNetworkAssignDefaultPorts(src);
8323 
8324     virStorageSourceInitiatorParseXML(ctxt, &src->initiator);
8325 
8326     if ((src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS ||
8327          src->protocol == VIR_STORAGE_NET_PROTOCOL_FTPS) &&
8328         (tmpnode = virXPathNode("./ssl", ctxt))) {
8329         if (virXMLPropTristateBool(tmpnode, "verify", VIR_XML_PROP_NONE,
8330                                    &src->sslverify) < 0)
8331             return -1;
8332     }
8333 
8334     if ((src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
8335          src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS) &&
8336         (tmpnode = virXPathNode("./cookies", ctxt))) {
8337         if (virDomainStorageNetCookiesParse(tmpnode, ctxt, src) < 0)
8338             return -1;
8339     }
8340 
8341     if (src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
8342         src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS ||
8343         src->protocol == VIR_STORAGE_NET_PROTOCOL_FTP ||
8344         src->protocol == VIR_STORAGE_NET_PROTOCOL_FTPS) {
8345 
8346         if (virXPathULongLong("string(./readahead/@size)", ctxt, &src->readahead) == -2 ||
8347             virXPathULongLong("string(./timeout/@seconds)", ctxt, &src->timeout) == -2) {
8348             virReportError(VIR_ERR_XML_ERROR, "%s",
8349                           _("invalid readahead size or timeout"));
8350             return -1;
8351         }
8352     }
8353 
8354     return 0;
8355 }
8356 
8357 
8358 static int
virDomainDiskSourceNVMeParse(xmlNodePtr node,xmlXPathContextPtr ctxt,virStorageSource * src)8359 virDomainDiskSourceNVMeParse(xmlNodePtr node,
8360                              xmlXPathContextPtr ctxt,
8361                              virStorageSource *src)
8362 {
8363     g_autoptr(virStorageSourceNVMeDef) nvme = NULL;
8364     g_autofree char *type = NULL;
8365     g_autofree char *namespc = NULL;
8366     xmlNodePtr address;
8367 
8368     nvme = g_new0(virStorageSourceNVMeDef, 1);
8369 
8370     if (!(type = virXMLPropString(node, "type"))) {
8371         virReportError(VIR_ERR_XML_ERROR, "%s",
8372                        _("missing 'type' attribute to disk source"));
8373         return -1;
8374     }
8375 
8376     if (STRNEQ(type, "pci")) {
8377         virReportError(VIR_ERR_XML_ERROR,
8378                        _("unsupported source type '%s'"),
8379                        type);
8380         return -1;
8381     }
8382 
8383     if (!(namespc = virXMLPropString(node, "namespace"))) {
8384         virReportError(VIR_ERR_XML_ERROR, "%s",
8385                        _("missing 'namespace' attribute to disk source"));
8386         return -1;
8387     }
8388 
8389     if (virStrToLong_ull(namespc, NULL, 10, &nvme->namespc) < 0) {
8390         virReportError(VIR_ERR_XML_ERROR,
8391                        _("malformed namespace '%s'"),
8392                        namespc);
8393         return -1;
8394     }
8395 
8396     if (virXMLPropTristateBool(node, "managed", VIR_XML_PROP_NONE,
8397                                &nvme->managed) < 0)
8398         return -1;
8399 
8400     if (!(address = virXPathNode("./address", ctxt))) {
8401         virReportError(VIR_ERR_XML_ERROR, "%s",
8402                        _("NVMe disk source is missing address"));
8403         return -1;
8404     }
8405 
8406     if (virPCIDeviceAddressParseXML(address, &nvme->pciAddr) < 0)
8407         return -1;
8408 
8409     src->nvme = g_steal_pointer(&nvme);
8410     return 0;
8411 }
8412 
8413 
8414 static int
virDomainDiskSourceVHostUserParse(xmlNodePtr node,virStorageSource * src,virDomainXMLOption * xmlopt,xmlXPathContextPtr ctxt)8415 virDomainDiskSourceVHostUserParse(xmlNodePtr node,
8416                                   virStorageSource *src,
8417                                   virDomainXMLOption *xmlopt,
8418                                   xmlXPathContextPtr ctxt)
8419 {
8420     g_autofree char *type = virXMLPropString(node, "type");
8421     g_autofree char *path = virXMLPropString(node, "path");
8422 
8423     if (!type) {
8424         virReportError(VIR_ERR_XML_ERROR, "%s",
8425                        _("missing 'type' attribute for vhostuser disk source"));
8426         return -1;
8427     }
8428 
8429     if (STRNEQ(type, "unix")) {
8430         virReportError(VIR_ERR_XML_ERROR, "%s",
8431                        _("invalid 'type' attribute for vhostuser disk source"));
8432         return -1;
8433     }
8434 
8435     if (!path) {
8436         virReportError(VIR_ERR_XML_ERROR, "%s",
8437                        _("missing 'path' attribute for vhostuser disk source"));
8438         return -1;
8439     }
8440 
8441     if (!(src->vhostuser = virDomainChrSourceDefNew(xmlopt)))
8442         return -1;
8443 
8444     src->vhostuser->type = virDomainChrTypeFromString(type);
8445     src->vhostuser->data.nix.path = g_steal_pointer(&path);
8446 
8447     if (virDomainChrSourceReconnectDefParseXML(&src->vhostuser->data.nix.reconnect,
8448                                                node,
8449                                                ctxt) < 0) {
8450         return -1;
8451     }
8452 
8453     return 0;
8454 }
8455 
8456 
8457 static int
virDomainDiskSourcePRParse(xmlNodePtr node,xmlXPathContextPtr ctxt,virStoragePRDef ** pr)8458 virDomainDiskSourcePRParse(xmlNodePtr node,
8459                            xmlXPathContextPtr ctxt,
8460                            virStoragePRDef **pr)
8461 {
8462     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8463 
8464     ctxt->node = node;
8465 
8466     if (!(ctxt->node = virXPathNode("./reservations", ctxt)))
8467         return 0;
8468 
8469     if (!(*pr = virStoragePRDefParseXML(ctxt)))
8470         return -1;
8471 
8472     return 0;
8473 }
8474 
8475 
8476 virStorageSource *
virDomainStorageSourceParseBase(const char * type,const char * format,const char * index)8477 virDomainStorageSourceParseBase(const char *type,
8478                                 const char *format,
8479                                 const char *index)
8480 {
8481     g_autoptr(virStorageSource) src = NULL;
8482 
8483     src = virStorageSourceNew();
8484     src->type = VIR_STORAGE_TYPE_FILE;
8485 
8486     if (type &&
8487         (src->type = virStorageTypeFromString(type)) <= 0) {
8488         virReportError(VIR_ERR_XML_ERROR,
8489                        _("unknown storage source type '%s'"), type);
8490         return NULL;
8491     }
8492 
8493     if (format &&
8494         (src->format = virStorageFileFormatTypeFromString(format)) <= 0) {
8495         virReportError(VIR_ERR_XML_ERROR,
8496                        _("unknown storage source format '%s'"), format);
8497         return NULL;
8498     }
8499 
8500     if (index &&
8501         virStrToLong_uip(index, NULL, 10, &src->id) < 0) {
8502         virReportError(VIR_ERR_XML_ERROR,
8503                        _("invalid storage source index '%s'"), index);
8504         return NULL;
8505     }
8506 
8507     return g_steal_pointer(&src);
8508 }
8509 
8510 
8511 static virStorageSourceSlice *
virDomainStorageSourceParseSlice(xmlNodePtr node,xmlXPathContextPtr ctxt)8512 virDomainStorageSourceParseSlice(xmlNodePtr node,
8513                                  xmlXPathContextPtr ctxt)
8514 {
8515     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8516     g_autofree char *offset = NULL;
8517     g_autofree char *size = NULL;
8518     g_autofree virStorageSourceSlice *ret = g_new0(virStorageSourceSlice, 1);
8519 
8520     ctxt->node = node;
8521 
8522     if (!(offset = virXPathString("string(./@offset)", ctxt)) ||
8523         !(size = virXPathString("string(./@size)", ctxt))) {
8524         virReportError(VIR_ERR_XML_ERROR, "%s",
8525                        _("missing offset or size attribute of slice"));
8526         return NULL;
8527     }
8528 
8529     if (virStrToLong_ullp(offset, NULL, 10, &ret->offset) < 0) {
8530         virReportError(VIR_ERR_XML_ERROR,
8531                        _("malformed value '%s' of 'offset' attribute of slice"),
8532                        offset);
8533         return NULL;
8534     }
8535 
8536     if (virStrToLong_ullp(size, NULL, 10, &ret->size) < 0) {
8537         virReportError(VIR_ERR_XML_ERROR,
8538                        _("malformed value '%s' of 'size' attribute of slice"),
8539                        size);
8540         return NULL;
8541     }
8542 
8543     return g_steal_pointer(&ret);
8544 }
8545 
8546 
8547 static int
virDomainStorageSourceParseSlices(virStorageSource * src,xmlXPathContextPtr ctxt)8548 virDomainStorageSourceParseSlices(virStorageSource *src,
8549                                   xmlXPathContextPtr ctxt)
8550 {
8551     xmlNodePtr node;
8552 
8553     if ((node = virXPathNode("./slices/slice[@type='storage']", ctxt))) {
8554         if (!(src->sliceStorage = virDomainStorageSourceParseSlice(node, ctxt)))
8555             return -1;
8556     }
8557 
8558     return 0;
8559 }
8560 
8561 
8562 /**
8563  * virDomainStorageSourceParse:
8564  * @node: XML node pointing to the source element to parse
8565  * @ctxt: XPath context
8566  * @src: filled with parsed data
8567  * @flags: XML parser flags
8568  * @xmlopt: XML parser callbacks
8569  *
8570  * Parses @src definition from element pointed to by @node. Note that this
8571  * does not parse the 'type' and 'format' attributes of @src and 'type' needs
8572  * to be set correctly prior to calling this function.
8573  */
8574 int
virDomainStorageSourceParse(xmlNodePtr node,xmlXPathContextPtr ctxt,virStorageSource * src,unsigned int flags,virDomainXMLOption * xmlopt)8575 virDomainStorageSourceParse(xmlNodePtr node,
8576                             xmlXPathContextPtr ctxt,
8577                             virStorageSource *src,
8578                             unsigned int flags,
8579                             virDomainXMLOption *xmlopt)
8580 {
8581     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8582     xmlNodePtr tmp;
8583 
8584     ctxt->node = node;
8585 
8586     switch ((virStorageType)src->type) {
8587     case VIR_STORAGE_TYPE_FILE:
8588         src->path = virXMLPropString(node, "file");
8589         break;
8590     case VIR_STORAGE_TYPE_BLOCK:
8591         src->path = virXMLPropString(node, "dev");
8592         break;
8593     case VIR_STORAGE_TYPE_DIR:
8594         src->path = virXMLPropString(node, "dir");
8595         break;
8596     case VIR_STORAGE_TYPE_NETWORK:
8597         if (virDomainDiskSourceNetworkParse(node, ctxt, src, flags) < 0)
8598             return -1;
8599         break;
8600     case VIR_STORAGE_TYPE_VOLUME:
8601         if (virDomainDiskSourcePoolDefParse(node, &src->srcpool) < 0)
8602             return -1;
8603         break;
8604     case VIR_STORAGE_TYPE_NVME:
8605         if (virDomainDiskSourceNVMeParse(node, ctxt, src) < 0)
8606             return -1;
8607         break;
8608     case VIR_STORAGE_TYPE_VHOST_USER:
8609         if (virDomainDiskSourceVHostUserParse(node, src, xmlopt, ctxt) < 0)
8610             return -1;
8611         break;
8612     case VIR_STORAGE_TYPE_NONE:
8613     case VIR_STORAGE_TYPE_LAST:
8614         virReportError(VIR_ERR_INTERNAL_ERROR,
8615                        _("unexpected disk type %s"),
8616                        virStorageTypeToString(src->type));
8617         return -1;
8618     }
8619 
8620     if ((tmp = virXPathNode("./auth", ctxt)) &&
8621         !(src->auth = virStorageAuthDefParse(tmp, ctxt)))
8622         return -1;
8623 
8624     if ((tmp = virXPathNode("./encryption", ctxt)) &&
8625         !(src->encryption = virStorageEncryptionParseNode(tmp, ctxt)))
8626         return -1;
8627 
8628     if (virDomainDiskSourcePRParse(node, ctxt, &src->pr) < 0)
8629         return -1;
8630 
8631     if (virDomainStorageSourceParseSlices(src, ctxt) < 0)
8632         return -1;
8633 
8634     if (virSecurityDeviceLabelDefParseXML(&src->seclabels, &src->nseclabels,
8635                                           ctxt, flags) < 0)
8636         return -1;
8637 
8638     /* People sometimes pass a bogus '' source path when they mean to omit the
8639      * source element completely (e.g. CDROM without media). This is just a
8640      * little compatibility check to help those broken apps */
8641     if (src->path && !*src->path)
8642         VIR_FREE(src->path);
8643 
8644     if ((flags & VIR_DOMAIN_DEF_PARSE_STATUS) &&
8645         xmlopt && xmlopt->privateData.storageParse &&
8646         (tmp = virXPathNode("./privateData", ctxt))) {
8647         ctxt->node = tmp;
8648 
8649         if (xmlopt->privateData.storageParse(ctxt, src) < 0)
8650             return -1;
8651     }
8652 
8653     return 0;
8654 }
8655 
8656 
8657 int
virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,virStorageSource * src,unsigned int flags,virDomainXMLOption * xmlopt)8658 virDomainDiskBackingStoreParse(xmlXPathContextPtr ctxt,
8659                                virStorageSource *src,
8660                                unsigned int flags,
8661                                virDomainXMLOption *xmlopt)
8662 {
8663     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8664     xmlNodePtr source;
8665     g_autoptr(virStorageSource) backingStore = NULL;
8666     g_autofree char *type = NULL;
8667     g_autofree char *format = NULL;
8668     g_autofree char *idx = NULL;
8669 
8670     if (!(ctxt->node = virXPathNode("./backingStore", ctxt)))
8671         return 0;
8672 
8673     /* terminator does not have a type */
8674     if (!(type = virXMLPropString(ctxt->node, "type"))) {
8675         src->backingStore = virStorageSourceNew();
8676         return 0;
8677     }
8678 
8679     if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
8680         idx = virXMLPropString(ctxt->node, "index");
8681 
8682     if (!(format = virXPathString("string(./format/@type)", ctxt))) {
8683         virReportError(VIR_ERR_XML_ERROR, "%s",
8684                        _("missing disk backing store format"));
8685         return -1;
8686     }
8687 
8688     if (!(source = virXPathNode("./source", ctxt))) {
8689         virReportError(VIR_ERR_XML_ERROR, "%s",
8690                        _("missing disk backing store source"));
8691         return -1;
8692     }
8693 
8694     if (!(backingStore = virDomainStorageSourceParseBase(type, format, idx)))
8695         return -1;
8696 
8697     if (virParseScaledValue("./format/metadata_cache/max_size", NULL,
8698                             ctxt,
8699                             &backingStore->metadataCacheMaxSize,
8700                             1, ULLONG_MAX, false) < 0)
8701         return -1;
8702 
8703     /* backing store is always read-only */
8704     backingStore->readonly = true;
8705 
8706     if (virDomainStorageSourceParse(source, ctxt, backingStore, flags, xmlopt) < 0 ||
8707         virDomainDiskBackingStoreParse(ctxt, backingStore, flags, xmlopt) < 0)
8708         return -1;
8709 
8710     src->backingStore = g_steal_pointer(&backingStore);
8711 
8712     return 0;
8713 }
8714 
8715 #define PARSE_IOTUNE(val) \
8716     if (virXPathULongLong("string(./iotune/" #val ")", \
8717                           ctxt, &def->blkdeviotune.val) == -2) { \
8718         virReportError(VIR_ERR_XML_ERROR, \
8719                        _("disk iotune field '%s' must be an integer"), #val); \
8720         return -1; \
8721     }
8722 
8723 static int
virDomainDiskDefIotuneParse(virDomainDiskDef * def,xmlXPathContextPtr ctxt)8724 virDomainDiskDefIotuneParse(virDomainDiskDef *def,
8725                             xmlXPathContextPtr ctxt)
8726 {
8727     PARSE_IOTUNE(total_bytes_sec);
8728     PARSE_IOTUNE(read_bytes_sec);
8729     PARSE_IOTUNE(write_bytes_sec);
8730     PARSE_IOTUNE(total_iops_sec);
8731     PARSE_IOTUNE(read_iops_sec);
8732     PARSE_IOTUNE(write_iops_sec);
8733 
8734     PARSE_IOTUNE(total_bytes_sec_max);
8735     PARSE_IOTUNE(read_bytes_sec_max);
8736     PARSE_IOTUNE(write_bytes_sec_max);
8737     PARSE_IOTUNE(total_iops_sec_max);
8738     PARSE_IOTUNE(read_iops_sec_max);
8739     PARSE_IOTUNE(write_iops_sec_max);
8740 
8741     PARSE_IOTUNE(size_iops_sec);
8742 
8743     PARSE_IOTUNE(total_bytes_sec_max_length);
8744     PARSE_IOTUNE(read_bytes_sec_max_length);
8745     PARSE_IOTUNE(write_bytes_sec_max_length);
8746     PARSE_IOTUNE(total_iops_sec_max_length);
8747     PARSE_IOTUNE(read_iops_sec_max_length);
8748     PARSE_IOTUNE(write_iops_sec_max_length);
8749 
8750     def->blkdeviotune.group_name =
8751         virXPathString("string(./iotune/group_name)", ctxt);
8752 
8753     if ((def->blkdeviotune.total_bytes_sec &&
8754          def->blkdeviotune.read_bytes_sec) ||
8755         (def->blkdeviotune.total_bytes_sec &&
8756          def->blkdeviotune.write_bytes_sec)) {
8757         virReportError(VIR_ERR_XML_ERROR, "%s",
8758                        _("total and read/write bytes_sec "
8759                          "cannot be set at the same time"));
8760         return -1;
8761     }
8762 
8763     if ((def->blkdeviotune.total_iops_sec &&
8764          def->blkdeviotune.read_iops_sec) ||
8765         (def->blkdeviotune.total_iops_sec &&
8766          def->blkdeviotune.write_iops_sec)) {
8767         virReportError(VIR_ERR_XML_ERROR, "%s",
8768                        _("total and read/write iops_sec "
8769                          "cannot be set at the same time"));
8770         return -1;
8771     }
8772 
8773     if ((def->blkdeviotune.total_bytes_sec_max &&
8774          def->blkdeviotune.read_bytes_sec_max) ||
8775         (def->blkdeviotune.total_bytes_sec_max &&
8776          def->blkdeviotune.write_bytes_sec_max)) {
8777         virReportError(VIR_ERR_XML_ERROR, "%s",
8778                        _("total and read/write bytes_sec_max "
8779                          "cannot be set at the same time"));
8780         return -1;
8781     }
8782 
8783     if ((def->blkdeviotune.total_iops_sec_max &&
8784          def->blkdeviotune.read_iops_sec_max) ||
8785         (def->blkdeviotune.total_iops_sec_max &&
8786          def->blkdeviotune.write_iops_sec_max)) {
8787         virReportError(VIR_ERR_XML_ERROR, "%s",
8788                        _("total and read/write iops_sec_max "
8789                          "cannot be set at the same time"));
8790         return -1;
8791     }
8792 
8793     return 0;
8794 }
8795 #undef PARSE_IOTUNE
8796 
8797 
8798 static int
virDomainDiskDefMirrorParse(virDomainDiskDef * def,xmlNodePtr cur,xmlXPathContextPtr ctxt,unsigned int flags,virDomainXMLOption * xmlopt)8799 virDomainDiskDefMirrorParse(virDomainDiskDef *def,
8800                             xmlNodePtr cur,
8801                             xmlXPathContextPtr ctxt,
8802                             unsigned int flags,
8803                             virDomainXMLOption *xmlopt)
8804 {
8805     xmlNodePtr mirrorNode;
8806     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8807     g_autofree char *mirrorFormat = NULL;
8808     g_autofree char *mirrorType = NULL;
8809     g_autofree char *ready = NULL;
8810     g_autofree char *blockJob = NULL;
8811     g_autofree char *index = NULL;
8812 
8813     ctxt->node = cur;
8814 
8815     if ((blockJob = virXMLPropString(cur, "job"))) {
8816         if ((def->mirrorJob = virDomainBlockJobTypeFromString(blockJob)) <= 0) {
8817             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
8818                            _("unknown mirror job type '%s'"), blockJob);
8819             return -1;
8820         }
8821     } else {
8822         def->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
8823     }
8824 
8825     if ((mirrorType = virXMLPropString(cur, "type"))) {
8826         mirrorFormat = virXPathString("string(./format/@type)", ctxt);
8827         index = virXPathString("string(./source/@index)", ctxt);
8828     } else {
8829         if (def->mirrorJob != VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
8830             virReportError(VIR_ERR_XML_ERROR, "%s",
8831                            _("mirror without type only supported "
8832                              "by copy job"));
8833             return -1;
8834         }
8835         mirrorFormat = virXMLPropString(cur, "format");
8836     }
8837 
8838     if (!(def->mirror = virDomainStorageSourceParseBase(mirrorType, mirrorFormat,
8839                                                         index)))
8840         return -1;
8841 
8842     if (mirrorType) {
8843         if (!(mirrorNode = virXPathNode("./source", ctxt))) {
8844             virReportError(VIR_ERR_XML_ERROR, "%s",
8845                            _("mirror requires source element"));
8846             return -1;
8847         }
8848 
8849         if (virDomainStorageSourceParse(mirrorNode, ctxt, def->mirror, flags,
8850                                         xmlopt) < 0)
8851             return -1;
8852         if (virDomainDiskBackingStoreParse(ctxt, def->mirror, flags, xmlopt) < 0)
8853             return -1;
8854     } else {
8855         /* For back-compat reasons, we handle a file name encoded as
8856          * attributes, even though we prefer modern output in the style of
8857          * backingStore */
8858         if (!(def->mirror->path = virXMLPropString(cur, "file"))) {
8859             virReportError(VIR_ERR_XML_ERROR, "%s",
8860                            _("mirror requires file name"));
8861             return -1;
8862         }
8863     }
8864 
8865     if ((ready = virXMLPropString(cur, "ready")) &&
8866         (def->mirrorState = virDomainDiskMirrorStateTypeFromString(ready)) < 0) {
8867         virReportError(VIR_ERR_XML_ERROR,
8868                        _("unknown mirror ready state %s"), ready);
8869         return -1;
8870     }
8871 
8872     if (virParseScaledValue("./format/metadata_cache/max_size", NULL,
8873                             ctxt,
8874                             &def->mirror->metadataCacheMaxSize,
8875                             1, ULLONG_MAX, false) < 0)
8876         return -1;
8877 
8878     return 0;
8879 }
8880 
8881 
8882 static int
virDomainDiskDefGeometryParse(virDomainDiskDef * def,xmlNodePtr cur)8883 virDomainDiskDefGeometryParse(virDomainDiskDef *def,
8884                               xmlNodePtr cur)
8885 {
8886     if (virXMLPropUInt(cur, "cyls", 10, VIR_XML_PROP_NONE,
8887                        &def->geometry.cylinders) < 0)
8888         return -1;
8889 
8890     if (virXMLPropUInt(cur, "heads", 10, VIR_XML_PROP_NONE,
8891                        &def->geometry.heads) < 0)
8892         return -1;
8893 
8894     if (virXMLPropUInt(cur, "secs", 10, VIR_XML_PROP_NONE,
8895                        &def->geometry.sectors) < 0)
8896         return -1;
8897 
8898     if (virXMLPropEnum(cur, "trans", virDomainDiskGeometryTransTypeFromString,
8899                        VIR_XML_PROP_NONZERO, &def->geometry.trans) < 0)
8900         return -1;
8901 
8902     return 0;
8903 }
8904 
8905 
8906 static int
virDomainDiskDefDriverParseXML(virDomainDiskDef * def,xmlNodePtr cur,xmlXPathContextPtr ctxt)8907 virDomainDiskDefDriverParseXML(virDomainDiskDef *def,
8908                                xmlNodePtr cur,
8909                                xmlXPathContextPtr ctxt)
8910 {
8911     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8912 
8913     ctxt->node = cur;
8914 
8915     def->driverName = virXMLPropString(cur, "name");
8916 
8917     if (virXMLPropEnum(cur, "cache", virDomainDiskCacheTypeFromString,
8918                        VIR_XML_PROP_NONE, &def->cachemode) < 0)
8919         return -1;
8920 
8921     if (virXMLPropEnum(cur, "error_policy",
8922                        virDomainDiskErrorPolicyTypeFromString,
8923                        VIR_XML_PROP_NONZERO, &def->error_policy) < 0)
8924         return -1;
8925 
8926     if (virXMLPropEnum(cur, "rerror_policy",
8927                        virDomainDiskErrorPolicyTypeFromString,
8928                        VIR_XML_PROP_NONZERO, &def->rerror_policy) < 0)
8929         return -1;
8930 
8931     if (def->rerror_policy == VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE) {
8932         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
8933                        _("Invalid disk read error policy: '%s'"),
8934                        virDomainDiskErrorPolicyTypeToString(def->rerror_policy));
8935         return -1;
8936     }
8937 
8938     if (virXMLPropEnum(cur, "io", virDomainDiskIoTypeFromString,
8939                        VIR_XML_PROP_NONZERO, &def->iomode) < 0)
8940         return -1;
8941 
8942     if (virXMLPropTristateSwitch(cur, "ioeventfd", VIR_XML_PROP_NONE,
8943                                  &def->ioeventfd) < 0)
8944         return -1;
8945 
8946     if (virXMLPropTristateSwitch(cur, "event_idx", VIR_XML_PROP_NONE,
8947                                  &def->event_idx) < 0)
8948         return -1;
8949 
8950     if (virXMLPropTristateSwitch(cur, "copy_on_read", VIR_XML_PROP_NONE,
8951                                  &def->copy_on_read) < 0)
8952         return -1;
8953 
8954     if (virXMLPropEnum(cur, "discard", virDomainDiskDiscardTypeFromString,
8955                        VIR_XML_PROP_NONZERO, &def->discard) < 0)
8956         return -1;
8957 
8958     if (virXMLPropUInt(cur, "iothread", 10, VIR_XML_PROP_NONZERO, &def->iothread) < 0)
8959         return -1;
8960 
8961     if (virXMLPropEnum(cur, "detect_zeroes",
8962                        virDomainDiskDetectZeroesTypeFromString,
8963                        VIR_XML_PROP_NONZERO, &def->detect_zeroes) < 0)
8964         return -1;
8965 
8966     if (virXMLPropUInt(cur, "queues", 10, VIR_XML_PROP_NONE, &def->queues) < 0)
8967         return -1;
8968 
8969     if (virXMLPropUInt(cur, "queue_size", 10, VIR_XML_PROP_NONE, &def->queue_size) < 0)
8970         return -1;
8971 
8972     return 0;
8973 }
8974 
8975 
8976 static int
virDomainDiskDefDriverSourceParseXML(virStorageSource * src,xmlNodePtr cur,xmlXPathContextPtr ctxt)8977 virDomainDiskDefDriverSourceParseXML(virStorageSource *src,
8978                                      xmlNodePtr cur,
8979                                      xmlXPathContextPtr ctxt)
8980 {
8981     g_autofree char *tmp = NULL;
8982     VIR_XPATH_NODE_AUTORESTORE(ctxt)
8983 
8984     ctxt->node = cur;
8985 
8986     if ((tmp = virXMLPropString(cur, "type"))) {
8987         if (STREQ(tmp, "aio")) {
8988             /* Xen back-compat */
8989             src->format = VIR_STORAGE_FILE_RAW;
8990         } else {
8991             if ((src->format = virStorageFileFormatTypeFromString(tmp)) <= 0) {
8992                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
8993                                _("unknown driver format value '%s'"), tmp);
8994                 return -1;
8995             }
8996         }
8997     }
8998 
8999     if (virParseScaledValue("./metadata_cache/max_size", NULL,
9000                             ctxt,
9001                             &src->metadataCacheMaxSize,
9002                             1, ULLONG_MAX, false) < 0)
9003         return -1;
9004 
9005     return 0;
9006 }
9007 
9008 
9009 static int
virDomainDiskDefParsePrivateData(xmlXPathContextPtr ctxt,virDomainDiskDef * disk,virDomainXMLOption * xmlopt)9010 virDomainDiskDefParsePrivateData(xmlXPathContextPtr ctxt,
9011                                  virDomainDiskDef *disk,
9012                                  virDomainXMLOption *xmlopt)
9013 {
9014     xmlNodePtr private_node = virXPathNode("./privateData", ctxt);
9015     VIR_XPATH_NODE_AUTORESTORE(ctxt)
9016 
9017     if (!xmlopt ||
9018         !xmlopt->privateData.diskParse ||
9019         !private_node)
9020         return 0;
9021 
9022     ctxt->node = private_node;
9023 
9024     if (xmlopt->privateData.diskParse(ctxt, disk) < 0)
9025         return -1;
9026 
9027     return 0;
9028 }
9029 
9030 
9031 static virStorageSource *
virDomainDiskDefParseSourceXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)9032 virDomainDiskDefParseSourceXML(virDomainXMLOption *xmlopt,
9033                                xmlNodePtr node,
9034                                xmlXPathContextPtr ctxt,
9035                                unsigned int flags)
9036 {
9037     g_autoptr(virStorageSource) src = virStorageSourceNew();
9038     VIR_XPATH_NODE_AUTORESTORE(ctxt)
9039     g_autofree char *type = NULL;
9040     xmlNodePtr tmp;
9041 
9042     ctxt->node = node;
9043 
9044     src->type = VIR_STORAGE_TYPE_FILE;
9045 
9046     if ((type = virXMLPropString(node, "type")) &&
9047         (src->type = virStorageTypeFromString(type)) <= 0) {
9048         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9049                        _("unknown disk type '%s'"), type);
9050         return NULL;
9051     }
9052 
9053     if ((tmp = virXPathNode("./source[1]", ctxt))) {
9054         if (virDomainStorageSourceParse(tmp, ctxt, src, flags, xmlopt) < 0)
9055             return NULL;
9056 
9057         if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
9058             g_autofree char *sourceindex = NULL;
9059 
9060             if ((sourceindex = virXMLPropString(tmp, "index")) &&
9061                 virStrToLong_uip(sourceindex, NULL, 10, &src->id) < 0) {
9062                 virReportError(VIR_ERR_XML_ERROR,
9063                                _("invalid disk index '%s'"), sourceindex);
9064                 return NULL;
9065             }
9066         }
9067     } else {
9068         /* Reset src->type in case when 'source' was not present */
9069         src->type = VIR_STORAGE_TYPE_FILE;
9070     }
9071 
9072     if (virXPathNode("./readonly[1]", ctxt))
9073         src->readonly = true;
9074 
9075     if (virXPathNode("./shareable[1]", ctxt))
9076         src->shared = true;
9077 
9078     if ((tmp = virXPathNode("./auth", ctxt))) {
9079         /* If we've already parsed <source> and found an <auth> child,
9080          * then generate an error to avoid ambiguity */
9081         if (src->auth) {
9082             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9083                            _("an <auth> definition already found for disk source"));
9084             return NULL;
9085         }
9086 
9087         if (!(src->auth = virStorageAuthDefParse(tmp, ctxt)))
9088             return NULL;
9089     }
9090 
9091     if ((tmp = virXPathNode("./encryption", ctxt))) {
9092         /* If we've already parsed <source> and found an <encryption> child,
9093          * then generate an error to avoid ambiguity */
9094         if (src->encryption) {
9095             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
9096                            _("an <encryption> definition already found for disk source"));
9097             return NULL;
9098         }
9099 
9100         if (!(src->encryption = virStorageEncryptionParseNode(tmp, ctxt)))
9101             return NULL;
9102     }
9103 
9104     if (virDomainDiskBackingStoreParse(ctxt, src, flags, xmlopt) < 0)
9105         return NULL;
9106 
9107     return g_steal_pointer(&src);
9108 }
9109 
9110 
9111 static virDomainDiskDef *
virDomainDiskDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)9112 virDomainDiskDefParseXML(virDomainXMLOption *xmlopt,
9113                          xmlNodePtr node,
9114                          xmlXPathContextPtr ctxt,
9115                          unsigned int flags)
9116 {
9117     g_autoptr(virDomainDiskDef) def = NULL;
9118     VIR_XPATH_NODE_AUTORESTORE(ctxt)
9119     xmlNodePtr sourceNode;
9120     xmlNodePtr targetNode;
9121     xmlNodePtr geometryNode;
9122     xmlNodePtr blockioNode;
9123     xmlNodePtr driverNode;
9124     xmlNodePtr mirrorNode;
9125     xmlNodePtr transientNode;
9126     g_autoptr(virStorageSource) src = NULL;
9127 
9128     if (!(src = virDomainDiskDefParseSourceXML(xmlopt, node, ctxt, flags)))
9129         return NULL;
9130 
9131     if (!(def = virDomainDiskDefNewSource(xmlopt, &src)))
9132         return NULL;
9133 
9134     ctxt->node = node;
9135 
9136     if (virXMLPropEnumDefault(node, "device", virDomainDiskDeviceTypeFromString,
9137                               VIR_XML_PROP_NONE, &def->device,
9138                               VIR_DOMAIN_DISK_DEVICE_DISK) < 0)
9139         return NULL;
9140 
9141     if (virXMLPropEnum(node, "model", virDomainDiskModelTypeFromString,
9142                        VIR_XML_PROP_NONE, &def->model) < 0)
9143         return NULL;
9144 
9145     if (virXMLPropEnum(node, "snapshot", virDomainSnapshotLocationTypeFromString,
9146                        VIR_XML_PROP_NONZERO, &def->snapshot) < 0)
9147         return NULL;
9148 
9149     if (virXMLPropTristateBool(node, "rawio", VIR_XML_PROP_NONE, &def->rawio) < 0)
9150         return NULL;
9151 
9152     if (virXMLPropEnum(node, "sgio", virDomainDeviceSGIOTypeFromString,
9153                        VIR_XML_PROP_NONZERO, &def->sgio) < 0)
9154         return NULL;
9155 
9156     if ((sourceNode = virXPathNode("./source", ctxt))) {
9157         if (virXMLPropEnum(sourceNode, "startupPolicy",
9158                            virDomainStartupPolicyTypeFromString,
9159                            VIR_XML_PROP_NONZERO,
9160                            &def->startupPolicy) < 0)
9161             return NULL;
9162     }
9163 
9164     if ((targetNode = virXPathNode("./target", ctxt))) {
9165         def->dst = virXMLPropString(targetNode, "dev");
9166 
9167         if (virXMLPropEnum(targetNode, "bus",
9168                            virDomainDiskBusTypeFromString,
9169                            VIR_XML_PROP_NONZERO,
9170                            &def->bus) < 0)
9171             return NULL;
9172 
9173         if (virXMLPropEnum(targetNode, "tray", virDomainDiskTrayTypeFromString,
9174                            VIR_XML_PROP_NONE, &def->tray_status) < 0)
9175             return NULL;
9176 
9177         if (virXMLPropTristateSwitch(targetNode, "removable", VIR_XML_PROP_NONE,
9178                                      &def->removable) < 0)
9179             return NULL;
9180 
9181         if (virXMLPropUInt(targetNode, "rotation_rate", 10, VIR_XML_PROP_NONE,
9182                            &def->rotation_rate) < 0)
9183             return NULL;
9184     }
9185 
9186     if ((geometryNode = virXPathNode("./geometry", ctxt))) {
9187         if (virDomainDiskDefGeometryParse(def, geometryNode) < 0)
9188             return NULL;
9189     }
9190 
9191     if ((blockioNode = virXPathNode("./blockio", ctxt))) {
9192         if (virXMLPropUInt(blockioNode, "logical_block_size", 10, VIR_XML_PROP_NONE,
9193                            &def->blockio.logical_block_size) < 0)
9194             return NULL;
9195 
9196         if (virXMLPropUInt(blockioNode, "physical_block_size", 10, VIR_XML_PROP_NONE,
9197                            &def->blockio.physical_block_size) < 0)
9198             return NULL;
9199     }
9200 
9201     if ((driverNode = virXPathNode("./driver", ctxt))) {
9202         if (virDomainVirtioOptionsParseXML(driverNode, &def->virtio) < 0)
9203             return NULL;
9204 
9205         if (virDomainDiskDefDriverParseXML(def, driverNode, ctxt) < 0)
9206             return NULL;
9207 
9208         if (virDomainDiskDefDriverSourceParseXML(def->src, driverNode, ctxt) < 0)
9209             return NULL;
9210     }
9211 
9212     if ((mirrorNode = virXPathNode("./mirror", ctxt))) {
9213         if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
9214             if (virDomainDiskDefMirrorParse(def, mirrorNode, ctxt, flags, xmlopt) < 0)
9215                 return NULL;
9216         }
9217     }
9218 
9219     if (virXPathNode("./auth", ctxt))
9220         def->diskElementAuth = true;
9221 
9222     if (virXPathNode("./encryption", ctxt))
9223         def->diskElementEnc = true;
9224 
9225     if (flags & VIR_DOMAIN_DEF_PARSE_STATUS) {
9226         xmlNodePtr diskSecretsPlacementNode;
9227 
9228         if ((diskSecretsPlacementNode = virXPathNode("./diskSecretsPlacement", ctxt))) {
9229             g_autofree char *secretAuth = virXMLPropString(diskSecretsPlacementNode, "auth");
9230             g_autofree char *secretEnc = virXMLPropString(diskSecretsPlacementNode, "enc");
9231 
9232             def->diskElementAuth = !!secretAuth;
9233             def->diskElementEnc = !!secretEnc;
9234         }
9235     }
9236 
9237     if ((transientNode = virXPathNode("./transient", ctxt))) {
9238         def->transient = true;
9239 
9240         if (virXMLPropTristateBool(transientNode, "shareBacking",
9241                                    VIR_XML_PROP_NONE,
9242                                    &def->transientShareBacking) < 0)
9243             return NULL;
9244     }
9245 
9246     if (virDomainDiskDefIotuneParse(def, ctxt) < 0)
9247         return NULL;
9248 
9249     def->domain_name = virXPathString("string(./backenddomain/@name)", ctxt);
9250     def->serial = virXPathString("string(./serial)", ctxt);
9251     def->wwn = virXPathString("string(./wwn)", ctxt);
9252     def->vendor = virXPathString("string(./vendor)", ctxt);
9253     def->product = virXPathString("string(./product)", ctxt);
9254 
9255     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info,
9256                                     flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT) < 0) {
9257         return NULL;
9258     }
9259 
9260     if (flags & VIR_DOMAIN_DEF_PARSE_STATUS &&
9261         virDomainDiskDefParsePrivateData(ctxt, def, xmlopt) < 0)
9262         return NULL;
9263 
9264     return g_steal_pointer(&def);
9265 }
9266 
9267 
9268 /**
9269  * virDomainParseMemory:
9270  * @xpath: XPath to memory amount
9271  * @units_xpath: XPath to units attribute
9272  * @ctxt: XPath context
9273  * @mem: scaled memory amount is stored here
9274  * @required: whether value is required
9275  * @capped: whether scaled value must fit within unsigned long
9276  *
9277  * Parse a memory element or attribute located at @xpath within
9278  * @ctxt, and store the result into @mem, in blocks of 1024. The
9279  * value is scaled by units located at @units_xpath (or the
9280  * 'unit' attribute under @xpath if @units_xpath is NULL). If
9281  * units are not present, he default scale of 1024 is used. If
9282  * @required is set, then the value must exist; otherwise, the
9283  * value is optional.  The value must not exceed
9284  * VIR_DOMAIN_MEMORY_PARAM_UNLIMITED once scaled; additionally,
9285  * if @capped is true, the value must fit within an unsigned long
9286  * (only matters on 32-bit platforms).
9287  *
9288  * Return 0 on success, -1 on failure after issuing error.
9289  */
9290 int
virDomainParseMemory(const char * xpath,const char * units_xpath,xmlXPathContextPtr ctxt,unsigned long long * mem,bool required,bool capped)9291 virDomainParseMemory(const char *xpath,
9292                      const char *units_xpath,
9293                      xmlXPathContextPtr ctxt,
9294                      unsigned long long *mem,
9295                      bool required,
9296                      bool capped)
9297 {
9298     unsigned long long bytes, max;
9299 
9300     max = virMemoryMaxValue(capped);
9301 
9302     if (virParseScaledValue(xpath, units_xpath, ctxt,
9303                             &bytes, 1024, max, required) < 0)
9304         return -1;
9305 
9306     /* Yes, we really do use kibibytes for our internal sizing.  */
9307     *mem = VIR_DIV_UP(bytes, 1024);
9308 
9309     if (*mem >= VIR_DIV_UP(max, 1024)) {
9310         virReportError(VIR_ERR_OVERFLOW, "%s", _("size value too large"));
9311         return -1;
9312     }
9313     return 0;
9314 }
9315 
9316 
9317 /**
9318  * virDomainParseMemoryLimit:
9319  *
9320  * @xpath: XPath to memory amount
9321  * @units_xpath: XPath to units attribute
9322  * @ctxt: XPath context
9323  * @mem: scaled memory amount is stored here
9324  *
9325  * Parse a memory element or attribute located at @xpath within @ctxt, and
9326  * store the result into @mem, in blocks of 1024.  The  value is scaled by
9327  * units located at @units_xpath (or the 'unit' attribute under @xpath if
9328  * @units_xpath is NULL).  If units are not present, he default scale of 1024
9329  * is used.  The value must not exceed VIR_DOMAIN_MEMORY_PARAM_UNLIMITED
9330  * once scaled.
9331  *
9332  * This helper should be used only on *_limit memory elements.
9333  *
9334  * Return 0 on success, -1 on failure after issuing error.
9335  */
9336 static int
virDomainParseMemoryLimit(const char * xpath,const char * units_xpath,xmlXPathContextPtr ctxt,unsigned long long * mem)9337 virDomainParseMemoryLimit(const char *xpath,
9338                           const char *units_xpath,
9339                           xmlXPathContextPtr ctxt,
9340                           unsigned long long *mem)
9341 {
9342     int ret;
9343     unsigned long long bytes;
9344 
9345     ret = virParseScaledValue(xpath, units_xpath, ctxt, &bytes, 1024,
9346                               VIR_DOMAIN_MEMORY_PARAM_UNLIMITED << 10,
9347                               false);
9348 
9349     if (ret < 0)
9350         return -1;
9351 
9352     if (ret == 0)
9353         *mem = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
9354     else
9355         *mem = virMemoryLimitTruncate(VIR_DIV_UP(bytes, 1024));
9356 
9357     return 0;
9358 }
9359 
9360 
9361 bool
virDomainDefHasMemoryHotplug(const virDomainDef * def)9362 virDomainDefHasMemoryHotplug(const virDomainDef *def)
9363 {
9364     return def->mem.memory_slots > 0 || def->mem.max_memory > 0;
9365 }
9366 
9367 
9368 /**
9369  * virDomainDefGetMemoryInitial:
9370  * @def: domain definition
9371  *
9372  * Returns the size of the initial amount of guest memory. The initial amount
9373  * is the memory size excluding possible memory modules.
9374  */
9375 unsigned long long
virDomainDefGetMemoryInitial(const virDomainDef * def)9376 virDomainDefGetMemoryInitial(const virDomainDef *def)
9377 {
9378     size_t i;
9379     unsigned long long ret = def->mem.total_memory;
9380 
9381     for (i = 0; i < def->nmems; i++)
9382         ret -= def->mems[i]->size;
9383 
9384     return ret;
9385 }
9386 
9387 
9388 /**
9389  * virDomainDefSetMemoryTotal:
9390  * @def: domain definition
9391  * @size: size to set
9392  *
9393  * Sets the total memory size in @def. This value needs to include possible
9394  * additional memory modules.
9395  */
9396 void
virDomainDefSetMemoryTotal(virDomainDef * def,unsigned long long size)9397 virDomainDefSetMemoryTotal(virDomainDef *def,
9398                            unsigned long long size)
9399 {
9400     def->mem.total_memory = size;
9401 }
9402 
9403 
9404 /**
9405  * virDomainDefGetMemoryTotal:
9406  * @def: domain definition
9407  *
9408  * Returns the current maximum memory size usable by the domain described by
9409  * @def. This size includes possible additional memory devices.
9410  */
9411 unsigned long long
virDomainDefGetMemoryTotal(const virDomainDef * def)9412 virDomainDefGetMemoryTotal(const virDomainDef *def)
9413 {
9414     return def->mem.total_memory;
9415 }
9416 
9417 
9418 static int
virDomainControllerModelTypeFromString(const virDomainControllerDef * def,const char * model)9419 virDomainControllerModelTypeFromString(const virDomainControllerDef *def,
9420                                        const char *model)
9421 {
9422     if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
9423         return virDomainControllerModelSCSITypeFromString(model);
9424     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_USB)
9425         return virDomainControllerModelUSBTypeFromString(model);
9426     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
9427         return virDomainControllerModelPCITypeFromString(model);
9428     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE)
9429         return virDomainControllerModelIDETypeFromString(model);
9430     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL)
9431         return virDomainControllerModelVirtioSerialTypeFromString(model);
9432     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_ISA)
9433         return virDomainControllerModelISATypeFromString(model);
9434 
9435     return -1;
9436 }
9437 
9438 
9439 static const char *
virDomainControllerModelTypeToString(virDomainControllerDef * def,int model)9440 virDomainControllerModelTypeToString(virDomainControllerDef *def,
9441                                      int model)
9442 {
9443     if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
9444         return virDomainControllerModelSCSITypeToString(model);
9445     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_USB)
9446         return virDomainControllerModelUSBTypeToString(model);
9447     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI)
9448         return virDomainControllerModelPCITypeToString(model);
9449     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_IDE)
9450         return virDomainControllerModelIDETypeToString(model);
9451     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL)
9452         return virDomainControllerModelVirtioSerialTypeToString(model);
9453     else if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_ISA)
9454         return virDomainControllerModelISATypeToString(model);
9455 
9456     return NULL;
9457 }
9458 
9459 
9460 static virDomainControllerDef *
virDomainControllerDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)9461 virDomainControllerDefParseXML(virDomainXMLOption *xmlopt,
9462                                xmlNodePtr node,
9463                                xmlXPathContextPtr ctxt,
9464                                unsigned int flags)
9465 {
9466     g_autoptr(virDomainControllerDef) def = NULL;
9467     virDomainControllerType type = 0;
9468     xmlNodePtr driver = NULL;
9469     g_autofree xmlNodePtr *targetNodes = NULL;
9470     int ntargetNodes = 0;
9471     g_autofree xmlNodePtr *modelNodes = NULL;
9472     int nmodelNodes = 0;
9473     int numaNode = -1;
9474     int ports;
9475     VIR_XPATH_NODE_AUTORESTORE(ctxt)
9476     int rc;
9477     g_autofree char *idx = NULL;
9478     g_autofree char *model = NULL;
9479 
9480     ctxt->node = node;
9481 
9482     if (virXMLPropEnum(node, "type", virDomainControllerTypeFromString,
9483                        VIR_XML_PROP_NONE, &type) < 0)
9484         return NULL;
9485 
9486     if (!(def = virDomainControllerDefNew(type)))
9487         return NULL;
9488 
9489     if ((model = virXMLPropString(node, "model"))) {
9490         if ((def->model = virDomainControllerModelTypeFromString(def, model)) < 0) {
9491             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9492                            _("Unknown model type '%s'"), model);
9493             return NULL;
9494         }
9495     }
9496 
9497     idx = virXMLPropString(node, "index");
9498     if (idx) {
9499         unsigned int idxVal;
9500         if (virStrToLong_ui(idx, NULL, 10, &idxVal) < 0 || idxVal > INT_MAX) {
9501             virReportError(VIR_ERR_INTERNAL_ERROR,
9502                            _("Cannot parse controller index %s"), idx);
9503             return NULL;
9504         }
9505         def->idx = idxVal;
9506     }
9507 
9508     if ((driver = virXPathNode("./driver", ctxt))) {
9509         if (virXMLPropUInt(driver, "queues", 10, VIR_XML_PROP_NONE,
9510                            &def->queues) < 0)
9511             return NULL;
9512 
9513         if (virXMLPropUInt(driver, "cmd_per_lun", 10, VIR_XML_PROP_NONE,
9514                            &def->cmd_per_lun) < 0)
9515             return NULL;
9516 
9517         if (virXMLPropUInt(driver, "max_sectors", 10, VIR_XML_PROP_NONE,
9518                            &def->max_sectors) < 0)
9519             return NULL;
9520 
9521         if (virXMLPropTristateSwitch(driver, "ioeventfd",
9522                                      VIR_XML_PROP_NONE,
9523                                      &def->ioeventfd) < 0)
9524             return NULL;
9525 
9526         if (virXMLPropUInt(driver, "iothread", 10, VIR_XML_PROP_NONE,
9527                            &def->iothread) < 0)
9528             return NULL;
9529 
9530         if (virDomainVirtioOptionsParseXML(driver, &def->virtio) < 0)
9531             return NULL;
9532     }
9533 
9534     nmodelNodes = virXPathNodeSet("./model", ctxt, &modelNodes);
9535     if (nmodelNodes == 1) {
9536         if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
9537             if (virXMLPropEnum(modelNodes[0], "name",
9538                                virDomainControllerPCIModelNameTypeFromString,
9539                                VIR_XML_PROP_NONE,
9540                                &def->opts.pciopts.modelName) < 0)
9541                 return NULL;
9542         }
9543     } else if (nmodelNodes > 1) {
9544         virReportError(VIR_ERR_XML_ERROR, "%s",
9545                        _("Multiple <model> elements in "
9546                          "controller definition not allowed"));
9547         return NULL;
9548     }
9549 
9550     ntargetNodes = virXPathNodeSet("./target", ctxt, &targetNodes);
9551     if (ntargetNodes == 1) {
9552         if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
9553         if (virXMLPropInt(targetNodes[0], "chassisNr", 0, VIR_XML_PROP_NONE,
9554                       &def->opts.pciopts.chassisNr,
9555                       def->opts.pciopts.chassisNr) < 0)
9556             return NULL;
9557 
9558         if (virXMLPropInt(targetNodes[0], "chassis", 0, VIR_XML_PROP_NONE,
9559                           &def->opts.pciopts.chassis,
9560                           def->opts.pciopts.chassis) < 0)
9561             return NULL;
9562 
9563         if (virXMLPropInt(targetNodes[0], "port", 0, VIR_XML_PROP_NONE,
9564                           &def->opts.pciopts.port,
9565                           def->opts.pciopts.port) < 0)
9566             return NULL;
9567 
9568         if (virXMLPropInt(targetNodes[0], "busNr", 0, VIR_XML_PROP_NONE,
9569                           &def->opts.pciopts.busNr,
9570                           def->opts.pciopts.busNr) < 0)
9571             return NULL;
9572 
9573         if (virXMLPropTristateSwitch(targetNodes[0], "hotplug",
9574                                      VIR_XML_PROP_NONE,
9575                                      &def->opts.pciopts.hotplug) < 0)
9576             return NULL;
9577 
9578         if ((rc = virXMLPropInt(targetNodes[0], "index", 0, VIR_XML_PROP_NONE,
9579                           &def->opts.pciopts.targetIndex,
9580                           def->opts.pciopts.targetIndex)) < 0)
9581             return NULL;
9582 
9583         if ((rc == 1) && def->opts.pciopts.targetIndex == -1)
9584             virReportError(VIR_ERR_XML_ERROR,
9585                            _("Invalid target index '%i' in PCI controller"),
9586                            def->opts.pciopts.targetIndex);
9587         }
9588     } else if (ntargetNodes > 1) {
9589         virReportError(VIR_ERR_XML_ERROR, "%s",
9590                        _("Multiple <target> elements in "
9591                          "controller definition not allowed"));
9592         return NULL;
9593     }
9594 
9595     /* node is parsed differently from target attributes because
9596      * someone thought it should be a subelement instead...
9597      */
9598     rc = virXPathInt("string(./target/node)", ctxt, &numaNode);
9599     if (rc == -2 || (rc == 0 && numaNode < 0)) {
9600         virReportError(VIR_ERR_XML_ERROR, "%s",
9601                        _("invalid NUMA node in target"));
9602         return NULL;
9603     }
9604 
9605     if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_USB &&
9606         def->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE) {
9607         VIR_DEBUG("Ignoring device address for none model usb controller");
9608     } else if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
9609                                            &def->info, flags) < 0) {
9610         return NULL;
9611     }
9612 
9613     if ((rc = virXMLPropInt(node, "ports", 10, VIR_XML_PROP_NONE, &ports, -1)) < 0)
9614         return NULL;
9615     if ((rc == 1) && ports < 0) {
9616         virReportError(VIR_ERR_INTERNAL_ERROR,
9617                        _("Invalid ports: %i"), ports);
9618         return NULL;
9619     }
9620 
9621     switch (def->type) {
9622     case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: {
9623         if ((rc = virXMLPropInt(node, "vectors", 10, VIR_XML_PROP_NONE,
9624                                 &def->opts.vioserial.vectors,
9625                                 def->opts.vioserial.vectors)) < 0)
9626             return NULL;
9627 
9628         if ((rc == 1) && def->opts.vioserial.vectors < 0) {
9629             virReportError(VIR_ERR_INTERNAL_ERROR,
9630                            _("Invalid vectors: %i"),
9631                            def->opts.vioserial.vectors);
9632             return NULL;
9633         }
9634 
9635         def->opts.vioserial.ports = ports;
9636         break;
9637     }
9638     case VIR_DOMAIN_CONTROLLER_TYPE_USB: {
9639         /* If the XML has a uhci1, uhci2, uhci3 controller and no
9640          * master port was given, we should set a sensible one */
9641         int masterPort = -1;
9642         switch (def->model) {
9643         case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
9644             masterPort = 0;
9645             break;
9646         case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
9647             masterPort = 2;
9648             break;
9649         case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
9650             masterPort = 4;
9651             break;
9652         }
9653         if (masterPort != -1 &&
9654             def->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_NONE) {
9655             def->info.mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
9656             def->info.master.usb.startport = masterPort;
9657         }
9658 
9659         def->opts.usbopts.ports = ports;
9660         break;
9661     }
9662     case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
9663         switch ((virDomainControllerModelPCI) def->model) {
9664         case VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT:
9665         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT: {
9666             unsigned long long bytes;
9667             if ((rc = virParseScaledValue("./pcihole64", NULL,
9668                                           ctxt, &bytes, 1024,
9669                                           1024ULL * ULONG_MAX, false)) < 0)
9670                 return NULL;
9671 
9672             if (rc == 1)
9673                 def->opts.pciopts.pcihole64 = true;
9674             def->opts.pciopts.pcihole64size = VIR_DIV_UP(bytes, 1024);
9675         }
9676         case VIR_DOMAIN_CONTROLLER_MODEL_PCI_BRIDGE:
9677         case VIR_DOMAIN_CONTROLLER_MODEL_DMI_TO_PCI_BRIDGE:
9678         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_TO_PCI_BRIDGE:
9679         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT_PORT:
9680         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_UPSTREAM_PORT:
9681         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_SWITCH_DOWNSTREAM_PORT:
9682         case VIR_DOMAIN_CONTROLLER_MODEL_PCI_EXPANDER_BUS:
9683         case VIR_DOMAIN_CONTROLLER_MODEL_PCIE_EXPANDER_BUS:
9684         case VIR_DOMAIN_CONTROLLER_MODEL_PCI_DEFAULT:
9685         case VIR_DOMAIN_CONTROLLER_MODEL_PCI_LAST:
9686             /* Other controller models don't require extra checks */
9687             break;
9688         }
9689 
9690         if (numaNode >= 0)
9691             def->opts.pciopts.numaNode = numaNode;
9692 
9693         break;
9694     case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS: {
9695         if ((rc = virXMLPropInt(node, "maxGrantFrames", 10, VIR_XML_PROP_NONE,
9696                                 &def->opts.xenbusopts.maxGrantFrames,
9697                                 def->opts.xenbusopts.maxGrantFrames)) < 0)
9698             return NULL;
9699 
9700         if ((rc == 1) && def->opts.xenbusopts.maxGrantFrames < 0) {
9701             virReportError(VIR_ERR_INTERNAL_ERROR,
9702                            _("Invalid maxGrantFrames: %i"),
9703                            def->opts.xenbusopts.maxGrantFrames);
9704             return NULL;
9705         }
9706 
9707         if ((rc = virXMLPropInt(node, "maxEventChannels", 10, VIR_XML_PROP_NONE,
9708                                 &def->opts.xenbusopts.maxEventChannels,
9709                                 def->opts.xenbusopts.maxEventChannels)) < 0)
9710             return NULL;
9711 
9712         if ((rc == 1) && def->opts.xenbusopts.maxEventChannels < 0) {
9713             virReportError(VIR_ERR_INTERNAL_ERROR,
9714                            _("Invalid maxEventChannels: %i"),
9715                            def->opts.xenbusopts.maxEventChannels);
9716             return NULL;
9717         }
9718         break;
9719     }
9720 
9721     default:
9722         break;
9723     }
9724 
9725     return g_steal_pointer(&def);
9726 }
9727 
9728 
9729 void
virDomainNetGenerateMAC(virDomainXMLOption * xmlopt,virMacAddr * mac)9730 virDomainNetGenerateMAC(virDomainXMLOption *xmlopt,
9731                         virMacAddr *mac)
9732 {
9733     virMacAddrGenerate(xmlopt->config.macPrefix, mac);
9734 }
9735 
9736 
9737 static virDomainFSDef *
virDomainFSDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)9738 virDomainFSDefParseXML(virDomainXMLOption *xmlopt,
9739                        xmlNodePtr node,
9740                        xmlXPathContextPtr ctxt,
9741                        unsigned int flags)
9742 {
9743     VIR_XPATH_NODE_AUTORESTORE(ctxt)
9744     virDomainFSDef *def;
9745     xmlNodePtr driver_node = NULL;
9746     xmlNodePtr source_node = NULL;
9747     g_autofree char *type = NULL;
9748     g_autofree char *source = NULL;
9749     g_autofree char *target = NULL;
9750     g_autofree char *format = NULL;
9751     g_autofree char *accessmode = NULL;
9752     g_autofree char *usage = NULL;
9753     g_autofree char *units = NULL;
9754     g_autofree char *model = NULL;
9755     g_autofree char *multidevs = NULL;
9756     g_autofree char *fmode = NULL;
9757     g_autofree char *dmode = NULL;
9758     g_autofree char *sock = NULL;
9759 
9760     ctxt->node = node;
9761 
9762     if (!(def = virDomainFSDefNew(xmlopt)))
9763         return NULL;
9764 
9765     type = virXMLPropString(node, "type");
9766     if (type) {
9767         if ((def->type = virDomainFSTypeFromString(type)) < 0) {
9768             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9769                            _("unknown filesystem type '%s'"), type);
9770             goto error;
9771         }
9772     } else {
9773         def->type = VIR_DOMAIN_FS_TYPE_MOUNT;
9774     }
9775 
9776     accessmode = virXMLPropString(node, "accessmode");
9777     if (accessmode) {
9778         if ((def->accessmode = virDomainFSAccessModeTypeFromString(accessmode)) < 0) {
9779             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9780                            _("unknown accessmode '%s'"), accessmode);
9781             goto error;
9782         }
9783     } else {
9784         def->accessmode = VIR_DOMAIN_FS_ACCESSMODE_DEFAULT;
9785     }
9786 
9787     fmode = virXMLPropString(node, "fmode");
9788     if (fmode) {
9789         if ((virStrToLong_uip(fmode, NULL, 8, &def->fmode) < 0) ||
9790             (def->fmode > 0777)) {
9791             virReportError(VIR_ERR_XML_ERROR,
9792                            _("invalid fmode: '%s'"), fmode);
9793             goto error;
9794         }
9795     }
9796 
9797     dmode = virXMLPropString(node, "dmode");
9798     if (dmode) {
9799         if ((virStrToLong_uip(dmode, NULL, 8, &def->dmode) < 0) ||
9800             (def->dmode > 0777)) {
9801             virReportError(VIR_ERR_XML_ERROR,
9802                            _("invalid dmode: '%s'"), dmode);
9803             goto error;
9804         }
9805     }
9806 
9807     model = virXMLPropString(node, "model");
9808     if (model) {
9809         if ((def->model = virDomainFSModelTypeFromString(model)) < 0 ||
9810             def->model == VIR_DOMAIN_FS_MODEL_DEFAULT) {
9811             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9812                            _("unknown model '%s'"), model);
9813             goto error;
9814         }
9815     }
9816 
9817     multidevs = virXMLPropString(node, "multidevs");
9818     if (multidevs) {
9819         if ((def->multidevs = virDomainFSMultidevsTypeFromString(multidevs)) < 0) {
9820             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9821                            _("unknown multidevs '%s'"), multidevs);
9822             goto error;
9823         }
9824     } else {
9825         def->multidevs = VIR_DOMAIN_FS_MULTIDEVS_DEFAULT;
9826     }
9827 
9828     if (virParseScaledValue("./space_hard_limit[1]",
9829                             NULL, ctxt, &def->space_hard_limit,
9830                             1, ULLONG_MAX, false) < 0)
9831         goto error;
9832 
9833     if (virParseScaledValue("./space_soft_limit[1]",
9834                             NULL, ctxt, &def->space_soft_limit,
9835                             1, ULLONG_MAX, false) < 0)
9836         goto error;
9837 
9838     if ((source_node = virXPathNode("./source", ctxt))) {
9839         sock = virXMLPropString(source_node, "socket");
9840         if (def->type == VIR_DOMAIN_FS_TYPE_MOUNT ||
9841             def->type == VIR_DOMAIN_FS_TYPE_BIND) {
9842             source = virXMLPropString(source_node, "dir");
9843         } else if (def->type == VIR_DOMAIN_FS_TYPE_FILE) {
9844             source = virXMLPropString(source_node, "file");
9845         } else if (def->type == VIR_DOMAIN_FS_TYPE_BLOCK) {
9846             source = virXMLPropString(source_node, "dev");
9847         } else if (def->type == VIR_DOMAIN_FS_TYPE_TEMPLATE) {
9848             source = virXMLPropString(source_node, "name");
9849         } else if (def->type == VIR_DOMAIN_FS_TYPE_RAM) {
9850             usage = virXMLPropString(source_node, "usage");
9851             units = virXMLPropString(source_node, "units");
9852         } else if (def->type == VIR_DOMAIN_FS_TYPE_VOLUME) {
9853             def->src->type = VIR_STORAGE_TYPE_VOLUME;
9854             if (virDomainDiskSourcePoolDefParse(source_node, &def->src->srcpool) < 0)
9855                 goto error;
9856         }
9857     }
9858 
9859     target = virXPathString("string(./target/@dir)", ctxt);
9860 
9861     if (virXPathNode("./readonly", ctxt))
9862         def->readonly = true;
9863 
9864     if ((driver_node = virXPathNode("./driver", ctxt))) {
9865         if (virXMLPropEnum(driver_node, "type",
9866                            virDomainFSDriverTypeFromString,
9867                            VIR_XML_PROP_NONE, &def->fsdriver) < 0)
9868             goto error;
9869 
9870         if (virXMLPropEnum(driver_node, "wrpolicy",
9871                            virDomainFSWrpolicyTypeFromString,
9872                            VIR_XML_PROP_NONE, &def->wrpolicy) < 0)
9873             goto error;
9874 
9875         if ((format = virXMLPropString(driver_node, "format")) &&
9876             ((def->format = virStorageFileFormatTypeFromString(format)) <= 0)) {
9877             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9878                            _("unknown driver format value '%s'"), format);
9879             goto error;
9880         }
9881 
9882         if (virDomainVirtioOptionsParseXML(driver_node, &def->virtio) < 0)
9883             goto error;
9884     }
9885 
9886     if (def->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
9887         g_autofree char *queue_size = virXPathString("string(./driver/@queue)", ctxt);
9888         g_autofree char *binary = virXPathString("string(./binary/@path)", ctxt);
9889         g_autofree char *xattr = virXPathString("string(./binary/@xattr)", ctxt);
9890         g_autofree char *cache = virXPathString("string(./binary/cache/@mode)", ctxt);
9891         g_autofree char *sandbox = virXPathString("string(./binary/sandbox/@mode)", ctxt);
9892         g_autofree char *posix_lock = virXPathString("string(./binary/lock/@posix)", ctxt);
9893         g_autofree char *flock = virXPathString("string(./binary/lock/@flock)", ctxt);
9894         int val;
9895 
9896         if (queue_size && virStrToLong_ull(queue_size, NULL, 10, &def->queue_size) < 0) {
9897             virReportError(VIR_ERR_XML_ERROR,
9898                            _("cannot parse queue size '%s' for virtiofs"),
9899                            queue_size);
9900             goto error;
9901         }
9902 
9903         if (binary)
9904             def->binary = virFileSanitizePath(binary);
9905 
9906         if (xattr) {
9907             if ((val = virTristateSwitchTypeFromString(xattr)) <= 0) {
9908                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9909                                _("unknown xattr value '%s'"), xattr);
9910                 goto error;
9911             }
9912             def->xattr = val;
9913         }
9914 
9915         if (cache) {
9916             if ((val = virDomainFSCacheModeTypeFromString(cache)) <= 0) {
9917                 virReportError(VIR_ERR_XML_ERROR,
9918                                _("cannot parse cache mode '%s' for virtiofs"),
9919                                cache);
9920                 goto error;
9921             }
9922             def->cache = val;
9923         }
9924 
9925         if (sandbox) {
9926             if ((val = virDomainFSSandboxModeTypeFromString(sandbox)) <= 0) {
9927                 virReportError(VIR_ERR_XML_ERROR,
9928                                _("cannot parse sandbox mode '%s' for virtiofs"),
9929                                sandbox);
9930                 goto error;
9931             }
9932             def->sandbox = val;
9933         }
9934 
9935         if (posix_lock) {
9936             if ((val = virTristateSwitchTypeFromString(posix_lock)) <= 0) {
9937                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9938                                _("unknown posix lock value '%s'"), posix_lock);
9939                 goto error;
9940             }
9941             def->posix_lock = val;
9942         }
9943 
9944         if (flock) {
9945             if ((val = virTristateSwitchTypeFromString(flock)) <= 0) {
9946                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
9947                                _("unknown flock value '%s'"), flock);
9948                 goto error;
9949             }
9950             def->flock = val;
9951         }
9952     }
9953 
9954     if (source == NULL && def->type != VIR_DOMAIN_FS_TYPE_RAM
9955         && def->type != VIR_DOMAIN_FS_TYPE_VOLUME && !sock) {
9956         virReportError(VIR_ERR_NO_SOURCE,
9957                        target ? "%s" : NULL, target);
9958         goto error;
9959     }
9960 
9961     if (def->type == VIR_DOMAIN_FS_TYPE_RAM) {
9962         if (!usage) {
9963             virReportError(VIR_ERR_XML_ERROR, "%s",
9964                            _("missing 'usage' attribute for RAM filesystem"));
9965             goto error;
9966         }
9967         if (virStrToLong_ull(usage, NULL, 10, &def->usage) < 0) {
9968             virReportError(VIR_ERR_XML_ERROR,
9969                            _("cannot parse usage '%s' for RAM filesystem"),
9970                            usage);
9971             goto error;
9972         }
9973         if (virScaleInteger(&def->usage, units,
9974                             1024, ULLONG_MAX) < 0)
9975             goto error;
9976     }
9977 
9978     def->src->path = g_steal_pointer(&source);
9979     def->sock = g_steal_pointer(&sock);
9980     def->dst = g_steal_pointer(&target);
9981 
9982     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info,
9983                                     flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT) < 0)
9984         goto error;
9985 
9986     return def;
9987 
9988  error:
9989     virDomainFSDefFree(def);
9990     return NULL;
9991 }
9992 
9993 static int
virDomainActualNetDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virDomainNetDef * parent,virDomainActualNetDef ** def,unsigned int flags,virDomainXMLOption * xmlopt)9994 virDomainActualNetDefParseXML(xmlNodePtr node,
9995                               xmlXPathContextPtr ctxt,
9996                               virDomainNetDef *parent,
9997                               virDomainActualNetDef **def,
9998                               unsigned int flags,
9999                               virDomainXMLOption *xmlopt)
10000 {
10001     virDomainActualNetDef *actual = NULL;
10002     int ret = -1;
10003     VIR_XPATH_NODE_AUTORESTORE(ctxt)
10004     xmlNodePtr bandwidth_node = NULL;
10005     xmlNodePtr vlanNode;
10006     xmlNodePtr virtPortNode;
10007     g_autofree char *addrtype = NULL;
10008     g_autofree char *macTableManager = NULL;
10009 
10010     actual = g_new0(virDomainActualNetDef, 1);
10011 
10012     ctxt->node = node;
10013 
10014     if (virXMLPropEnum(node, "type", virDomainNetTypeFromString,
10015                        VIR_XML_PROP_REQUIRED, &actual->type) < 0)
10016         goto error;
10017 
10018     if (actual->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
10019         actual->type != VIR_DOMAIN_NET_TYPE_DIRECT &&
10020         actual->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
10021         actual->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
10022         virReportError(VIR_ERR_INTERNAL_ERROR,
10023                        _("unsupported type '%s' in interface's <actual> element"),
10024                        virDomainNetTypeToString(actual->type));
10025         goto error;
10026     }
10027 
10028     if (virXMLPropTristateBool(node, "trustGuestRxFilters", VIR_XML_PROP_NONE,
10029                                &actual->trustGuestRxFilters) < 0)
10030         goto error;
10031 
10032     virtPortNode = virXPathNode("./virtualport", ctxt);
10033     if (virtPortNode) {
10034         if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
10035             actual->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
10036             actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
10037             /* the virtualport in <actual> should always already
10038              * have an instanceid/interfaceid if its required,
10039              * so don't let the parser generate one */
10040             if (!(actual->virtPortProfile
10041                   = virNetDevVPortProfileParse(virtPortNode,
10042                                                VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES |
10043                                                VIR_VPORT_XML_REQUIRE_TYPE))) {
10044                 goto error;
10045             }
10046         } else {
10047             virReportError(VIR_ERR_INTERNAL_ERROR,
10048                            _("<virtualport> element unsupported for type='%s'"
10049                              " in interface's <actual> element"),
10050                              virDomainNetTypeToString(actual->type));
10051             goto error;
10052         }
10053     }
10054 
10055     if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
10056         xmlNodePtr sourceNode = virXPathNode("./source[1]", ctxt);
10057 
10058         if (sourceNode) {
10059             int rc;
10060             virNetDevMacVLanMode mode;
10061 
10062             actual->data.direct.linkdev = virXMLPropString(sourceNode, "dev");
10063 
10064             if ((rc = virXMLPropEnum(sourceNode, "mode",
10065                                      virNetDevMacVLanModeTypeFromString,
10066                                      VIR_XML_PROP_NONE, &mode)) < 0)
10067                 goto error;
10068 
10069             if (rc == 1)
10070                 actual->data.direct.mode = mode;
10071         }
10072     } else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
10073         virDomainHostdevDef *hostdev = &actual->data.hostdev.def;
10074 
10075         hostdev->parentnet = parent;
10076         hostdev->info = &parent->info;
10077         /* The helper function expects type to already be found and
10078          * passed in as a string, since it is in a different place in
10079          * NetDef vs HostdevDef.
10080          */
10081         addrtype = virXPathString("string(./source/address/@type)", ctxt);
10082         /* if not explicitly stated, source/vendor implies usb device */
10083         if (!addrtype && virXPathNode("./source/vendor", ctxt))
10084             addrtype = g_strdup("usb");
10085         hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
10086         if (virDomainHostdevDefParseXMLSubsys(node, ctxt, addrtype,
10087                                               hostdev, flags, xmlopt) < 0) {
10088             goto error;
10089         }
10090     } else if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
10091                actual->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
10092         g_autofree char *class_id = NULL;
10093         xmlNodePtr sourceNode;
10094 
10095         class_id = virXPathString("string(./class/@id)", ctxt);
10096         if (class_id &&
10097             virStrToLong_ui(class_id, NULL, 10, &actual->class_id) < 0) {
10098             virReportError(VIR_ERR_INTERNAL_ERROR,
10099                            _("Unable to parse class id '%s'"),
10100                            class_id);
10101             goto error;
10102         }
10103 
10104         sourceNode = virXPathNode("./source", ctxt);
10105         if (sourceNode) {
10106             char *brname = virXMLPropString(sourceNode, "bridge");
10107 
10108             if (!brname && actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
10109                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10110                                _("Missing <source> element with bridge name in "
10111                                  "interface's <actual> element"));
10112                 goto error;
10113             }
10114             actual->data.bridge.brname = brname;
10115             macTableManager = virXMLPropString(sourceNode, "macTableManager");
10116             if (macTableManager &&
10117                 (actual->data.bridge.macTableManager
10118                  = virNetworkBridgeMACTableManagerTypeFromString(macTableManager)) <= 0) {
10119                 virReportError(VIR_ERR_XML_ERROR,
10120                                _("Invalid macTableManager setting '%s' "
10121                                  "in domain interface's <actual> element"),
10122                                macTableManager);
10123                 goto error;
10124             }
10125         }
10126     }
10127 
10128     bandwidth_node = virXPathNode("./bandwidth", ctxt);
10129     if (bandwidth_node &&
10130         virNetDevBandwidthParse(&actual->bandwidth,
10131                                 NULL,
10132                                 bandwidth_node,
10133                                 actual->type == VIR_DOMAIN_NET_TYPE_NETWORK) < 0)
10134         goto error;
10135 
10136     vlanNode = virXPathNode("./vlan", ctxt);
10137     if (vlanNode && virNetDevVlanParse(vlanNode, ctxt, &actual->vlan) < 0)
10138         goto error;
10139 
10140     if (virNetworkPortOptionsParseXML(ctxt, &actual->isolatedPort) < 0)
10141         goto error;
10142 
10143     *def = g_steal_pointer(&actual);
10144     ret = 0;
10145  error:
10146     virDomainActualNetDefFree(actual);
10147 
10148     return ret;
10149 }
10150 
10151 #define NET_MODEL_CHARS \
10152     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
10153 
10154 
10155 int
virDomainNetAppendIPAddress(virDomainNetDef * def,const char * address,int family,unsigned int prefix)10156 virDomainNetAppendIPAddress(virDomainNetDef *def,
10157                             const char *address,
10158                             int family,
10159                             unsigned int prefix)
10160 {
10161     virNetDevIPAddr *ipDef = NULL;
10162     ipDef = g_new0(virNetDevIPAddr, 1);
10163 
10164     if (virSocketAddrParse(&ipDef->address, address, family) < 0)
10165         goto error;
10166     ipDef->prefix = prefix;
10167 
10168     VIR_APPEND_ELEMENT(def->guestIP.ips, def->guestIP.nips, ipDef);
10169 
10170     return 0;
10171 
10172  error:
10173     VIR_FREE(ipDef);
10174     return -1;
10175 }
10176 
10177 
10178 static int
virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt)10179 virDomainChrSourceReconnectDefParseXML(virDomainChrSourceReconnectDef *def,
10180                                        xmlNodePtr node,
10181                                        xmlXPathContextPtr ctxt)
10182 {
10183     VIR_XPATH_NODE_AUTORESTORE(ctxt)
10184     xmlNodePtr cur;
10185 
10186     ctxt->node = node;
10187 
10188     if ((cur = virXPathNode("./reconnect", ctxt))) {
10189         if (virXMLPropTristateBool(cur, "enabled", VIR_XML_PROP_NONE,
10190                                    &def->enabled) < 0)
10191             return -1;
10192 
10193         if (def->enabled == VIR_TRISTATE_BOOL_YES) {
10194             if (virXMLPropUInt(cur, "timeout", 10, VIR_XML_PROP_REQUIRED,
10195                                &def->timeout) < 0)
10196                 return -1;
10197         }
10198     }
10199 
10200     return 0;
10201 }
10202 
10203 
10204 static int
virDomainNetTeamingInfoParseXML(xmlXPathContextPtr ctxt,virDomainNetTeamingInfo ** teaming)10205 virDomainNetTeamingInfoParseXML(xmlXPathContextPtr ctxt,
10206                                 virDomainNetTeamingInfo **teaming)
10207 {
10208     g_autofree char *typeStr = virXPathString("string(./teaming/@type)", ctxt);
10209     g_autofree char *persistentStr = virXPathString("string(./teaming/@persistent)", ctxt);
10210     g_autoptr(virDomainNetTeamingInfo) tmpTeaming = NULL;
10211     int tmpType;
10212 
10213     if (!typeStr && !persistentStr)
10214         return 0;
10215 
10216     tmpTeaming = g_new0(virDomainNetTeamingInfo, 1);
10217 
10218     if ((tmpType = virDomainNetTeamingTypeFromString(typeStr)) <= 0) {
10219             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10220                            _("unknown teaming type '%s'"),
10221                            typeStr);
10222             return -1;
10223     }
10224 
10225     tmpTeaming->type = tmpType;
10226     tmpTeaming->persistent = g_steal_pointer(&persistentStr);
10227     *teaming = g_steal_pointer(&tmpTeaming);
10228     return 0;
10229 }
10230 
10231 
10232 static virDomainNetDef *
virDomainNetDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)10233 virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
10234                         xmlNodePtr node,
10235                         xmlXPathContextPtr ctxt,
10236                         unsigned int flags)
10237 {
10238     virDomainNetDef *def;
10239     virDomainHostdevDef *hostdev;
10240     xmlNodePtr source_node = NULL;
10241     xmlNodePtr virtualport_node = NULL;
10242     xmlNodePtr driver_node = NULL;
10243     xmlNodePtr filterref_node = NULL;
10244     xmlNodePtr actual_node = NULL;
10245     xmlNodePtr vlan_node = NULL;
10246     xmlNodePtr bandwidth_node = NULL;
10247     xmlNodePtr tmpNode;
10248     GHashTable *filterparams = NULL;
10249     virDomainActualNetDef *actual = NULL;
10250     VIR_XPATH_NODE_AUTORESTORE(ctxt)
10251     virDomainChrSourceReconnectDef reconnect = {0};
10252     int rv, val;
10253     g_autofree char *macaddr = NULL;
10254     g_autofree char *macaddr_type = NULL;
10255     g_autofree char *macaddr_check = NULL;
10256     g_autofree char *network = NULL;
10257     g_autofree char *portgroup = NULL;
10258     g_autofree char *portid = NULL;
10259     g_autofree char *bridge = NULL;
10260     g_autofree char *dev = NULL;
10261     g_autofree char *ifname = NULL;
10262     g_autofree char *managed_tap = NULL;
10263     g_autofree char *ifname_guest = NULL;
10264     g_autofree char *ifname_guest_actual = NULL;
10265     g_autofree char *script = NULL;
10266     g_autofree char *downscript = NULL;
10267     g_autofree char *address = NULL;
10268     g_autofree char *port = NULL;
10269     g_autofree char *localaddr = NULL;
10270     g_autofree char *localport = NULL;
10271     g_autofree char *model = NULL;
10272     g_autofree char *backend = NULL;
10273     g_autofree char *txmode = NULL;
10274     g_autofree char *ioeventfd = NULL;
10275     g_autofree char *event_idx = NULL;
10276     g_autofree char *queues = NULL;
10277     g_autofree char *rx_queue_size = NULL;
10278     g_autofree char *tx_queue_size = NULL;
10279     g_autofree char *filter = NULL;
10280     g_autofree char *internal = NULL;
10281     g_autofree char *mode = NULL;
10282     g_autofree char *linkstate = NULL;
10283     g_autofree char *addrtype = NULL;
10284     g_autofree char *domain_name = NULL;
10285     g_autofree char *vhostuser_mode = NULL;
10286     g_autofree char *vhostuser_path = NULL;
10287     g_autofree char *vhostuser_type = NULL;
10288     g_autofree char *vhost_path = NULL;
10289     g_autofree char *tap = NULL;
10290     g_autofree char *vhost = NULL;
10291     const char *prefix = xmlopt ? xmlopt->config.netPrefix : NULL;
10292 
10293     if (!(def = virDomainNetDefNew(xmlopt)))
10294         return NULL;
10295 
10296     ctxt->node = node;
10297 
10298     if ((rv = virXMLPropEnum(node, "type", virDomainNetTypeFromString,
10299                              VIR_XML_PROP_NONE, &def->type)) < 0)
10300         goto error;
10301 
10302     if (rv == 0)
10303         def->type = VIR_DOMAIN_NET_TYPE_USER;
10304 
10305     if (virXMLPropTristateBool(node, "trustGuestRxFilters", VIR_XML_PROP_NONE,
10306                                &def->trustGuestRxFilters) < 0)
10307         goto error;
10308 
10309     if ((source_node = virXPathNode("./source", ctxt))) {
10310         xmlNodePtr tmpnode = ctxt->node;
10311 
10312         ctxt->node = source_node;
10313         if (virDomainNetIPInfoParseXML(_("interface host IP"), ctxt, &def->hostIP) < 0)
10314             goto error;
10315         ctxt->node = tmpnode;
10316 
10317         if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
10318             network = virXMLPropString(source_node, "network");
10319             portgroup = virXMLPropString(source_node, "portgroup");
10320             if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
10321                 portid = virXMLPropString(source_node, "portid");
10322         }
10323 
10324         if (def->type == VIR_DOMAIN_NET_TYPE_INTERNAL)
10325             internal = virXMLPropString(source_node, "name");
10326 
10327         if (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE)
10328             bridge = virXMLPropString(source_node, "bridge");
10329 
10330         if (def->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
10331             dev = virXMLPropString(source_node, "dev");
10332             mode = virXMLPropString(source_node, "mode");
10333         }
10334 
10335         /* This clause is only necessary because from 2010 to 2016 it was
10336          * possible (but never documented) to configure the name of the
10337          * guest-side interface of an openvz domain with <source dev='blah'/>.
10338          * That was blatant misuse of <source>, so was likely (hopefully)
10339          * never used, but just in case there was somebody using it, we
10340          * need to generate an error. If the openvz driver is ever
10341          * deprecated, this clause can be removed from here.
10342          */
10343         if (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
10344             (dev = virXMLPropString(source_node, "dev"))) {
10345             virReportError(VIR_ERR_XML_ERROR,
10346                            _("Invalid attempt to set <interface type='ethernet'> "
10347                              "device name with <source dev='%s'/>. "
10348                              "Use <target dev='%s'/> (for host-side) "
10349                              "or <guest dev='%s'/> (for guest-side) instead."),
10350                            dev, dev, dev);
10351             goto error;
10352         }
10353 
10354         if (def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
10355             vhostuser_type = virXMLPropString(source_node, "type");
10356             vhostuser_path = virXMLPropString(source_node, "path");
10357             vhostuser_mode = virXMLPropString(source_node, "mode");
10358             if (virDomainChrSourceReconnectDefParseXML(&reconnect, source_node, ctxt) < 0)
10359                 goto error;
10360         }
10361 
10362         if (def->type == VIR_DOMAIN_NET_TYPE_VDPA)
10363             dev = virXMLPropString(source_node, "dev");
10364 
10365         if (def->type == VIR_DOMAIN_NET_TYPE_SERVER ||
10366             def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
10367             def->type == VIR_DOMAIN_NET_TYPE_MCAST ||
10368             def->type == VIR_DOMAIN_NET_TYPE_UDP) {
10369 
10370             address = virXMLPropString(source_node, "address");
10371             port = virXMLPropString(source_node, "port");
10372             if (def->type == VIR_DOMAIN_NET_TYPE_UDP) {
10373                 xmlNodePtr tmp_node = ctxt->node;
10374                 ctxt->node = source_node;
10375                 if ((tmpNode = virXPathNode("./local", ctxt))) {
10376                     localaddr = virXMLPropString(tmpNode, "address");
10377                     localport = virXMLPropString(tmpNode, "port");
10378                 }
10379                 ctxt->node = tmp_node;
10380             }
10381         }
10382     }
10383 
10384     if ((virtualport_node = virXPathNode("./virtualport", ctxt))) {
10385         if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
10386             if (!(def->virtPortProfile
10387                   = virNetDevVPortProfileParse(virtualport_node,
10388                                                VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS))) {
10389                 goto error;
10390             }
10391         } else if (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
10392                    def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
10393                    def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
10394             if (!(def->virtPortProfile
10395                   = virNetDevVPortProfileParse(virtualport_node, VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS|
10396                                                VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES|
10397                                                VIR_VPORT_XML_REQUIRE_TYPE))) {
10398                 goto error;
10399             }
10400         } else {
10401             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10402                            _("<virtualport> element unsupported for"
10403                              " <interface type='%s'>"),
10404                              virDomainNetTypeToString(def->type));
10405             goto error;
10406         }
10407     }
10408 
10409     ifname = virXPathString("string(./target/@dev)", ctxt);
10410     managed_tap = virXPathString("string(./target/@managed)", ctxt);
10411 
10412     ifname_guest = virXPathString("string(./guest/@dev)", ctxt);
10413     ifname_guest_actual = virXPathString("string(./guest/@actual)", ctxt);
10414 
10415     linkstate = virXPathString("string(./link/@state)", ctxt);
10416     script = virXPathString("string(./script/@path)", ctxt);
10417     downscript = virXPathString("string(./downscript/@path)", ctxt);
10418     domain_name = virXPathString("string(./backenddomain/@name)", ctxt);
10419     model = virXPathString("string(./model/@type)", ctxt);
10420 
10421     if ((driver_node = virXPathNode("./driver", ctxt)) &&
10422         (virDomainVirtioOptionsParseXML(driver_node, &def->virtio) < 0))
10423         goto error;
10424 
10425     backend = virXMLPropString(driver_node, "name");
10426     txmode = virXMLPropString(driver_node, "txmode");
10427     ioeventfd = virXMLPropString(driver_node, "ioeventfd");
10428     event_idx = virXMLPropString(driver_node, "event_idx");
10429     queues = virXMLPropString(driver_node, "queues");
10430     rx_queue_size = virXMLPropString(driver_node, "rx_queue_size");
10431     tx_queue_size = virXMLPropString(driver_node, "tx_queue_size");
10432 
10433     if ((filterref_node = virXPathNode("./filterref", ctxt))) {
10434         filter = virXMLPropString(filterref_node, "filter");
10435         virHashFree(filterparams);
10436         filterparams = virNWFilterParseParamAttributes(filterref_node);
10437     }
10438 
10439     if ((flags & VIR_DOMAIN_DEF_PARSE_ACTUAL_NET) &&
10440         def->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
10441         (actual_node = virXPathNode("./actual", ctxt)) &&
10442         (virDomainActualNetDefParseXML(actual_node, ctxt, def,
10443                                       &actual, flags, xmlopt) < 0))
10444         goto error;
10445 
10446     if ((bandwidth_node = virXPathNode("./bandwidth", ctxt)) &&
10447         (virNetDevBandwidthParse(&def->bandwidth, NULL, bandwidth_node,
10448                                  def->type == VIR_DOMAIN_NET_TYPE_NETWORK) < 0))
10449         goto error;
10450 
10451     if ((vlan_node = virXPathNode("./vlan", ctxt)) &&
10452         (virNetDevVlanParse(vlan_node, ctxt, &def->vlan) < 0))
10453         goto error;
10454 
10455     if ((tap = virXPathString("string(./backend/@tap)", ctxt)))
10456         def->backend.tap = virFileSanitizePath(tap);
10457 
10458     if ((vhost = virXPathString("string(./backend/@vhost)", ctxt)))
10459         vhost_path = virFileSanitizePath(vhost);
10460 
10461     if ((macaddr = virXPathString("string(./mac/@address)", ctxt))) {
10462         if (virMacAddrParse((const char *)macaddr, &def->mac) < 0) {
10463             virReportError(VIR_ERR_XML_ERROR,
10464                            _("unable to parse mac address '%s'"),
10465                            (const char *)macaddr);
10466             goto error;
10467         }
10468         if (virMacAddrIsMulticast(&def->mac)) {
10469             virReportError(VIR_ERR_XML_ERROR,
10470                            _("expected unicast mac address, found multicast '%s'"),
10471                            (const char *)macaddr);
10472             goto error;
10473         }
10474     } else {
10475         virDomainNetGenerateMAC(xmlopt, &def->mac);
10476         def->mac_generated = true;
10477     }
10478 
10479     if ((macaddr_type = virXPathString("string(./mac/@type)", ctxt))) {
10480         int tmp;
10481 
10482         if ((tmp = virDomainNetMacTypeTypeFromString(macaddr_type)) <= 0) {
10483             virReportError(VIR_ERR_XML_ERROR,
10484                            _("invalid mac address type value: '%s'. Valid "
10485                              "values are \"generated\" and \"static\"."),
10486                            macaddr_type);
10487             goto error;
10488         }
10489         def->mac_type = tmp;
10490     }
10491 
10492     if ((macaddr_check = virXPathString("string(./mac/@check)", ctxt))) {
10493         int tmpCheck;
10494 
10495         if ((tmpCheck = virTristateBoolTypeFromString(macaddr_check)) < 0) {
10496             virReportError(VIR_ERR_XML_ERROR,
10497                            _("invalid mac address check value: '%s'"),
10498                            macaddr_check);
10499             goto error;
10500         }
10501         def->mac_check = tmpCheck;
10502     }
10503 
10504     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info,
10505                                     flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT
10506                                     | VIR_DOMAIN_DEF_PARSE_ALLOW_ROM) < 0) {
10507         goto error;
10508     }
10509 
10510     if (model != NULL &&
10511         virDomainNetSetModelString(def, model) < 0)
10512         goto error;
10513 
10514     switch (def->type) {
10515     case VIR_DOMAIN_NET_TYPE_NETWORK:
10516         if (network == NULL) {
10517             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10518                            _("No <source> 'network' attribute "
10519                              "specified with <interface type='network'/>"));
10520             goto error;
10521         }
10522         if (portid &&
10523             virUUIDParse(portid, def->data.network.portid) < 0) {
10524             virReportError(VIR_ERR_INTERNAL_ERROR,
10525                            _("Unable to parse port id '%s'"), portid);
10526             goto error;
10527         }
10528 
10529         def->data.network.name = g_steal_pointer(&network);
10530         def->data.network.portgroup = g_steal_pointer(&portgroup);
10531         def->data.network.actual = g_steal_pointer(&actual);
10532         break;
10533 
10534     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
10535         if (!virDomainNetIsVirtioModel(def)) {
10536             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10537                            _("Wrong or no <model> 'type' attribute "
10538                              "specified with <interface type='vhostuser'/>. "
10539                              "vhostuser requires the virtio-net* frontend"));
10540             goto error;
10541         }
10542 
10543         if (STRNEQ_NULLABLE(vhostuser_type, "unix")) {
10544             if (vhostuser_type)
10545                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10546                                _("Type='%s' unsupported for"
10547                                  " <interface type='vhostuser'>"),
10548                                vhostuser_type);
10549             else
10550                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10551                                _("No <source> 'type' attribute "
10552                                  "specified for <interface "
10553                                  "type='vhostuser'>"));
10554             goto error;
10555         }
10556 
10557         if (vhostuser_path == NULL) {
10558             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10559                            _("No <source> 'path' attribute "
10560                              "specified with <interface "
10561                              "type='vhostuser'/>"));
10562             goto error;
10563         }
10564 
10565         if (vhostuser_mode == NULL) {
10566             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10567                            _("No <source> 'mode' attribute "
10568                              "specified with <interface "
10569                              "type='vhostuser'/>"));
10570             goto error;
10571         }
10572 
10573         if (!(def->data.vhostuser = virDomainChrSourceDefNew(xmlopt)))
10574             goto error;
10575 
10576         def->data.vhostuser->type = VIR_DOMAIN_CHR_TYPE_UNIX;
10577         def->data.vhostuser->data.nix.path = g_steal_pointer(&vhostuser_path);
10578 
10579         if (STREQ(vhostuser_mode, "server")) {
10580             def->data.vhostuser->data.nix.listen = true;
10581             if (reconnect.enabled == VIR_TRISTATE_BOOL_YES) {
10582                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10583                                _("'reconnect' attribute  unsupported "
10584                                  "'server' mode for <interface type='vhostuser'>"));
10585                 goto error;
10586            }
10587         } else if (STREQ(vhostuser_mode, "client")) {
10588             def->data.vhostuser->data.nix.listen = false;
10589             def->data.vhostuser->data.nix.reconnect = reconnect;
10590         } else {
10591             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10592                            _("Wrong <source> 'mode' attribute "
10593                              "specified with <interface "
10594                              "type='vhostuser'/>"));
10595             goto error;
10596         }
10597         break;
10598 
10599     case VIR_DOMAIN_NET_TYPE_VDPA:
10600         if (dev == NULL) {
10601             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10602                            _("No <source> 'dev' attribute "
10603                              "specified with <interface type='vdpa'/>"));
10604             goto error;
10605         }
10606         def->data.vdpa.devicepath = g_steal_pointer(&dev);
10607         break;
10608 
10609     case VIR_DOMAIN_NET_TYPE_BRIDGE:
10610         if (bridge == NULL) {
10611             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10612                            _("No <source> 'bridge' attribute "
10613                              "specified with <interface type='bridge'/>"));
10614             goto error;
10615         }
10616         def->data.bridge.brname = g_steal_pointer(&bridge);
10617         break;
10618 
10619     case VIR_DOMAIN_NET_TYPE_CLIENT:
10620     case VIR_DOMAIN_NET_TYPE_SERVER:
10621     case VIR_DOMAIN_NET_TYPE_MCAST:
10622     case VIR_DOMAIN_NET_TYPE_UDP:
10623         if (port == NULL) {
10624             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10625                            _("No <source> 'port' attribute "
10626                              "specified with socket interface"));
10627             goto error;
10628         }
10629         if (virStrToLong_i(port, NULL, 10, &def->data.socket.port) < 0) {
10630             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10631                            _("Cannot parse <source> 'port' attribute "
10632                              "with socket interface"));
10633             goto error;
10634         }
10635 
10636         if (address == NULL) {
10637             if (def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
10638                 def->type == VIR_DOMAIN_NET_TYPE_MCAST ||
10639                 def->type == VIR_DOMAIN_NET_TYPE_UDP) {
10640                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10641                                _("No <source> 'address' attribute "
10642                                  "specified with socket interface"));
10643                 goto error;
10644             }
10645         } else {
10646             def->data.socket.address = g_steal_pointer(&address);
10647         }
10648 
10649         if (def->type != VIR_DOMAIN_NET_TYPE_UDP)
10650             break;
10651 
10652         if (localport == NULL) {
10653             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10654                            _("No <local> 'port' attribute "
10655                              "specified with socket interface"));
10656             goto error;
10657         }
10658         if (virStrToLong_i(localport, NULL, 10, &def->data.socket.localport) < 0) {
10659             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10660                            _("Cannot parse <local> 'port' attribute "
10661                              "with socket interface"));
10662             goto error;
10663         }
10664 
10665         if (localaddr == NULL) {
10666             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10667                            _("No <local> 'address' attribute "
10668                              "specified with socket interface"));
10669             goto error;
10670         } else {
10671             def->data.socket.localaddr = g_steal_pointer(&localaddr);
10672         }
10673         break;
10674 
10675     case VIR_DOMAIN_NET_TYPE_INTERNAL:
10676         if (internal == NULL) {
10677             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10678                            _("No <source> 'name' attribute specified "
10679                              "with <interface type='internal'/>"));
10680             goto error;
10681         }
10682         def->data.internal.name = g_steal_pointer(&internal);
10683         break;
10684 
10685     case VIR_DOMAIN_NET_TYPE_DIRECT:
10686         if (dev == NULL) {
10687             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
10688                            _("No <source> 'dev' attribute specified "
10689                              "with <interface type='direct'/>"));
10690             goto error;
10691         }
10692 
10693         if (mode != NULL) {
10694             if ((val = virNetDevMacVLanModeTypeFromString(mode)) < 0) {
10695                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
10696                                _("Unknown mode has been specified"));
10697                 goto error;
10698             }
10699             def->data.direct.mode = val;
10700         } else {
10701             def->data.direct.mode = VIR_NETDEV_MACVLAN_MODE_VEPA;
10702         }
10703 
10704         def->data.direct.linkdev = g_steal_pointer(&dev);
10705         break;
10706 
10707     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
10708         hostdev = &def->data.hostdev.def;
10709         hostdev->parentnet = def;
10710         hostdev->info = &def->info;
10711         /* The helper function expects type to already be found and
10712          * passed in as a string, since it is in a different place in
10713          * NetDef vs HostdevDef.
10714          */
10715         addrtype = virXPathString("string(./source/address/@type)", ctxt);
10716         /* if not explicitly stated, source/vendor implies usb device */
10717         if (!addrtype && virXPathNode("./source/vendor", ctxt))
10718             addrtype = g_strdup("usb");
10719         hostdev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
10720         if (virDomainHostdevDefParseXMLSubsys(node, ctxt, addrtype,
10721                                               hostdev, flags, xmlopt) < 0) {
10722             goto error;
10723         }
10724         break;
10725 
10726     case VIR_DOMAIN_NET_TYPE_ETHERNET:
10727     case VIR_DOMAIN_NET_TYPE_USER:
10728     case VIR_DOMAIN_NET_TYPE_LAST:
10729         break;
10730     }
10731 
10732     if (virDomainNetIPInfoParseXML(_("guest interface"),
10733                                    ctxt, &def->guestIP) < 0)
10734         goto error;
10735 
10736     if (managed_tap) {
10737         bool state = false;
10738         if (virStringParseYesNo(managed_tap, &state) < 0) {
10739             virReportError(VIR_ERR_XML_ERROR,
10740                            _("invalid 'managed' value '%s'"),
10741                            managed_tap);
10742             goto error;
10743         }
10744         def->managed_tap = virTristateBoolFromBool(state);
10745     }
10746 
10747     if (def->managed_tap != VIR_TRISTATE_BOOL_NO && ifname &&
10748         (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
10749         (STRPREFIX(ifname, VIR_NET_GENERATED_VNET_PREFIX) ||
10750          STRPREFIX(ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) ||
10751          STRPREFIX(ifname, VIR_NET_GENERATED_MACVLAN_PREFIX) ||
10752          (prefix && STRPREFIX(ifname, prefix)))) {
10753         /* An auto-generated target name, blank it out */
10754         VIR_FREE(ifname);
10755     }
10756 
10757     if (script != NULL)
10758         def->script = g_steal_pointer(&script);
10759     if (downscript != NULL)
10760         def->downscript = g_steal_pointer(&downscript);
10761     if (domain_name != NULL)
10762         def->domain_name = g_steal_pointer(&domain_name);
10763     if (ifname != NULL)
10764         def->ifname = g_steal_pointer(&ifname);
10765     if (ifname_guest != NULL)
10766         def->ifname_guest = g_steal_pointer(&ifname_guest);
10767     if (ifname_guest_actual != NULL)
10768         def->ifname_guest_actual = g_steal_pointer(&ifname_guest_actual);
10769 
10770     if (def->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
10771         virDomainNetIsVirtioModel(def)) {
10772         if (backend != NULL) {
10773             if ((val = virDomainNetBackendTypeFromString(backend)) < 0 ||
10774                 val == VIR_DOMAIN_NET_BACKEND_TYPE_DEFAULT) {
10775                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10776                                _("Unknown interface <driver name='%s'> "
10777                                  "has been specified"),
10778                                backend);
10779                 goto error;
10780             }
10781             def->driver.virtio.name = val;
10782         }
10783         if (txmode != NULL) {
10784             if ((val = virDomainNetVirtioTxModeTypeFromString(txmode)) < 0 ||
10785                 val == VIR_DOMAIN_NET_VIRTIO_TX_MODE_DEFAULT) {
10786                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10787                                _("Unknown interface <driver txmode='%s'> "
10788                                  "has been specified"),
10789                                txmode);
10790                 goto error;
10791             }
10792             def->driver.virtio.txmode = val;
10793         }
10794         if (ioeventfd) {
10795             if ((val = virTristateSwitchTypeFromString(ioeventfd)) <= 0) {
10796                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10797                                _("unknown interface ioeventfd mode '%s'"),
10798                                ioeventfd);
10799                 goto error;
10800             }
10801             def->driver.virtio.ioeventfd = val;
10802         }
10803         if (event_idx) {
10804             if ((val = virTristateSwitchTypeFromString(event_idx)) <= 0) {
10805                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10806                                _("unknown interface event_idx mode '%s'"),
10807                                event_idx);
10808                 goto error;
10809             }
10810             def->driver.virtio.event_idx = val;
10811         }
10812         if (queues) {
10813             unsigned int q;
10814             if (virStrToLong_uip(queues, NULL, 10, &q) < 0) {
10815                 virReportError(VIR_ERR_XML_DETAIL,
10816                                _("'queues' attribute must be positive number: %s"),
10817                                queues);
10818                 goto error;
10819             }
10820             if (q > 1)
10821                 def->driver.virtio.queues = q;
10822         }
10823         if (rx_queue_size) {
10824             unsigned int q;
10825             if (virStrToLong_uip(rx_queue_size, NULL, 10, &q) < 0) {
10826                 virReportError(VIR_ERR_XML_DETAIL,
10827                                _("'rx_queue_size' attribute must be positive number: %s"),
10828                                rx_queue_size);
10829                 goto error;
10830             }
10831             def->driver.virtio.rx_queue_size = q;
10832         }
10833         if (tx_queue_size) {
10834             unsigned int q;
10835             if (virStrToLong_uip(tx_queue_size, NULL, 10, &q) < 0) {
10836                 virReportError(VIR_ERR_XML_DETAIL,
10837                                _("'tx_queue_size' attribute must be positive number: %s"),
10838                                tx_queue_size);
10839                 goto error;
10840             }
10841             def->driver.virtio.tx_queue_size = q;
10842         }
10843 
10844         if ((tmpNode = virXPathNode("./driver/host", ctxt))) {
10845             if (virXMLPropTristateSwitch(tmpNode, "csum", VIR_XML_PROP_NONE,
10846                                          &def->driver.virtio.host.csum) < 0)
10847                 goto error;
10848 
10849             if (virXMLPropTristateSwitch(tmpNode, "gso", VIR_XML_PROP_NONE,
10850                                          &def->driver.virtio.host.gso) < 0)
10851                 goto error;
10852 
10853             if (virXMLPropTristateSwitch(tmpNode, "tso4", VIR_XML_PROP_NONE,
10854                                          &def->driver.virtio.host.tso4) < 0)
10855                 goto error;
10856 
10857             if (virXMLPropTristateSwitch(tmpNode, "tso6", VIR_XML_PROP_NONE,
10858                                          &def->driver.virtio.host.tso6) < 0)
10859                 goto error;
10860 
10861             if (virXMLPropTristateSwitch(tmpNode, "ecn", VIR_XML_PROP_NONE,
10862                                          &def->driver.virtio.host.ecn) < 0)
10863                 goto error;
10864 
10865             if (virXMLPropTristateSwitch(tmpNode, "ufo", VIR_XML_PROP_NONE,
10866                                          &def->driver.virtio.host.ufo) < 0)
10867                 goto error;
10868 
10869             if (virXMLPropTristateSwitch(tmpNode, "mrg_rxbuf",
10870                                          VIR_XML_PROP_NONE,
10871                                          &def->driver.virtio.host.mrg_rxbuf) < 0)
10872                 goto error;
10873         }
10874 
10875         if ((tmpNode = virXPathNode("./driver/guest", ctxt))) {
10876             if (virXMLPropTristateSwitch(tmpNode, "csum", VIR_XML_PROP_NONE,
10877                                          &def->driver.virtio.guest.csum) < 0)
10878                 goto error;
10879 
10880             if (virXMLPropTristateSwitch(tmpNode, "tso4", VIR_XML_PROP_NONE,
10881                                          &def->driver.virtio.guest.tso4) < 0)
10882                 goto error;
10883 
10884             if (virXMLPropTristateSwitch(tmpNode, "tso6", VIR_XML_PROP_NONE,
10885                                          &def->driver.virtio.guest.tso6) < 0)
10886                 goto error;
10887 
10888             if (virXMLPropTristateSwitch(tmpNode, "ecn", VIR_XML_PROP_NONE,
10889                                          &def->driver.virtio.guest.ecn) < 0)
10890                 goto error;
10891 
10892             if (virXMLPropTristateSwitch(tmpNode, "ufo", VIR_XML_PROP_NONE,
10893                                          &def->driver.virtio.guest.ufo) < 0)
10894                 goto error;
10895         }
10896         def->backend.vhost = g_steal_pointer(&vhost_path);
10897     }
10898 
10899     def->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DEFAULT;
10900     if (linkstate != NULL) {
10901         if ((def->linkstate = virDomainNetInterfaceLinkStateTypeFromString(linkstate)) <= 0) {
10902             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
10903                            _("unknown interface link state '%s'"),
10904                            linkstate);
10905             goto error;
10906         }
10907     }
10908 
10909     if (filter != NULL) {
10910         switch (def->type) {
10911         case VIR_DOMAIN_NET_TYPE_ETHERNET:
10912         case VIR_DOMAIN_NET_TYPE_NETWORK:
10913         case VIR_DOMAIN_NET_TYPE_BRIDGE:
10914             def->filter = g_steal_pointer(&filter);
10915             def->filterparams = g_steal_pointer(&filterparams);
10916             break;
10917         case VIR_DOMAIN_NET_TYPE_USER:
10918         case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
10919         case VIR_DOMAIN_NET_TYPE_SERVER:
10920         case VIR_DOMAIN_NET_TYPE_CLIENT:
10921         case VIR_DOMAIN_NET_TYPE_MCAST:
10922         case VIR_DOMAIN_NET_TYPE_INTERNAL:
10923         case VIR_DOMAIN_NET_TYPE_DIRECT:
10924         case VIR_DOMAIN_NET_TYPE_HOSTDEV:
10925         case VIR_DOMAIN_NET_TYPE_UDP:
10926         case VIR_DOMAIN_NET_TYPE_VDPA:
10927             break;
10928         case VIR_DOMAIN_NET_TYPE_LAST:
10929         default:
10930             virReportEnumRangeError(virDomainNetType, def->type);
10931             goto error;
10932         }
10933     }
10934 
10935     if (virDomainNetTeamingInfoParseXML(ctxt, &def->teaming) < 0)
10936         goto error;
10937 
10938     rv = virXPathULong("string(./tune/sndbuf)", ctxt, &def->tune.sndbuf);
10939     if (rv >= 0) {
10940         def->tune.sndbuf_specified = true;
10941     } else if (rv == -2) {
10942         virReportError(VIR_ERR_XML_ERROR, "%s",
10943                        _("sndbuf must be a positive integer"));
10944         goto error;
10945     }
10946 
10947     if (virXPathUInt("string(./mtu/@size)", ctxt, &def->mtu) < -1) {
10948         virReportError(VIR_ERR_XML_ERROR, "%s",
10949                        _("malformed mtu size"));
10950         goto error;
10951     }
10952 
10953     node = virXPathNode("./coalesce", ctxt);
10954     if (node) {
10955         if (virDomainNetDefCoalesceParseXML(node, ctxt, &def->coalesce) < 0)
10956             goto error;
10957     }
10958 
10959     if (virNetworkPortOptionsParseXML(ctxt, &def->isolatedPort) < 0)
10960         goto error;
10961 
10962  cleanup:
10963     virDomainActualNetDefFree(actual);
10964     virHashFree(filterparams);
10965     return def;
10966 
10967  error:
10968     virDomainNetDefFree(def);
10969     def = NULL;
10970     goto cleanup;
10971 }
10972 
10973 static int
virDomainChrDefaultTargetType(int devtype)10974 virDomainChrDefaultTargetType(int devtype)
10975 {
10976     switch ((virDomainChrDeviceType) devtype) {
10977     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
10978         virReportError(VIR_ERR_XML_ERROR,
10979                        _("target type must be specified for %s device"),
10980                        virDomainChrDeviceTypeToString(devtype));
10981         return -1;
10982 
10983     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
10984         return VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE;
10985 
10986     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
10987         return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE;
10988 
10989     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
10990     case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
10991         /* No target type yet */
10992         break;
10993     }
10994 
10995     return 0;
10996 }
10997 
10998 static int
virDomainChrTargetTypeFromString(int devtype,const char * targetType)10999 virDomainChrTargetTypeFromString(int devtype,
11000                                  const char *targetType)
11001 {
11002     int ret = -1;
11003 
11004     if (!targetType)
11005         return virDomainChrDefaultTargetType(devtype);
11006 
11007     switch ((virDomainChrDeviceType) devtype) {
11008     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
11009         ret = virDomainChrChannelTargetTypeFromString(targetType);
11010         break;
11011 
11012     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
11013         ret = virDomainChrConsoleTargetTypeFromString(targetType);
11014         break;
11015 
11016     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
11017         ret = virDomainChrSerialTargetTypeFromString(targetType);
11018         break;
11019 
11020     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
11021     case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
11022         /* No target type yet */
11023         ret = 0;
11024         break;
11025     }
11026 
11027     return ret;
11028 }
11029 
11030 static int
virDomainChrTargetModelFromString(int devtype,const char * targetModel)11031 virDomainChrTargetModelFromString(int devtype,
11032                                   const char *targetModel)
11033 {
11034     int ret = -1;
11035 
11036     if (!targetModel)
11037         return 0;
11038 
11039     switch ((virDomainChrDeviceType) devtype) {
11040     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
11041         ret = virDomainChrSerialTargetModelTypeFromString(targetModel);
11042         break;
11043 
11044     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
11045     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
11046     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
11047     case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
11048         /* Target model not supported yet */
11049         ret = 0;
11050         break;
11051     }
11052 
11053     return ret;
11054 }
11055 
11056 static int
virDomainChrDefParseTargetXML(virDomainChrDef * def,xmlNodePtr cur,xmlXPathContextPtr ctxt,unsigned int flags)11057 virDomainChrDefParseTargetXML(virDomainChrDef *def,
11058                               xmlNodePtr cur,
11059                               xmlXPathContextPtr ctxt,
11060                               unsigned int flags)
11061 {
11062     unsigned int port;
11063     g_autofree char *targetType = virXMLPropString(cur, "type");
11064     g_autofree char *targetModel = NULL;
11065     g_autofree char *addrStr = NULL;
11066     g_autofree char *portStr = NULL;
11067     VIR_XPATH_NODE_AUTORESTORE(ctxt)
11068 
11069     ctxt->node = cur;
11070 
11071     if ((def->targetType =
11072          virDomainChrTargetTypeFromString(def->deviceType,
11073                                           targetType)) < 0) {
11074         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11075                        _("unknown target type '%s' specified for character device"),
11076                        targetType);
11077         return -1;
11078     }
11079 
11080     targetModel = virXPathString("string(./model/@name)", ctxt);
11081 
11082     if ((def->targetModel =
11083          virDomainChrTargetModelFromString(def->deviceType,
11084                                            targetModel)) < 0) {
11085         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11086                        _("unknown target model '%s' specified for character device"),
11087                        targetModel);
11088         return -1;
11089     }
11090 
11091     switch (def->deviceType) {
11092     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
11093         switch (def->targetType) {
11094         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
11095             addrStr = virXMLPropString(cur, "address");
11096 
11097             def->target.addr = g_new0(virSocketAddr, 1);
11098 
11099             if (addrStr == NULL) {
11100                 virReportError(VIR_ERR_XML_ERROR, "%s",
11101                                _("guestfwd channel does not "
11102                                  "define a target address"));
11103                 return -1;
11104             }
11105 
11106             if (virSocketAddrParse(def->target.addr, addrStr, AF_UNSPEC) < 0)
11107                 return -1;
11108 
11109             if (def->target.addr->data.stor.ss_family != AF_INET) {
11110                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11111                                "%s", _("guestfwd channel only supports "
11112                                        "IPv4 addresses"));
11113                 return -1;
11114             }
11115 
11116             if (virXMLPropUInt(cur, "port", 10, VIR_XML_PROP_REQUIRED, &port) < 0)
11117                 return -1;
11118 
11119             virSocketAddrSetPort(def->target.addr, port);
11120             break;
11121 
11122         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
11123         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
11124             def->target.name = virXMLPropString(cur, "name");
11125 
11126             if (def->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
11127                 !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
11128 
11129                 if (virXMLPropEnum(cur, "state",
11130                                    virDomainChrDeviceStateTypeFromString,
11131                                    VIR_XML_PROP_NONZERO, &def->state) < 0)
11132                     return -1;
11133             }
11134             break;
11135         }
11136         break;
11137 
11138     default:
11139         portStr = virXMLPropString(cur, "port");
11140         if (portStr == NULL) {
11141             /* Set to negative value to indicate we should set it later */
11142             def->target.port = -1;
11143             break;
11144         }
11145 
11146         if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) {
11147             virReportError(VIR_ERR_XML_ERROR,
11148                            _("Invalid port number: %s"),
11149                            portStr);
11150             return -1;
11151         }
11152         def->target.port = port;
11153         break;
11154     }
11155 
11156     return 0;
11157 }
11158 
11159 typedef enum {
11160     VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT,
11161     VIR_DOMAIN_CHR_SOURCE_MODE_BIND,
11162 } virDomainChrSourceModeType;
11163 
11164 
11165 static int
virDomainChrSourceModeTypeFromString(const char * str)11166 virDomainChrSourceModeTypeFromString(const char *str)
11167 {
11168     if (!str)
11169         return -1;
11170 
11171     if (STREQ(str, "connect"))
11172         return VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT;
11173     if (STREQ(str, "bind"))
11174         return VIR_DOMAIN_CHR_SOURCE_MODE_BIND;
11175 
11176     return -1;
11177 }
11178 
11179 
11180 static int
virDomainChrSourceDefParseTCP(virDomainChrSourceDef * def,xmlNodePtr source,xmlXPathContextPtr ctxt,unsigned int flags)11181 virDomainChrSourceDefParseTCP(virDomainChrSourceDef *def,
11182                               xmlNodePtr source,
11183                               xmlXPathContextPtr ctxt,
11184                               unsigned int flags)
11185 {
11186     virDomainChrSourceModeType mode;
11187 
11188     if (virXMLPropEnumDefault(source, "mode", virDomainChrSourceModeTypeFromString,
11189                               VIR_XML_PROP_NONE, &mode,
11190                               VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT) < 0)
11191         return -1;
11192 
11193     def->data.tcp.listen = mode == VIR_DOMAIN_CHR_SOURCE_MODE_BIND;
11194     def->data.tcp.host = virXMLPropString(source, "host");
11195     def->data.tcp.service = virXMLPropString(source, "service");
11196 
11197     if (virXMLPropTristateBool(source, "tls", VIR_XML_PROP_NONE,
11198                                &def->data.tcp.haveTLS) < 0)
11199         return -1;
11200 
11201     if (flags & VIR_DOMAIN_DEF_PARSE_STATUS) {
11202         int tmpVal;
11203 
11204         if (virXMLPropInt(source, "tlsFromConfig", 10, VIR_XML_PROP_NONE,
11205                           &tmpVal, 0) < 0)
11206             return -1;
11207         def->data.tcp.tlsFromConfig = !!tmpVal;
11208     }
11209 
11210     if (virDomainChrSourceReconnectDefParseXML(&def->data.tcp.reconnect,
11211                                                source,
11212                                                ctxt) < 0) {
11213         return -1;
11214     }
11215 
11216     return 0;
11217 }
11218 
11219 
11220 static int
virDomainChrSourceDefParseUDP(virDomainChrSourceDef * def,xmlNodePtr source)11221 virDomainChrSourceDefParseUDP(virDomainChrSourceDef *def,
11222                               xmlNodePtr source)
11223 {
11224     virDomainChrSourceModeType mode;
11225 
11226     if (virXMLPropEnumDefault(source, "mode", virDomainChrSourceModeTypeFromString,
11227                               VIR_XML_PROP_NONE, &mode,
11228                               VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT) < 0)
11229         return -1;
11230 
11231     if (mode == VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT &&
11232         !def->data.udp.connectHost && !def->data.udp.connectService) {
11233         def->data.udp.connectHost = virXMLPropString(source, "host");
11234         def->data.udp.connectService = virXMLPropString(source, "service");
11235     } else if (mode == VIR_DOMAIN_CHR_SOURCE_MODE_BIND &&
11236                !def->data.udp.bindHost && !def->data.udp.bindService) {
11237         def->data.udp.bindHost = virXMLPropString(source, "host");
11238         def->data.udp.bindService = virXMLPropString(source, "service");
11239     }
11240 
11241     return 0;
11242 }
11243 
11244 
11245 static int
virDomainChrSourceDefParseUnix(virDomainChrSourceDef * def,xmlNodePtr source,xmlXPathContextPtr ctxt)11246 virDomainChrSourceDefParseUnix(virDomainChrSourceDef *def,
11247                                xmlNodePtr source,
11248                                xmlXPathContextPtr ctxt)
11249 {
11250     virDomainChrSourceModeType mode;
11251 
11252     if (virXMLPropEnumDefault(source, "mode", virDomainChrSourceModeTypeFromString,
11253                               VIR_XML_PROP_NONE, &mode,
11254                               VIR_DOMAIN_CHR_SOURCE_MODE_CONNECT) < 0)
11255         return -1;
11256 
11257     def->data.nix.listen = mode == VIR_DOMAIN_CHR_SOURCE_MODE_BIND;
11258     def->data.nix.path = virXMLPropString(source, "path");
11259 
11260     if (virDomainChrSourceReconnectDefParseXML(&def->data.nix.reconnect,
11261                                                source,
11262                                                ctxt) < 0) {
11263         return -1;
11264     }
11265 
11266     return 0;
11267 }
11268 
11269 
11270 static int
virDomainChrSourceDefParseFile(virDomainChrSourceDef * def,xmlNodePtr source)11271 virDomainChrSourceDefParseFile(virDomainChrSourceDef *def,
11272                                xmlNodePtr source)
11273 {
11274     def->data.file.path = virXMLPropString(source, "path");
11275 
11276     if (virXMLPropTristateSwitch(source, "append", VIR_XML_PROP_NONE,
11277                                  &def->data.file.append) < 0)
11278         return -1;
11279 
11280     return 0;
11281 }
11282 
11283 
11284 static int
virDomainChrSourceDefParseProtocol(virDomainChrSourceDef * def,xmlNodePtr protocol)11285 virDomainChrSourceDefParseProtocol(virDomainChrSourceDef *def,
11286                                    xmlNodePtr protocol)
11287 {
11288     g_autofree char *prot = NULL;
11289 
11290     if (def->type != VIR_DOMAIN_CHR_TYPE_TCP)
11291         return 0;
11292 
11293     if ((prot = virXMLPropString(protocol, "type")) &&
11294         (def->data.tcp.protocol =
11295          virDomainChrTcpProtocolTypeFromString(prot)) < 0) {
11296         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11297                        _("Unknown protocol '%s'"), prot);
11298         return -1;
11299     }
11300 
11301     return 0;
11302 }
11303 
11304 
11305 static int
virDomainChrSourceDefParseLog(virDomainChrSourceDef * def,xmlNodePtr log)11306 virDomainChrSourceDefParseLog(virDomainChrSourceDef *def,
11307                               xmlNodePtr log)
11308 {
11309     def->logfile = virXMLPropString(log, "file");
11310 
11311     if (virXMLPropTristateSwitch(log, "append", VIR_XML_PROP_NONE,
11312                                  &def->logappend) < 0)
11313         return -1;
11314 
11315     return 0;
11316 }
11317 
11318 
11319 /* Parse the source half of the XML definition for a character device,
11320  * where node is the first element of node->children of the parent
11321  * element.  def->type must already be valid.
11322  *
11323  * Return -1 on failure, 0 on success. */
11324 static int
virDomainChrSourceDefParseXML(virDomainChrSourceDef * def,xmlNodePtr cur,unsigned int flags,virDomainChrDef * chr_def,xmlXPathContextPtr ctxt)11325 virDomainChrSourceDefParseXML(virDomainChrSourceDef *def,
11326                               xmlNodePtr cur, unsigned int flags,
11327                               virDomainChrDef *chr_def,
11328                               xmlXPathContextPtr ctxt)
11329 {
11330     g_autofree xmlNodePtr *logs = NULL;
11331     int nlogs = 0;
11332     g_autofree xmlNodePtr *protocols = NULL;
11333     int nprotocols = 0;
11334     g_autofree xmlNodePtr *sources = NULL;
11335     int nsources = 0;
11336     VIR_XPATH_NODE_AUTORESTORE(ctxt)
11337 
11338     ctxt->node = cur;
11339 
11340     if ((nsources = virXPathNodeSet("./source", ctxt, &sources)) < 0) {
11341         goto error;
11342     } else if (nsources > 0) {
11343         /* Parse only the first source element since only one is used
11344          * for chardev devices, the only exception is UDP type, where
11345          * user can specify two source elements. */
11346         if (nsources > 1 && def->type != VIR_DOMAIN_CHR_TYPE_UDP) {
11347             virReportError(VIR_ERR_XML_ERROR, "%s",
11348                            _("only one source element is allowed for "
11349                              "character device"));
11350             goto error;
11351         } else if (nsources > 2) {
11352             virReportError(VIR_ERR_XML_ERROR, "%s",
11353                            _("only two source elements are allowed for "
11354                              "character device"));
11355             goto error;
11356         }
11357 
11358         switch ((virDomainChrType) def->type) {
11359         case VIR_DOMAIN_CHR_TYPE_FILE:
11360             if (virDomainChrSourceDefParseFile(def, sources[0]) < 0)
11361                 goto error;
11362             break;
11363 
11364         case VIR_DOMAIN_CHR_TYPE_PTY:
11365             /* PTY path is only parsed from live xml.  */
11366             if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
11367                 def->data.file.path = virXMLPropString(sources[0], "path");
11368             break;
11369 
11370         case VIR_DOMAIN_CHR_TYPE_DEV:
11371         case VIR_DOMAIN_CHR_TYPE_PIPE:
11372             def->data.file.path = virXMLPropString(sources[0], "path");
11373             break;
11374 
11375         case VIR_DOMAIN_CHR_TYPE_UNIX:
11376             if (virDomainChrSourceDefParseUnix(def, sources[0], ctxt) < 0)
11377                 goto error;
11378             break;
11379 
11380         case VIR_DOMAIN_CHR_TYPE_UDP:
11381             if ((virDomainChrSourceDefParseUDP(def, sources[0]) < 0) ||
11382                 (nsources == 2 && virDomainChrSourceDefParseUDP(def, sources[1]) < 0))
11383                 goto error;
11384             break;
11385 
11386         case VIR_DOMAIN_CHR_TYPE_TCP:
11387             if (virDomainChrSourceDefParseTCP(def, sources[0], ctxt, flags) < 0)
11388                 goto error;
11389             break;
11390 
11391         case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
11392             def->data.spiceport.channel = virXMLPropString(sources[0], "channel");
11393             break;
11394 
11395         case VIR_DOMAIN_CHR_TYPE_NMDM:
11396             def->data.nmdm.master = virXMLPropString(sources[0], "master");
11397             def->data.nmdm.slave = virXMLPropString(sources[0], "slave");
11398             break;
11399 
11400         case VIR_DOMAIN_CHR_TYPE_LAST:
11401         case VIR_DOMAIN_CHR_TYPE_NULL:
11402         case VIR_DOMAIN_CHR_TYPE_VC:
11403         case VIR_DOMAIN_CHR_TYPE_STDIO:
11404         case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
11405             break;
11406         }
11407 
11408         /* Check for an optional seclabel override in <source/>. */
11409         if (chr_def) {
11410             xmlNodePtr tmp = ctxt->node;
11411 
11412             ctxt->node = sources[0];
11413             if (virSecurityDeviceLabelDefParseXML(&def->seclabels, &def->nseclabels,
11414                                                   ctxt, flags) < 0) {
11415                 goto error;
11416             }
11417             ctxt->node = tmp;
11418         }
11419     }
11420 
11421     if ((nlogs = virXPathNodeSet("./log", ctxt, &logs)) < 0) {
11422         goto error;
11423     } else if (nlogs == 1) {
11424         if (virDomainChrSourceDefParseLog(def, logs[0]) < 0)
11425             goto error;
11426     } else if (nlogs > 1) {
11427         virReportError(VIR_ERR_XML_ERROR, "%s",
11428                        _("only one log element is allowed for "
11429                          "character device"));
11430         goto error;
11431     }
11432 
11433     if ((nprotocols = virXPathNodeSet("./protocol", ctxt, &protocols)) < 0) {
11434         goto error;
11435     } else if (nprotocols == 1) {
11436         if (virDomainChrSourceDefParseProtocol(def, protocols[0]) < 0)
11437             goto error;
11438     } else if (nprotocols > 1) {
11439         virReportError(VIR_ERR_XML_ERROR, "%s",
11440                        _("only one protocol element is allowed for "
11441                          "character device"));
11442         goto error;
11443     }
11444 
11445     return 0;
11446 
11447  error:
11448     virDomainChrSourceDefClear(def);
11449     return -1;
11450 }
11451 
11452 
11453 static virClass *virDomainChrSourceDefClass;
11454 
11455 static int
virDomainChrSourceDefOnceInit(void)11456 virDomainChrSourceDefOnceInit(void)
11457 {
11458     if (!VIR_CLASS_NEW(virDomainChrSourceDef, virClassForObject()))
11459         return -1;
11460 
11461     return 0;
11462 }
11463 
11464 VIR_ONCE_GLOBAL_INIT(virDomainChrSourceDef);
11465 
11466 virDomainChrSourceDef *
virDomainChrSourceDefNew(virDomainXMLOption * xmlopt)11467 virDomainChrSourceDefNew(virDomainXMLOption *xmlopt)
11468 {
11469     virDomainChrSourceDef *def = NULL;
11470 
11471     if (virDomainChrSourceDefInitialize() < 0)
11472         return NULL;
11473 
11474     if (!(def = virObjectNew(virDomainChrSourceDefClass)))
11475         return NULL;
11476 
11477     if (xmlopt && xmlopt->privateData.chrSourceNew &&
11478         !(def->privateData = xmlopt->privateData.chrSourceNew())) {
11479         virObjectUnref(def);
11480         def = NULL;
11481     }
11482 
11483     return def;
11484 }
11485 
11486 
11487 /* Create a new character device definition and set
11488  * default port.
11489  */
11490 virDomainChrDef *
virDomainChrDefNew(virDomainXMLOption * xmlopt)11491 virDomainChrDefNew(virDomainXMLOption *xmlopt)
11492 {
11493     virDomainChrDef *def = NULL;
11494 
11495     def = g_new0(virDomainChrDef, 1);
11496 
11497     def->target.port = -1;
11498 
11499     if (!(def->source = virDomainChrSourceDefNew(xmlopt)))
11500         VIR_FREE(def);
11501 
11502     return def;
11503 }
11504 
11505 /* Parse the XML definition for a character device
11506  *
11507  * The XML we're dealing with looks like
11508  *
11509  * <serial type="pty">
11510  *   <source path="/dev/pts/3"/>
11511  *   <target port="1"/>
11512  * </serial>
11513  *
11514  * <serial type="dev">
11515  *   <source path="/dev/ttyS0"/>
11516  *   <target port="1"/>
11517  * </serial>
11518  *
11519  * <serial type="tcp">
11520  *   <source mode="connect" host="0.0.0.0" service="2445"/>
11521  *   <target port="1"/>
11522  * </serial>
11523  *
11524  * <serial type="tcp">
11525  *   <source mode="bind" host="0.0.0.0" service="2445"/>
11526  *   <target port="1"/>
11527  *   <protocol type='raw'/>
11528  * </serial>
11529  *
11530  * <serial type="udp">
11531  *   <source mode="bind" host="0.0.0.0" service="2445"/>
11532  *   <source mode="connect" host="0.0.0.0" service="2445"/>
11533  *   <target port="1"/>
11534  * </serial>
11535  *
11536  * <serial type="unix">
11537  *   <source mode="bind" path="/tmp/foo"/>
11538  *   <target port="1"/>
11539  * </serial>
11540  *
11541  * <serial type="nmdm">
11542  *   <source master="/dev/nmdm0A" slave="/dev/nmdm0B"/>
11543  *   <target port="1">
11544  * </serial>
11545  *
11546  */
11547 static virDomainChrDef *
virDomainChrDefParseXML(virDomainXMLOption * xmlopt,xmlXPathContextPtr ctxt,xmlNodePtr node,unsigned int flags)11548 virDomainChrDefParseXML(virDomainXMLOption *xmlopt,
11549                         xmlXPathContextPtr ctxt,
11550                         xmlNodePtr node,
11551                         unsigned int flags)
11552 {
11553     xmlNodePtr target;
11554     const char *nodeName;
11555     virDomainChrDef *def;
11556     g_autofree char *type = NULL;
11557     VIR_XPATH_NODE_AUTORESTORE(ctxt)
11558 
11559     ctxt->node = node;
11560 
11561     if (!(def = virDomainChrDefNew(xmlopt)))
11562         return NULL;
11563 
11564     type = virXMLPropString(node, "type");
11565     if (type == NULL) {
11566         def->source->type = VIR_DOMAIN_CHR_TYPE_PTY;
11567     } else if ((def->source->type = virDomainChrTypeFromString(type)) < 0) {
11568         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11569                        _("unknown type presented to host for character device: %s"),
11570                        type);
11571         goto error;
11572     }
11573 
11574     nodeName = (const char *) node->name;
11575     if ((def->deviceType = virDomainChrDeviceTypeFromString(nodeName)) < 0) {
11576         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11577                        _("unknown character device type: %s"),
11578                        nodeName);
11579         goto error;
11580     }
11581 
11582     if ((target = virXPathNode("./target", ctxt))) {
11583         if (virDomainChrDefParseTargetXML(def, target, ctxt, flags) < 0)
11584             goto error;
11585     } else if ((def->targetType = virDomainChrDefaultTargetType(def->deviceType)) < 0) {
11586         goto error;
11587     }
11588 
11589     if (virDomainChrSourceDefParseXML(def->source, node, flags, def,
11590                                       ctxt) < 0)
11591         goto error;
11592 
11593     if (def->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) {
11594         if (def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
11595             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
11596                            _("spicevmc device type only supports "
11597                              "virtio"));
11598             goto error;
11599         } else {
11600             def->source->data.spicevmc = VIR_DOMAIN_CHR_SPICEVMC_VDAGENT;
11601         }
11602     }
11603 
11604     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
11605         goto error;
11606 
11607     if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
11608         def->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB &&
11609         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
11610         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
11611         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
11612                        _("usb-serial requires address of usb type"));
11613         goto error;
11614     }
11615 
11616     return def;
11617 
11618  error:
11619     virDomainChrDefFree(def);
11620     return NULL;
11621 }
11622 
11623 static virDomainSmartcardDef *
virDomainSmartcardDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)11624 virDomainSmartcardDefParseXML(virDomainXMLOption *xmlopt,
11625                               xmlNodePtr node,
11626                               xmlXPathContextPtr ctxt,
11627                               unsigned int flags)
11628 {
11629     g_autoptr(virDomainSmartcardDef) def = NULL;
11630     g_autofree char *type = NULL;
11631     g_autofree xmlNodePtr *certificates = NULL;
11632     int n = 0;
11633     VIR_XPATH_NODE_AUTORESTORE(ctxt)
11634 
11635     ctxt->node = node;
11636     def = g_new0(virDomainSmartcardDef, 1);
11637 
11638     if (virXMLPropEnum(node, "mode", virDomainSmartcardTypeFromString,
11639                        VIR_XML_PROP_REQUIRED, &def->type) < 0)
11640         return NULL;
11641 
11642     switch (def->type) {
11643     case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
11644         break;
11645 
11646     case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
11647         n = virXPathNodeSet("./certificate", ctxt, &certificates);
11648         if (n != VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES) {
11649             virReportError(VIR_ERR_XML_ERROR, "%s",
11650                            _("host-certificates mode needs "
11651                              "exactly three certificates"));
11652             return NULL;
11653         }
11654 
11655         if (!(def->data.cert.file[0] = virXMLNodeContentString(certificates[0])) ||
11656             !(def->data.cert.file[1] = virXMLNodeContentString(certificates[1])) ||
11657             !(def->data.cert.file[2] = virXMLNodeContentString(certificates[2])))
11658             return NULL;
11659 
11660         if (virXPathNode("./database", ctxt) &&
11661             !def->data.cert.database) {
11662             if (!(def->data.cert.database =
11663                   virXPathString("string(./database/text())", ctxt)))
11664                 return NULL;
11665 
11666             if (*def->data.cert.database != '/') {
11667                 virReportError(VIR_ERR_XML_ERROR,
11668                                _("expecting absolute path: %s"),
11669                                def->data.cert.database);
11670                 return NULL;
11671             }
11672         }
11673         break;
11674 
11675     case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
11676         type = virXMLPropString(node, "type");
11677         if (type == NULL) {
11678             virReportError(VIR_ERR_XML_ERROR, "%s",
11679                            _("passthrough mode requires a character "
11680                              "device type attribute"));
11681             return NULL;
11682         }
11683 
11684         if (!(def->data.passthru = virDomainChrSourceDefNew(xmlopt)))
11685             return NULL;
11686 
11687         if ((def->data.passthru->type = virDomainChrTypeFromString(type)) < 0) {
11688             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11689                            _("unknown type presented to host for "
11690                              "character device: %s"), type);
11691             return NULL;
11692         }
11693 
11694         if (virDomainChrSourceDefParseXML(def->data.passthru, node, flags,
11695                                           NULL, ctxt) < 0)
11696             return NULL;
11697 
11698         if (def->data.passthru->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) {
11699             def->data.passthru->data.spicevmc
11700                 = VIR_DOMAIN_CHR_SPICEVMC_SMARTCARD;
11701         }
11702 
11703         break;
11704 
11705     case VIR_DOMAIN_SMARTCARD_TYPE_LAST:
11706     default:
11707         virReportEnumRangeError(virDomainSmartcardType, def->type);
11708         return NULL;
11709     }
11710 
11711     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
11712         return NULL;
11713 
11714     return g_steal_pointer(&def);
11715 }
11716 
11717 /* Parse the XML definition for a TPM device
11718  *
11719  * The XML looks like this:
11720  *
11721  * <tpm model='tpm-tis'>
11722  *   <backend type='passthrough'>
11723  *     <device path='/dev/tpm0'/>
11724  *   </backend>
11725  * </tpm>
11726  *
11727  * or like this:
11728  *
11729  * <tpm model='tpm-tis'>
11730  *   <backend type='emulator' version='2.0'/>
11731  * </tpm>
11732  *
11733  * Emulator state encryption is supported with the following:
11734  *
11735  * <tpm model='tpm-tis'>
11736  *   <backend type='emulator' version='2.0'>
11737  *     <encryption secret='32ee7e76-2178-47a1-ab7b-269e6e348015'/>
11738  *     <active_pcr_banks>
11739  *       <sha256/>
11740  *       <sha384/>
11741  *     </active_pcr_banks>
11742  *   </backend>
11743  * </tpm>
11744  *
11745  * Emulator persistent_state is supported with the following:
11746  *
11747  * <tpm model='tpm-tis'>
11748  *   <backend type='emulator' version='2.0' persistent_state='yes'>
11749  * </tpm>
11750  */
11751 static virDomainTPMDef *
virDomainTPMDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)11752 virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
11753                         xmlNodePtr node,
11754                         xmlXPathContextPtr ctxt,
11755                         unsigned int flags)
11756 {
11757     virDomainTPMDef *def;
11758     VIR_XPATH_NODE_AUTORESTORE(ctxt)
11759     int nbackends;
11760     int nnodes;
11761     size_t i;
11762     g_autofree char *path = NULL;
11763     g_autofree char *model = NULL;
11764     g_autofree char *backend = NULL;
11765     g_autofree char *version = NULL;
11766     g_autofree char *secretuuid = NULL;
11767     g_autofree char *persistent_state = NULL;
11768     g_autofree xmlNodePtr *backends = NULL;
11769     g_autofree xmlNodePtr *nodes = NULL;
11770     int bank;
11771 
11772     def = g_new0(virDomainTPMDef, 1);
11773 
11774     model = virXMLPropString(node, "model");
11775     if (model != NULL &&
11776         (def->model = virDomainTPMModelTypeFromString(model)) < 0) {
11777         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11778                        _("Unknown TPM frontend model '%s'"), model);
11779         goto error;
11780     }
11781 
11782     ctxt->node = node;
11783 
11784     if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) < 0)
11785         goto error;
11786 
11787     if (nbackends > 1) {
11788         virReportError(VIR_ERR_XML_ERROR, "%s",
11789                        _("only one TPM backend is supported"));
11790         goto error;
11791     }
11792 
11793     if (nbackends == 0) {
11794         virReportError(VIR_ERR_XML_ERROR, "%s",
11795                        _("missing TPM device backend"));
11796         goto error;
11797     }
11798 
11799     if (!(backend = virXMLPropString(backends[0], "type"))) {
11800         virReportError(VIR_ERR_XML_ERROR, "%s",
11801                        _("missing TPM device backend type"));
11802         goto error;
11803     }
11804 
11805     if ((def->type = virDomainTPMBackendTypeFromString(backend)) < 0) {
11806         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11807                        _("Unknown TPM backend type '%s'"),
11808                        backend);
11809         goto error;
11810     }
11811 
11812     version = virXMLPropString(backends[0], "version");
11813     if (!version) {
11814         def->version = VIR_DOMAIN_TPM_VERSION_DEFAULT;
11815     } else {
11816         if ((def->version = virDomainTPMVersionTypeFromString(version)) < 0) {
11817             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11818                            _("Unsupported TPM version '%s'"),
11819                            version);
11820             goto error;
11821         }
11822     }
11823 
11824     switch (def->type) {
11825     case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
11826         if (!(def->data.passthrough.source = virDomainChrSourceDefNew(xmlopt)))
11827             goto error;
11828         path = virXPathString("string(./backend/device/@path)", ctxt);
11829         if (!path)
11830             path = g_strdup(VIR_DOMAIN_TPM_DEFAULT_DEVICE);
11831         def->data.passthrough.source->type = VIR_DOMAIN_CHR_TYPE_DEV;
11832         def->data.passthrough.source->data.file.path = g_steal_pointer(&path);
11833         break;
11834     case VIR_DOMAIN_TPM_TYPE_EMULATOR:
11835         if (!(def->data.emulator.source = virDomainChrSourceDefNew(xmlopt)))
11836             goto error;
11837         secretuuid = virXPathString("string(./backend/encryption/@secret)", ctxt);
11838         if (secretuuid) {
11839             if (virUUIDParse(secretuuid, def->data.emulator.secretuuid) < 0) {
11840                 virReportError(VIR_ERR_INTERNAL_ERROR,
11841                                _("Unable to parse secret uuid '%s'"), secretuuid);
11842                 goto error;
11843             }
11844             def->data.emulator.hassecretuuid = true;
11845         }
11846 
11847         persistent_state = virXMLPropString(backends[0], "persistent_state");
11848         if (persistent_state) {
11849             if (virStringParseYesNo(persistent_state,
11850                                     &def->data.emulator.persistent_state) < 0) {
11851                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
11852                                _("Invalid persistent_state value, either 'yes' or 'no'"));
11853                 goto error;
11854             }
11855         }
11856         if (def->version == VIR_DOMAIN_TPM_VERSION_2_0) {
11857             if ((nnodes = virXPathNodeSet("./backend/active_pcr_banks/*", ctxt, &nodes)) < 0)
11858                 break;
11859             for (i = 0; i < nnodes; i++) {
11860                 if ((bank = virDomainTPMPcrBankTypeFromString((const char *)nodes[i]->name)) < 0) {
11861                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11862                                    _("Unsupported PCR banks '%s'"),
11863                                    nodes[i]->name);
11864                     goto error;
11865                 }
11866                 def->data.emulator.activePcrBanks |= (1 << bank);
11867             }
11868         }
11869         break;
11870     case VIR_DOMAIN_TPM_TYPE_LAST:
11871         goto error;
11872     }
11873 
11874     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
11875         goto error;
11876 
11877     return def;
11878 
11879  error:
11880     virDomainTPMDefFree(def);
11881     return NULL;
11882 }
11883 
11884 static virDomainPanicDef *
virDomainPanicDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)11885 virDomainPanicDefParseXML(virDomainXMLOption *xmlopt,
11886                           xmlNodePtr node,
11887                           xmlXPathContextPtr ctxt,
11888                           unsigned int flags)
11889 {
11890     virDomainPanicDef *panic;
11891     g_autofree char *model = NULL;
11892 
11893     panic = g_new0(virDomainPanicDef, 1);
11894 
11895     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
11896                                     &panic->info, flags) < 0)
11897         goto error;
11898 
11899     model = virXMLPropString(node, "model");
11900     if (model != NULL &&
11901         (panic->model = virDomainPanicModelTypeFromString(model)) < 0) {
11902         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11903                        _("unknown panic model '%s'"), model);
11904         goto error;
11905     }
11906 
11907     return panic;
11908 
11909  error:
11910     virDomainPanicDefFree(panic);
11911     return NULL;
11912 }
11913 
11914 /* Parse the XML definition for an input device */
11915 static virDomainInputDef *
virDomainInputDefParseXML(virDomainXMLOption * xmlopt,const virDomainDef * dom,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)11916 virDomainInputDefParseXML(virDomainXMLOption *xmlopt,
11917                           const virDomainDef *dom,
11918                           xmlNodePtr node,
11919                           xmlXPathContextPtr ctxt,
11920                           unsigned int flags)
11921 {
11922     VIR_XPATH_NODE_AUTORESTORE(ctxt)
11923     virDomainInputDef *def;
11924     g_autofree char *type = NULL;
11925     g_autofree char *bus = NULL;
11926     g_autofree char *model = NULL;
11927     xmlNodePtr source = NULL;
11928 
11929     def = g_new0(virDomainInputDef, 1);
11930 
11931     ctxt->node = node;
11932 
11933     type = virXMLPropString(node, "type");
11934     bus = virXMLPropString(node, "bus");
11935     model = virXMLPropString(node, "model");
11936 
11937     if (!type) {
11938         virReportError(VIR_ERR_INTERNAL_ERROR,
11939                        "%s", _("missing input device type"));
11940         goto error;
11941     }
11942 
11943     if ((def->type = virDomainInputTypeFromString(type)) < 0) {
11944         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11945                        _("unknown input device type '%s'"), type);
11946         goto error;
11947     }
11948 
11949     if (model &&
11950         ((def->model = virDomainInputModelTypeFromString(model)) < 0 ||
11951          def->model == VIR_DOMAIN_INPUT_MODEL_DEFAULT)) {
11952         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11953                        _("unknown input model '%s'"), model);
11954         goto error;
11955     }
11956 
11957     if (bus) {
11958         if ((def->bus = virDomainInputBusTypeFromString(bus)) < 0) {
11959             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
11960                            _("unknown input bus type '%s'"), bus);
11961             goto error;
11962         }
11963 
11964         if (dom->os.type == VIR_DOMAIN_OSTYPE_HVM) {
11965             if (def->bus == VIR_DOMAIN_INPUT_BUS_PS2 &&
11966                 def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
11967                 def->type != VIR_DOMAIN_INPUT_TYPE_KBD) {
11968                 virReportError(VIR_ERR_INTERNAL_ERROR,
11969                                _("ps2 bus does not support %s input device"),
11970                                type);
11971                 goto error;
11972             }
11973             if (def->bus == VIR_DOMAIN_INPUT_BUS_XEN) {
11974                 virReportError(VIR_ERR_INTERNAL_ERROR,
11975                                _("unsupported input bus %s"),
11976                                bus);
11977                 goto error;
11978             }
11979         } else if (dom->os.type == VIR_DOMAIN_OSTYPE_XEN ||
11980                    dom->os.type == VIR_DOMAIN_OSTYPE_XENPVH) {
11981             if (def->bus != VIR_DOMAIN_INPUT_BUS_XEN) {
11982                 virReportError(VIR_ERR_INTERNAL_ERROR,
11983                                _("unsupported input bus %s"),
11984                                bus);
11985                 goto error;
11986             }
11987             if (def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
11988                 def->type != VIR_DOMAIN_INPUT_TYPE_KBD) {
11989                 virReportError(VIR_ERR_INTERNAL_ERROR,
11990                                _("xen bus does not support %s input device"),
11991                                type);
11992                 goto error;
11993             }
11994         } else {
11995             if (dom->virtType == VIR_DOMAIN_VIRT_VZ ||
11996                 dom->virtType == VIR_DOMAIN_VIRT_PARALLELS) {
11997                 if (def->bus != VIR_DOMAIN_INPUT_BUS_PARALLELS) {
11998                     virReportError(VIR_ERR_INTERNAL_ERROR,
11999                                    _("parallels containers don't support "
12000                                      "input bus %s"),
12001                                    bus);
12002                     goto error;
12003                 }
12004 
12005                 if (def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE &&
12006                     def->type != VIR_DOMAIN_INPUT_TYPE_KBD) {
12007                     virReportError(VIR_ERR_INTERNAL_ERROR,
12008                                    _("parallels bus does not support "
12009                                      "%s input device"),
12010                                    type);
12011                     goto error;
12012                 }
12013             } else {
12014                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
12015                                _("Input devices are not supported by this "
12016                                  "virtualization driver."));
12017                 goto error;
12018             }
12019         }
12020     } else {
12021         if (dom->os.type == VIR_DOMAIN_OSTYPE_HVM) {
12022             if ((def->type == VIR_DOMAIN_INPUT_TYPE_MOUSE ||
12023                 def->type == VIR_DOMAIN_INPUT_TYPE_KBD) &&
12024                 (ARCH_IS_X86(dom->os.arch) || dom->os.arch == VIR_ARCH_NONE)) {
12025                 def->bus = VIR_DOMAIN_INPUT_BUS_PS2;
12026             } else if (ARCH_IS_S390(dom->os.arch) ||
12027                        def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH) {
12028                 def->bus = VIR_DOMAIN_INPUT_BUS_VIRTIO;
12029             } else if (def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) {
12030                 def->bus = VIR_DOMAIN_INPUT_BUS_NONE;
12031             } else {
12032                 def->bus = VIR_DOMAIN_INPUT_BUS_USB;
12033             }
12034         } else if (dom->os.type == VIR_DOMAIN_OSTYPE_XEN ||
12035                    dom->os.type == VIR_DOMAIN_OSTYPE_XENPVH) {
12036             def->bus = VIR_DOMAIN_INPUT_BUS_XEN;
12037         } else {
12038             if ((dom->virtType == VIR_DOMAIN_VIRT_VZ ||
12039                  dom->virtType == VIR_DOMAIN_VIRT_PARALLELS))
12040                 def->bus = VIR_DOMAIN_INPUT_BUS_PARALLELS;
12041         }
12042     }
12043 
12044     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
12045         goto error;
12046 
12047     if (def->bus == VIR_DOMAIN_INPUT_BUS_USB &&
12048         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
12049         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
12050         virReportError(VIR_ERR_XML_ERROR, "%s",
12051                        _("Invalid address for a USB device"));
12052         goto error;
12053     }
12054 
12055     if ((source = virXPathNode("./source", ctxt))) {
12056         g_autofree char *evdev = NULL;
12057 
12058         if (def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH)
12059             evdev = virXMLPropString(source, "evdev");
12060         else if (def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV)
12061             evdev = virXMLPropString(source, "dev");
12062 
12063         if (evdev)
12064             def->source.evdev = virFileSanitizePath(evdev);
12065 
12066         if (def->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH ||
12067             def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) {
12068             if (!def->source.evdev) {
12069                 virReportError(VIR_ERR_XML_ERROR, "%s",
12070                                _("Missing evdev path for input device"));
12071                 goto error;
12072             }
12073         }
12074 
12075         if (def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV) {
12076             if (virXMLPropEnum(source, "grab",
12077                                virDomainInputSourceGrabTypeFromString,
12078                                VIR_XML_PROP_NONZERO, &def->source.grab) < 0)
12079                 goto error;
12080 
12081             if (virXMLPropEnum(source, "grabToggle",
12082                                virDomainInputSourceGrabToggleTypeFromString,
12083                                VIR_XML_PROP_NONZERO, &def->source.grabToggle) < 0)
12084                 goto error;
12085 
12086             if (virXMLPropTristateSwitch(source, "repeat",
12087                                          VIR_XML_PROP_NONE, &def->source.repeat) < 0)
12088                 goto error;
12089         }
12090     }
12091 
12092     if (virDomainVirtioOptionsParseXML(virXPathNode("./driver", ctxt),
12093                                        &def->virtio) < 0)
12094         goto error;
12095 
12096     return def;
12097 
12098  error:
12099     virDomainInputDefFree(def);
12100     return NULL;
12101 }
12102 
12103 
12104 /* Parse the XML definition for a hub device */
12105 static virDomainHubDef *
virDomainHubDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)12106 virDomainHubDefParseXML(virDomainXMLOption *xmlopt,
12107                         xmlNodePtr node,
12108                         xmlXPathContextPtr ctxt,
12109                         unsigned int flags)
12110 {
12111     virDomainHubDef *def;
12112     g_autofree char *type = NULL;
12113 
12114     def = g_new0(virDomainHubDef, 1);
12115 
12116     type = virXMLPropString(node, "type");
12117 
12118     if (!type) {
12119         virReportError(VIR_ERR_INTERNAL_ERROR,
12120                        "%s", _("missing hub device type"));
12121         goto error;
12122     }
12123 
12124     if ((def->type = virDomainHubTypeFromString(type)) < 0) {
12125         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12126                        _("unknown hub device type '%s'"), type);
12127         goto error;
12128     }
12129 
12130     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
12131         goto error;
12132 
12133     return def;
12134 
12135  error:
12136     virDomainHubDefFree(def);
12137     return NULL;
12138 }
12139 
12140 
12141 /* Parse the XML definition for a clock timer */
12142 static virDomainTimerDef *
virDomainTimerDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt)12143 virDomainTimerDefParseXML(xmlNodePtr node,
12144                           xmlXPathContextPtr ctxt)
12145 {
12146     virDomainTimerDef *def;
12147     VIR_XPATH_NODE_AUTORESTORE(ctxt)
12148     xmlNodePtr catchup;
12149     int ret;
12150     g_autofree char *name = NULL;
12151     g_autofree char *present = NULL;
12152     g_autofree char *tickpolicy = NULL;
12153     g_autofree char *track = NULL;
12154     g_autofree char *mode = NULL;
12155 
12156     def = g_new0(virDomainTimerDef, 1);
12157 
12158     ctxt->node = node;
12159 
12160     name = virXMLPropString(node, "name");
12161     if (name == NULL) {
12162         virReportError(VIR_ERR_INTERNAL_ERROR,
12163                        "%s", _("missing timer name"));
12164         goto error;
12165     }
12166     if ((def->name = virDomainTimerNameTypeFromString(name)) < 0) {
12167         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12168                        _("unknown timer name '%s'"), name);
12169         goto error;
12170     }
12171 
12172     def->present = -1; /* unspecified */
12173     if ((present = virXMLPropString(node, "present")) != NULL) {
12174         bool state = false;
12175         if (virStringParseYesNo(present, &state) < 0) {
12176             virReportError(VIR_ERR_INTERNAL_ERROR,
12177                            _("unknown timer present value '%s'"), present);
12178             goto error;
12179         }
12180         def->present = state ? 1 : 0;
12181     }
12182 
12183     def->tickpolicy = -1;
12184     tickpolicy = virXMLPropString(node, "tickpolicy");
12185     if (tickpolicy != NULL) {
12186         if ((def->tickpolicy = virDomainTimerTickpolicyTypeFromString(tickpolicy)) < 0) {
12187             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12188                            _("unknown timer tickpolicy '%s'"), tickpolicy);
12189             goto error;
12190         }
12191     }
12192 
12193     def->track = -1;
12194     track = virXMLPropString(node, "track");
12195     if (track != NULL) {
12196         if ((def->track = virDomainTimerTrackTypeFromString(track)) < 0) {
12197             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12198                            _("unknown timer track '%s'"), track);
12199             goto error;
12200         }
12201     }
12202 
12203     ret = virXPathULongLong("string(./@frequency)", ctxt, &def->frequency);
12204     if (ret == -1) {
12205         def->frequency = 0;
12206     } else if (ret < 0) {
12207         virReportError(VIR_ERR_INTERNAL_ERROR,
12208                        "%s", _("invalid timer frequency"));
12209         goto error;
12210     }
12211 
12212     def->mode = -1;
12213     mode = virXMLPropString(node, "mode");
12214     if (mode != NULL) {
12215         if ((def->mode = virDomainTimerModeTypeFromString(mode)) < 0) {
12216             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12217                            _("unknown timer mode '%s'"), mode);
12218             goto error;
12219         }
12220     }
12221 
12222     catchup = virXPathNode("./catchup", ctxt);
12223     if (catchup != NULL) {
12224         ret = virXPathULong("string(./catchup/@threshold)", ctxt,
12225                             &def->catchup.threshold);
12226         if (ret == -1) {
12227             def->catchup.threshold = 0;
12228         } else if (ret < 0) {
12229             virReportError(VIR_ERR_INTERNAL_ERROR,
12230                            "%s", _("invalid catchup threshold"));
12231             goto error;
12232         }
12233 
12234         ret = virXPathULong("string(./catchup/@slew)", ctxt, &def->catchup.slew);
12235         if (ret == -1) {
12236             def->catchup.slew = 0;
12237         } else if (ret < 0) {
12238             virReportError(VIR_ERR_INTERNAL_ERROR,
12239                            "%s", _("invalid catchup slew"));
12240             goto error;
12241         }
12242 
12243         ret = virXPathULong("string(./catchup/@limit)", ctxt, &def->catchup.limit);
12244         if (ret == -1) {
12245             def->catchup.limit = 0;
12246         } else if (ret < 0) {
12247             virReportError(VIR_ERR_INTERNAL_ERROR,
12248                            "%s", _("invalid catchup limit"));
12249             goto error;
12250         }
12251     }
12252 
12253     return def;
12254 
12255  error:
12256     VIR_FREE(def);
12257     return def;
12258 }
12259 
12260 
12261 static int
virDomainGraphicsAuthDefParseXML(xmlNodePtr node,virDomainGraphicsAuthDef * def,int type)12262 virDomainGraphicsAuthDefParseXML(xmlNodePtr node,
12263                                  virDomainGraphicsAuthDef *def,
12264                                  int type)
12265 {
12266     g_autofree char *validTo = NULL;
12267     g_autofree char *connected = virXMLPropString(node, "connected");
12268 
12269     def->passwd = virXMLPropString(node, "passwd");
12270 
12271     if (!def->passwd)
12272         return 0;
12273 
12274     validTo = virXMLPropString(node, "passwdValidTo");
12275     if (validTo) {
12276         g_autoptr(GDateTime) then = NULL;
12277         g_autoptr(GTimeZone) tz = g_time_zone_new_utc();
12278         char *tmp;
12279         int year, mon, mday, hour, min, sec;
12280 
12281         /* Expect: YYYY-MM-DDTHH:MM:SS (%d-%d-%dT%d:%d:%d)  eg 2010-11-28T14:29:01 */
12282         if (/* year */
12283             virStrToLong_i(validTo, &tmp, 10, &year) < 0 || *tmp != '-' ||
12284             /* month */
12285             virStrToLong_i(tmp+1, &tmp, 10, &mon) < 0 || *tmp != '-' ||
12286             /* day */
12287             virStrToLong_i(tmp+1, &tmp, 10, &mday) < 0 || *tmp != 'T' ||
12288             /* hour */
12289             virStrToLong_i(tmp+1, &tmp, 10, &hour) < 0 || *tmp != ':' ||
12290             /* minute */
12291             virStrToLong_i(tmp+1, &tmp, 10, &min) < 0 || *tmp != ':' ||
12292             /* second */
12293             virStrToLong_i(tmp+1, &tmp, 10, &sec) < 0 || *tmp != '\0') {
12294             virReportError(VIR_ERR_INTERNAL_ERROR,
12295                            _("cannot parse password validity time '%s', expect YYYY-MM-DDTHH:MM:SS"),
12296                            validTo);
12297             VIR_FREE(def->passwd);
12298             return -1;
12299         }
12300 
12301         then = g_date_time_new(tz, year, mon, mday, hour, min, sec);
12302         def->validTo = (time_t)g_date_time_to_unix(then);
12303         def->expires = true;
12304     }
12305 
12306     if (connected) {
12307         int action = virDomainGraphicsAuthConnectedTypeFromString(connected);
12308         if (action <= 0) {
12309             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12310                            _("unknown connected value %s"),
12311                            connected);
12312             return -1;
12313         }
12314 
12315         /* VNC supports connected='keep' only */
12316         if (type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
12317             action != VIR_DOMAIN_GRAPHICS_AUTH_CONNECTED_KEEP) {
12318             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
12319                            _("VNC supports connected='keep' only"));
12320             return -1;
12321         }
12322 
12323         def->connected = action;
12324     }
12325 
12326     return 0;
12327 }
12328 
12329 
12330 /**
12331  * virDomainGraphicsListenDefParseXML:
12332  * @def: listen def pointer to be filled
12333  * @graphics: graphics def pointer
12334  * @node: xml node of <listen/> element
12335  * @parent: xml node of <graphics/> element
12336  * @flags: bit-wise or of VIR_DOMAIN_DEF_PARSE_*
12337  *
12338  * Parses current <listen/> element from @node to @def.  For backward
12339  * compatibility the @parent element should contain node of <graphics/> element
12340  * for the first <listen/> element in order to validate attributes from both
12341  * elements.
12342  */
12343 static int
virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDef * def,virDomainGraphicsDef * graphics,xmlNodePtr node,xmlNodePtr parent,unsigned int flags)12344 virDomainGraphicsListenDefParseXML(virDomainGraphicsListenDef *def,
12345                                    virDomainGraphicsDef *graphics,
12346                                    xmlNodePtr node,
12347                                    xmlNodePtr parent,
12348                                    unsigned int flags)
12349 {
12350     int ret = -1;
12351     const char *graphicsType = virDomainGraphicsTypeToString(graphics->type);
12352     g_autofree char *address = virXMLPropString(node, "address");
12353     g_autofree char *network = virXMLPropString(node, "network");
12354     g_autofree char *socketPath = virXMLPropString(node, "socket");
12355     g_autofree char *autoGenerated = virXMLPropString(node, "autoGenerated");
12356     g_autofree char *addressCompat = NULL;
12357     g_autofree char *socketCompat = NULL;
12358 
12359     if (parent) {
12360         addressCompat = virXMLPropString(parent, "listen");
12361         socketCompat = virXMLPropString(parent, "socket");
12362     }
12363 
12364     if (virXMLPropEnum(node, "type", virDomainGraphicsListenTypeFromString,
12365                        VIR_XML_PROP_REQUIRED, &def->type) < 0)
12366         goto error;
12367 
12368     switch (def->type) {
12369     case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
12370         if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
12371             graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
12372             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12373                            _("listen type 'socket' is not available for "
12374                              "graphics type '%s'"), graphicsType);
12375             goto error;
12376         }
12377         break;
12378     case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
12379         if (graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
12380             graphics->type != VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
12381             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12382                            _("listen type 'none' is not available for "
12383                              "graphics type '%s'"), graphicsType);
12384             goto error;
12385         }
12386         break;
12387     case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
12388     case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
12389     case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
12390         break;
12391     }
12392 
12393     if (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS) {
12394         if (address && addressCompat && STRNEQ(address, addressCompat)) {
12395             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12396                            _("graphics 'listen' attribute '%s' must match "
12397                              "'address' attribute of first listen element "
12398                              "(found '%s')"), addressCompat, address);
12399             goto error;
12400         }
12401 
12402         if (!address)
12403             address = g_steal_pointer(&addressCompat);
12404     }
12405 
12406     if (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET) {
12407         if (socketPath && socketCompat && STRNEQ(socketPath, socketCompat)) {
12408             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12409                            _("graphics 'socket' attribute '%s' must match "
12410                              "'socket' attribute of first listen element "
12411                              "(found '%s')"), socketCompat, socketPath);
12412             goto error;
12413         }
12414 
12415         if (!socketPath)
12416             socketPath = g_steal_pointer(&socketCompat);
12417     }
12418 
12419     if (address && address[0] &&
12420         (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS ||
12421          (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK &&
12422           !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)))) {
12423         def->address = g_steal_pointer(&address);
12424     }
12425 
12426     if (network && network[0]) {
12427         if (def->type != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK) {
12428             virReportError(VIR_ERR_XML_ERROR, "%s",
12429                            _("'network' attribute is valid only for listen "
12430                              "type 'network'"));
12431             goto error;
12432         }
12433         def->network = g_steal_pointer(&network);
12434     }
12435 
12436     if (socketPath && socketPath[0]) {
12437         if (def->type != VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET) {
12438             virReportError(VIR_ERR_XML_ERROR, "%s",
12439                            _("'socket' attribute is valid only for listen "
12440                              "type 'socket'"));
12441             goto error;
12442         }
12443         def->socket = g_steal_pointer(&socketPath);
12444     }
12445 
12446     if (flags & VIR_DOMAIN_DEF_PARSE_STATUS) {
12447         int tmp;
12448         if (virXMLPropInt(node, "fromConfig", 10, VIR_XML_PROP_NONE, &tmp, 0) < 0)
12449             return -1;
12450         def->fromConfig = tmp != 0;
12451     }
12452 
12453     if (autoGenerated &&
12454         flags & VIR_DOMAIN_DEF_PARSE_STATUS) {
12455         if (virStringParseYesNo(autoGenerated, &def->autoGenerated) < 0) {
12456             virReportError(VIR_ERR_XML_ERROR,
12457                            _("Invalid autoGenerated value: %s"),
12458                            autoGenerated);
12459             goto error;
12460         }
12461     }
12462 
12463     ret = 0;
12464  error:
12465     if (ret < 0)
12466         virDomainGraphicsListenDefClear(def);
12467     return ret;
12468 }
12469 
12470 
12471 static int
virDomainGraphicsListensParseXML(virDomainGraphicsDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)12472 virDomainGraphicsListensParseXML(virDomainGraphicsDef *def,
12473                                  xmlNodePtr node,
12474                                  xmlXPathContextPtr ctxt,
12475                                  unsigned int flags)
12476 {
12477     VIR_XPATH_NODE_AUTORESTORE(ctxt)
12478     virDomainGraphicsListenDef newListen = {0};
12479     int nListens;
12480     int ret = -1;
12481     g_autofree xmlNodePtr *listenNodes = NULL;
12482     g_autofree char *socketPath = NULL;
12483 
12484     ctxt->node = node;
12485 
12486     /* parse the <listen> subelements for graphics types that support it */
12487     nListens = virXPathNodeSet("./listen", ctxt, &listenNodes);
12488     if (nListens < 0)
12489         goto cleanup;
12490 
12491     if (nListens > 0) {
12492         size_t i;
12493 
12494         def->listens = g_new0(virDomainGraphicsListenDef, nListens);
12495 
12496         for (i = 0; i < nListens; i++) {
12497             if (virDomainGraphicsListenDefParseXML(&def->listens[i], def,
12498                                                    listenNodes[i],
12499                                                    i == 0 ? node : NULL,
12500                                                    flags) < 0)
12501                 goto cleanup;
12502 
12503             def->nListens++;
12504         }
12505     }
12506 
12507     /* If no <listen/> element was found in XML for backward compatibility
12508      * we should try to parse 'listen' or 'socket' attribute from <graphics/>
12509      * element. */
12510     if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC)
12511         socketPath = virXMLPropString(node, "socket");
12512 
12513     if (socketPath) {
12514         newListen.type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET;
12515         newListen.socket = g_steal_pointer(&socketPath);
12516     } else {
12517         newListen.type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
12518         newListen.address = virXMLPropString(node, "listen");
12519         if (STREQ_NULLABLE(newListen.address, ""))
12520             VIR_FREE(newListen.address);
12521     }
12522 
12523     /* If no <listen/> element was found add a new one created by parsing
12524      * <graphics/> element. */
12525     if (def->nListens == 0) {
12526         VIR_APPEND_ELEMENT(def->listens, def->nListens, newListen);
12527     } else {
12528         virDomainGraphicsListenDef *glisten = &def->listens[0];
12529 
12530         /* If the first <listen/> element is 'address' or 'network' and we found
12531          * 'socket' attribute inside <graphics/> element for backward
12532          * compatibility we need to replace the first listen by
12533          * <listen type='socket' .../> element based on the 'socket' attribute. */
12534         if ((glisten->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS ||
12535              glisten->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK) &&
12536             newListen.type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET) {
12537             virDomainGraphicsListenDefClear(glisten);
12538             *glisten = newListen;
12539             memset(&newListen, 0, sizeof(newListen));
12540         }
12541     }
12542 
12543     ret = 0;
12544  cleanup:
12545     virDomainGraphicsListenDefClear(&newListen);
12546     return ret;
12547 }
12548 
12549 
12550 static int
virDomainGraphicsDefParseXMLVNC(virDomainGraphicsDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)12551 virDomainGraphicsDefParseXMLVNC(virDomainGraphicsDef *def,
12552                                 xmlNodePtr node,
12553                                 xmlXPathContextPtr ctxt,
12554                                 unsigned int flags)
12555 {
12556     g_autofree char *port = virXMLPropString(node, "port");
12557     g_autofree char *websocketGenerated = virXMLPropString(node, "websocketGenerated");
12558     g_autofree char *autoport = virXMLPropString(node, "autoport");
12559     xmlNodePtr audioNode;
12560     VIR_XPATH_NODE_AUTORESTORE(ctxt)
12561 
12562     if (virDomainGraphicsListensParseXML(def, node, ctxt, flags) < 0)
12563         return -1;
12564 
12565     if (port) {
12566         if (virStrToLong_i(port, NULL, 10, &def->data.vnc.port) < 0) {
12567             virReportError(VIR_ERR_INTERNAL_ERROR,
12568                            _("cannot parse vnc port %s"), port);
12569             return -1;
12570         }
12571         /* Legacy compat syntax, used -1 for auto-port */
12572         if (def->data.vnc.port == -1) {
12573             if (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)
12574                 def->data.vnc.port = 0;
12575             def->data.vnc.autoport = true;
12576         }
12577     } else {
12578         def->data.vnc.port = 0;
12579         def->data.vnc.autoport = true;
12580     }
12581 
12582     if (autoport) {
12583         ignore_value(virStringParseYesNo(autoport, &def->data.vnc.autoport));
12584 
12585         if (def->data.vnc.autoport && flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)
12586             def->data.vnc.port = 0;
12587     }
12588 
12589     if (virXMLPropInt(node, "websocket", 10, VIR_XML_PROP_NONE,
12590                       &def->data.vnc.websocket, 0) < 0)
12591         return -1;
12592 
12593     if (websocketGenerated)
12594         ignore_value(virStringParseYesNo(websocketGenerated,
12595                      &def->data.vnc.websocketGenerated));
12596 
12597     if (virXMLPropEnum(node, "sharePolicy",
12598                        virDomainGraphicsVNCSharePolicyTypeFromString,
12599                        VIR_XML_PROP_NONE, &def->data.vnc.sharePolicy) < 0)
12600         return -1;
12601 
12602     if ((virXMLPropTristateBool(node, "powerControl", VIR_XML_PROP_NONE,
12603                                 &def->data.vnc.powerControl)) < 0)
12604         return -1;
12605 
12606     def->data.vnc.keymap = virXMLPropString(node, "keymap");
12607 
12608     ctxt->node = node;
12609     audioNode = virXPathNode("./audio", ctxt);
12610     if (audioNode) {
12611         if (virXMLPropUInt(audioNode, "id", 10,
12612                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
12613                            &def->data.vnc.audioId) < 0)
12614             return -1;
12615     }
12616 
12617     if (virDomainGraphicsAuthDefParseXML(node, &def->data.vnc.auth,
12618                                          def->type) < 0)
12619         return -1;
12620 
12621     return 0;
12622 }
12623 
12624 
12625 static int
virDomainGraphicsDefParseXMLSDL(virDomainGraphicsDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt)12626 virDomainGraphicsDefParseXMLSDL(virDomainGraphicsDef *def,
12627                                 xmlNodePtr node,
12628                                 xmlXPathContextPtr ctxt)
12629 {
12630     VIR_XPATH_NODE_AUTORESTORE(ctxt)
12631     xmlNodePtr glNode;
12632     virTristateBool fullscreen;
12633 
12634     ctxt->node = node;
12635 
12636     if (virXMLPropTristateBool(node, "fullscreen", VIR_XML_PROP_NONE,
12637                                &fullscreen) < 0)
12638         return -1;
12639 
12640     def->data.sdl.fullscreen = fullscreen == VIR_TRISTATE_BOOL_YES;
12641     def->data.sdl.xauth = virXMLPropString(node, "xauth");
12642     def->data.sdl.display = virXMLPropString(node, "display");
12643 
12644     if ((glNode = virXPathNode("./gl", ctxt))) {
12645         if (virXMLPropTristateBool(glNode, "enable", VIR_XML_PROP_REQUIRED,
12646                                    &def->data.sdl.gl) < 0)
12647             return -1;
12648     }
12649 
12650     return 0;
12651 }
12652 
12653 
12654 static int
virDomainGraphicsDefParseXMLRDP(virDomainGraphicsDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)12655 virDomainGraphicsDefParseXMLRDP(virDomainGraphicsDef *def,
12656                                 xmlNodePtr node,
12657                                 xmlXPathContextPtr ctxt,
12658                                 unsigned int flags)
12659 {
12660     g_autofree char *port = virXMLPropString(node, "port");
12661     g_autofree char *autoport = virXMLPropString(node, "autoport");
12662     g_autofree char *replaceUser = virXMLPropString(node, "replaceUser");
12663     g_autofree char *multiUser = virXMLPropString(node, "multiUser");
12664 
12665     if (virDomainGraphicsListensParseXML(def, node, ctxt, flags) < 0)
12666         return -1;
12667 
12668     if (port) {
12669         if (virStrToLong_i(port, NULL, 10, &def->data.rdp.port) < 0) {
12670             virReportError(VIR_ERR_INTERNAL_ERROR,
12671                            _("cannot parse rdp port %s"), port);
12672             return -1;
12673         }
12674         /* Legacy compat syntax, used -1 for auto-port */
12675         if (def->data.rdp.port == -1)
12676             def->data.rdp.autoport = true;
12677 
12678     } else {
12679         def->data.rdp.port = 0;
12680         def->data.rdp.autoport = true;
12681     }
12682 
12683     if (STREQ_NULLABLE(autoport, "yes"))
12684         def->data.rdp.autoport = true;
12685 
12686     if (def->data.rdp.autoport && (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
12687         def->data.rdp.port = 0;
12688 
12689     if (STREQ_NULLABLE(replaceUser, "yes"))
12690         def->data.rdp.replaceUser = true;
12691 
12692     if (STREQ_NULLABLE(multiUser, "yes"))
12693         def->data.rdp.multiUser = true;
12694 
12695     return 0;
12696 }
12697 
12698 
12699 static int
virDomainGraphicsDefParseXMLDesktop(virDomainGraphicsDef * def,xmlNodePtr node)12700 virDomainGraphicsDefParseXMLDesktop(virDomainGraphicsDef *def,
12701                                     xmlNodePtr node)
12702 {
12703     virTristateBool fullscreen;
12704 
12705     if (virXMLPropTristateBool(node, "fullscreen", VIR_XML_PROP_NONE,
12706                                &fullscreen) < 0)
12707         return -1;
12708 
12709     def->data.desktop.fullscreen = fullscreen == VIR_TRISTATE_BOOL_YES;
12710     def->data.desktop.display = virXMLPropString(node, "display");
12711 
12712     return 0;
12713 }
12714 
12715 
12716 static int
virDomainGraphicsDefParseXMLSpice(virDomainGraphicsDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)12717 virDomainGraphicsDefParseXMLSpice(virDomainGraphicsDef *def,
12718                                   xmlNodePtr node,
12719                                   xmlXPathContextPtr ctxt,
12720                                   unsigned int flags)
12721 {
12722     g_autofree xmlNodePtr *node_list = NULL;
12723     int n = 0;
12724     size_t i = 0;
12725     virTristateBool autoport;
12726     xmlNodePtr cur;
12727     VIR_XPATH_NODE_AUTORESTORE(ctxt)
12728 
12729     ctxt->node = node;
12730 
12731     if (virDomainGraphicsListensParseXML(def, node, ctxt, flags) < 0)
12732         return -1;
12733 
12734     if (virXMLPropInt(node, "port", 10, VIR_XML_PROP_NONE,
12735                       &def->data.spice.port, 0) < 0)
12736         return -1;
12737 
12738     if (virXMLPropInt(node, "tlsPort", 10, VIR_XML_PROP_NONE,
12739                       &def->data.spice.tlsPort, 0) < 0)
12740         return -1;
12741 
12742     if (virXMLPropTristateBool(node, "autoport", VIR_XML_PROP_NONE,
12743                                &autoport) < 0)
12744         return -1;
12745     def->data.spice.autoport = autoport == VIR_TRISTATE_BOOL_YES;
12746 
12747     def->data.spice.defaultMode = VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY;
12748     if (virXMLPropEnum(node, "defaultMode",
12749                        virDomainGraphicsSpiceChannelModeTypeFromString,
12750                        VIR_XML_PROP_NONE, &def->data.spice.defaultMode) < 0)
12751         return -1;
12752 
12753     if (def->data.spice.port == -1 && def->data.spice.tlsPort == -1) {
12754         /* Legacy compat syntax, used -1 for auto-port */
12755         def->data.spice.autoport = true;
12756     }
12757 
12758     if (def->data.spice.autoport && (flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
12759         def->data.spice.port = 0;
12760         def->data.spice.tlsPort = 0;
12761     }
12762 
12763     def->data.spice.keymap = virXMLPropString(node, "keymap");
12764 
12765     if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth,
12766                                          def->type) < 0)
12767         return -1;
12768 
12769     if ((n = virXPathNodeSet("./channel", ctxt, &node_list)) < 0)
12770         return -1;
12771 
12772     for (i = 0; i < n; i++) {
12773         virDomainGraphicsSpiceChannelName name;
12774         virDomainGraphicsSpiceChannelMode mode;
12775 
12776         if (virXMLPropEnum(node_list[i], "name",
12777                            virDomainGraphicsSpiceChannelNameTypeFromString,
12778                            VIR_XML_PROP_REQUIRED, &name) < 0)
12779             return -1;
12780 
12781         if (virXMLPropEnum(node_list[i], "mode",
12782                            virDomainGraphicsSpiceChannelModeTypeFromString,
12783                            VIR_XML_PROP_REQUIRED, &mode) < 0)
12784             return -1;
12785 
12786         def->data.spice.channels[name] = mode;
12787     }
12788 
12789     if ((cur = virXPathNode("./image", ctxt))) {
12790         virDomainGraphicsSpiceImageCompression compression;
12791 
12792         if (virXMLPropEnum(cur, "compression",
12793                            virDomainGraphicsSpiceImageCompressionTypeFromString,
12794                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
12795                            &compression) < 0)
12796             return -1;
12797 
12798         def->data.spice.image = compression;
12799     }
12800 
12801     if ((cur = virXPathNode("./jpeg", ctxt))) {
12802         virDomainGraphicsSpiceJpegCompression compression;
12803 
12804         if (virXMLPropEnum(cur, "compression",
12805                            virDomainGraphicsSpiceJpegCompressionTypeFromString,
12806                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
12807                            &compression) < 0)
12808             return -1;
12809 
12810         def->data.spice.jpeg = compression;
12811     }
12812 
12813     if ((cur = virXPathNode("./zlib", ctxt))) {
12814         virDomainGraphicsSpiceZlibCompression compression;
12815 
12816         if (virXMLPropEnum(cur, "compression",
12817                            virDomainGraphicsSpiceZlibCompressionTypeFromString,
12818                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
12819                            &compression) < 0)
12820             return -1;
12821 
12822         def->data.spice.zlib = compression;
12823     }
12824 
12825     if ((cur = virXPathNode("./playback", ctxt))) {
12826         if (virXMLPropTristateSwitch(cur, "compression",
12827                                      VIR_XML_PROP_REQUIRED,
12828                                      &def->data.spice.playback) < 0)
12829             return -1;
12830     }
12831 
12832     if ((cur = virXPathNode("./streaming", ctxt))) {
12833         virDomainGraphicsSpiceStreamingMode mode;
12834 
12835         if (virXMLPropEnum(cur, "mode",
12836                            virDomainGraphicsSpiceStreamingModeTypeFromString,
12837                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
12838                            &mode) < 0)
12839             return -1;
12840 
12841         def->data.spice.streaming = mode;
12842     }
12843 
12844     if ((cur = virXPathNode("./clipboard", ctxt))) {
12845         if (virXMLPropTristateBool(cur, "copypaste",
12846                                    VIR_XML_PROP_REQUIRED,
12847                                    &def->data.spice.copypaste) < 0)
12848             return -1;
12849     }
12850 
12851     if ((cur = virXPathNode("./filetransfer", ctxt))) {
12852         if (virXMLPropTristateBool(cur, "enable",
12853                                    VIR_XML_PROP_REQUIRED,
12854                                    &def->data.spice.filetransfer) < 0)
12855             return -1;
12856     }
12857 
12858     if ((cur = virXPathNode("./gl", ctxt))) {
12859         def->data.spice.rendernode = virXMLPropString(cur, "rendernode");
12860 
12861         if (virXMLPropTristateBool(cur, "enable",
12862                                    VIR_XML_PROP_REQUIRED,
12863                                    &def->data.spice.gl) < 0)
12864             return -1;
12865     }
12866 
12867     if ((cur = virXPathNode("./mouse", ctxt))) {
12868         if (virXMLPropEnum(cur, "mode",
12869                            virDomainGraphicsSpiceMouseModeTypeFromString,
12870                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
12871                            &def->data.spice.mousemode) < 0)
12872             return -1;
12873     }
12874 
12875     return 0;
12876 }
12877 
12878 
12879 static void
virDomainGraphicsDefParseXMLEGLHeadless(virDomainGraphicsDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt)12880 virDomainGraphicsDefParseXMLEGLHeadless(virDomainGraphicsDef *def,
12881                                         xmlNodePtr node,
12882                                         xmlXPathContextPtr ctxt)
12883 {
12884     VIR_XPATH_NODE_AUTORESTORE(ctxt)
12885     xmlNodePtr glNode;
12886 
12887     ctxt->node = node;
12888 
12889     if ((glNode = virXPathNode("./gl", ctxt)))
12890         def->data.egl_headless.rendernode = virXMLPropString(glNode,
12891                                                              "rendernode");
12892 }
12893 
12894 
12895 virDomainGraphicsDef *
virDomainGraphicsDefNew(virDomainXMLOption * xmlopt)12896 virDomainGraphicsDefNew(virDomainXMLOption *xmlopt)
12897 {
12898     virDomainGraphicsDef *def = NULL;
12899 
12900     def = g_new0(virDomainGraphicsDef, 1);
12901 
12902     if (xmlopt && xmlopt->privateData.graphicsNew &&
12903         !(def->privateData = xmlopt->privateData.graphicsNew())) {
12904         VIR_FREE(def);
12905         def = NULL;
12906     }
12907 
12908     return def;
12909 }
12910 
12911 
12912 virDomainNetDef *
virDomainNetDefNew(virDomainXMLOption * xmlopt)12913 virDomainNetDefNew(virDomainXMLOption *xmlopt)
12914 {
12915     virDomainNetDef *def = NULL;
12916 
12917     def = g_new0(virDomainNetDef, 1);
12918 
12919     if (xmlopt && xmlopt->privateData.networkNew &&
12920         !(def->privateData = xmlopt->privateData.networkNew())) {
12921         virDomainNetDefFree(def);
12922         def = NULL;
12923     }
12924 
12925     return def;
12926 }
12927 
12928 
12929 /* Parse the XML definition for a graphics device */
12930 static virDomainGraphicsDef *
virDomainGraphicsDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)12931 virDomainGraphicsDefParseXML(virDomainXMLOption *xmlopt,
12932                              xmlNodePtr node,
12933                              xmlXPathContextPtr ctxt,
12934                              unsigned int flags)
12935 {
12936     virDomainGraphicsDef *def;
12937 
12938     if (!(def = virDomainGraphicsDefNew(xmlopt)))
12939         return NULL;
12940 
12941     if (virXMLPropEnum(node, "type", virDomainGraphicsTypeFromString,
12942                        VIR_XML_PROP_REQUIRED, &def->type) < 0)
12943         goto error;
12944 
12945     switch (def->type) {
12946     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
12947         if (virDomainGraphicsDefParseXMLVNC(def, node, ctxt, flags) < 0)
12948             goto error;
12949         break;
12950     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
12951         if (virDomainGraphicsDefParseXMLSDL(def, node, ctxt) < 0)
12952             goto error;
12953         break;
12954     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
12955         if (virDomainGraphicsDefParseXMLRDP(def, node, ctxt, flags) < 0)
12956             goto error;
12957         break;
12958     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
12959         if (virDomainGraphicsDefParseXMLDesktop(def, node) < 0)
12960             goto error;
12961         break;
12962     case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
12963         if (virDomainGraphicsDefParseXMLSpice(def, node, ctxt, flags) < 0)
12964             goto error;
12965         break;
12966     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
12967         virDomainGraphicsDefParseXMLEGLHeadless(def, node, ctxt);
12968         break;
12969     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
12970         break;
12971     }
12972 
12973     return def;
12974 
12975  error:
12976     virDomainGraphicsDefFree(def);
12977     def = NULL;
12978     return NULL;
12979 }
12980 
12981 
12982 static virDomainSoundCodecDef *
virDomainSoundCodecDefParseXML(xmlNodePtr node)12983 virDomainSoundCodecDefParseXML(xmlNodePtr node)
12984 {
12985     virDomainSoundCodecDef *def;
12986     g_autofree char *type = NULL;
12987 
12988     def = g_new0(virDomainSoundCodecDef, 1);
12989 
12990     type = virXMLPropString(node, "type");
12991     if ((def->type = virDomainSoundCodecTypeFromString(type)) < 0) {
12992         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
12993                        _("unknown codec type '%s'"), type);
12994         goto error;
12995     }
12996 
12997     return def;
12998 
12999  error:
13000     virDomainSoundCodecDefFree(def);
13001     return NULL;
13002 }
13003 
13004 
13005 static virDomainSoundDef *
virDomainSoundDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)13006 virDomainSoundDefParseXML(virDomainXMLOption *xmlopt,
13007                           xmlNodePtr node,
13008                           xmlXPathContextPtr ctxt,
13009                           unsigned int flags)
13010 {
13011     virDomainSoundDef *def;
13012     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13013     xmlNodePtr audioNode;
13014 
13015     def = g_new0(virDomainSoundDef, 1);
13016     ctxt->node = node;
13017 
13018     if (virXMLPropEnum(node, "model", virDomainSoundModelTypeFromString,
13019                        VIR_XML_PROP_REQUIRED, &def->model) < 0)
13020         goto error;
13021 
13022     if (virDomainSoundModelSupportsCodecs(def)) {
13023         int ncodecs;
13024         g_autofree xmlNodePtr *codecNodes = NULL;
13025 
13026         /* parse the <codec> subelements for sound models that support it */
13027         ncodecs = virXPathNodeSet("./codec", ctxt, &codecNodes);
13028         if (ncodecs < 0)
13029             goto error;
13030 
13031         if (ncodecs > 0) {
13032             size_t i;
13033 
13034             def->codecs = g_new0(virDomainSoundCodecDef *, ncodecs);
13035 
13036             for (i = 0; i < ncodecs; i++) {
13037                 virDomainSoundCodecDef *codec = virDomainSoundCodecDefParseXML(codecNodes[i]);
13038                 if (codec == NULL)
13039                     goto error;
13040 
13041                 codec->cad = def->ncodecs; /* that will do for now */
13042                 def->codecs[def->ncodecs++] = codec;
13043             }
13044         }
13045     }
13046 
13047     audioNode = virXPathNode("./audio", ctxt);
13048     if (audioNode) {
13049         if (virXMLPropUInt(audioNode, "id", 10,
13050                            VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
13051                            &def->audioId) < 0)
13052             goto error;
13053     }
13054 
13055     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
13056         goto error;
13057 
13058     return def;
13059 
13060  error:
13061     virDomainSoundDefFree(def);
13062     return NULL;
13063 }
13064 
13065 
13066 static bool
virDomainSoundDefEquals(const virDomainSoundDef * a,const virDomainSoundDef * b)13067 virDomainSoundDefEquals(const virDomainSoundDef *a,
13068                         const virDomainSoundDef *b)
13069 {
13070     size_t i;
13071 
13072     if (a->model != b->model)
13073         return false;
13074 
13075     if (a->ncodecs != b->ncodecs)
13076         return false;
13077 
13078     for (i = 0; i < a->ncodecs; i++) {
13079         if (a->codecs[i]->type != b->codecs[i]->type)
13080             return false;
13081     }
13082 
13083     if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
13084         !virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
13085         return false;
13086 
13087     return true;
13088 }
13089 
13090 
13091 ssize_t
virDomainSoundDefFind(const virDomainDef * def,const virDomainSoundDef * sound)13092 virDomainSoundDefFind(const virDomainDef *def,
13093                       const virDomainSoundDef *sound)
13094 {
13095     size_t i;
13096 
13097     for (i = 0; i < def->nsounds; i++) {
13098         if (virDomainSoundDefEquals(sound, def->sounds[i]))
13099             return i;
13100     }
13101 
13102     return -1;
13103 }
13104 
13105 
13106 static int
virDomainAudioCommonParse(virDomainAudioIOCommon * def,xmlNodePtr node,xmlXPathContextPtr ctxt)13107 virDomainAudioCommonParse(virDomainAudioIOCommon *def,
13108                           xmlNodePtr node,
13109                           xmlXPathContextPtr ctxt)
13110 {
13111     xmlNodePtr settings;
13112     VIR_XPATH_NODE_AUTORESTORE(ctxt);
13113 
13114     ctxt->node = node;
13115     settings = virXPathNode("./settings", ctxt);
13116 
13117     if (virXMLPropTristateBool(node, "mixingEngine", VIR_XML_PROP_NONE,
13118                                &def->mixingEngine) < 0)
13119         return -1;
13120 
13121     if (virXMLPropTristateBool(node, "fixedSettings", VIR_XML_PROP_NONE,
13122                                &def->fixedSettings) < 0)
13123         return -1;
13124 
13125     if (def->fixedSettings == VIR_TRISTATE_BOOL_YES &&
13126         def->mixingEngine != VIR_TRISTATE_BOOL_YES) {
13127         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
13128                        _("fixed audio settings requires mixing engine"));
13129         return -1;
13130     }
13131 
13132     if (virXMLPropUInt(node, "voices", 10,
13133                        VIR_XML_PROP_NONZERO,
13134                        &def->voices) < 0)
13135         return -1;
13136 
13137     if (virXMLPropUInt(node, "bufferLength", 10,
13138                        VIR_XML_PROP_NONZERO,
13139                        &def->bufferLength) < 0)
13140         return -1;
13141 
13142     if (settings) {
13143         if (def->fixedSettings != VIR_TRISTATE_BOOL_YES) {
13144             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
13145                            _("audio settings specified without fixed settings flag"));
13146             return -1;
13147         }
13148 
13149         if (virXMLPropUInt(settings, "frequency", 10,
13150                            VIR_XML_PROP_NONZERO,
13151                            &def->frequency) < 0)
13152             return -1;
13153 
13154         if (virXMLPropUInt(settings, "channels", 10,
13155                            VIR_XML_PROP_NONZERO,
13156                            &def->channels) < 0)
13157             return -1;
13158 
13159         if (virXMLPropEnum(settings, "format",
13160                            virDomainAudioFormatTypeFromString,
13161                            VIR_XML_PROP_NONZERO, &def->format) < 0)
13162             return -1;
13163     }
13164 
13165     return 0;
13166 }
13167 
13168 
13169 static void
virDomainAudioALSAParse(virDomainAudioIOALSA * def,xmlNodePtr node)13170 virDomainAudioALSAParse(virDomainAudioIOALSA *def,
13171                         xmlNodePtr node)
13172 {
13173     def->dev = virXMLPropString(node, "dev");
13174 }
13175 
13176 
13177 static int
virDomainAudioCoreAudioParse(virDomainAudioIOCoreAudio * def,xmlNodePtr node)13178 virDomainAudioCoreAudioParse(virDomainAudioIOCoreAudio *def,
13179                              xmlNodePtr node)
13180 {
13181     if (virXMLPropUInt(node, "bufferCount", 10, VIR_XML_PROP_NONE,
13182                        &def->bufferCount) < 0)
13183         return -1;
13184 
13185     return 0;
13186 }
13187 
13188 
13189 static int
virDomainAudioJackParse(virDomainAudioIOJack * def,xmlNodePtr node)13190 virDomainAudioJackParse(virDomainAudioIOJack *def,
13191                         xmlNodePtr node)
13192 {
13193     def->serverName = virXMLPropString(node, "serverName");
13194     def->clientName = virXMLPropString(node, "clientName");
13195     def->connectPorts = virXMLPropString(node, "connectPorts");
13196 
13197     if (virXMLPropTristateBool(node, "exactName", VIR_XML_PROP_NONE,
13198                                &def->exactName) < 0)
13199         return -1;
13200 
13201     return 0;
13202 }
13203 
13204 
13205 static int
virDomainAudioOSSParse(virDomainAudioIOOSS * def,xmlNodePtr node)13206 virDomainAudioOSSParse(virDomainAudioIOOSS *def,
13207                        xmlNodePtr node)
13208 {
13209     def->dev = virXMLPropString(node, "dev");
13210 
13211     if (virXMLPropTristateBool(node, "tryPoll", VIR_XML_PROP_NONE,
13212                                &def->tryPoll) < 0)
13213         return -1;
13214 
13215     if (virXMLPropUInt(node, "bufferCount", 10, VIR_XML_PROP_NONE,
13216                        &def->bufferCount) < 0)
13217         return -1;
13218 
13219     return 0;
13220 }
13221 
13222 
13223 static int
virDomainAudioPulseAudioParse(virDomainAudioIOPulseAudio * def,xmlNodePtr node)13224 virDomainAudioPulseAudioParse(virDomainAudioIOPulseAudio *def,
13225                               xmlNodePtr node)
13226 {
13227     def->name = virXMLPropString(node, "name");
13228     def->streamName = virXMLPropString(node, "streamName");
13229 
13230     if (virXMLPropUInt(node, "latency", 10, VIR_XML_PROP_NONE,
13231                        &def->latency) < 0)
13232         return -1;
13233 
13234     return 0;
13235 }
13236 
13237 
13238 static int
virDomainAudioSDLParse(virDomainAudioIOSDL * def,xmlNodePtr node)13239 virDomainAudioSDLParse(virDomainAudioIOSDL *def,
13240                        xmlNodePtr node)
13241 {
13242     if (virXMLPropUInt(node, "bufferCount", 10, VIR_XML_PROP_NONE,
13243                        &def->bufferCount) < 0)
13244         return -1;
13245 
13246     return 0;
13247 }
13248 
13249 
13250 static virDomainAudioDef *
virDomainAudioDefParseXML(virDomainXMLOption * xmlopt G_GNUC_UNUSED,xmlNodePtr node,xmlXPathContextPtr ctxt)13251 virDomainAudioDefParseXML(virDomainXMLOption *xmlopt G_GNUC_UNUSED,
13252                           xmlNodePtr node,
13253                           xmlXPathContextPtr ctxt)
13254 {
13255     virDomainAudioDef *def;
13256     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13257     xmlNodePtr inputNode, outputNode;
13258 
13259     def = g_new0(virDomainAudioDef, 1);
13260     ctxt->node = node;
13261 
13262     if (virXMLPropEnum(node, "type", virDomainAudioTypeTypeFromString,
13263                        VIR_XML_PROP_REQUIRED, &def->type) < 0)
13264         goto error;
13265 
13266     if (virXMLPropUInt(node, "id", 10, VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
13267                        &def->id) < 0)
13268         goto error;
13269 
13270     if (virXMLPropUInt(node, "timerPeriod", 10, VIR_XML_PROP_NONZERO,
13271                        &def->timerPeriod) < 0)
13272         goto error;
13273 
13274     inputNode = virXPathNode("./input", ctxt);
13275     outputNode = virXPathNode("./output", ctxt);
13276 
13277     if (inputNode && virDomainAudioCommonParse(&def->input, inputNode, ctxt) < 0)
13278         goto error;
13279     if (outputNode && virDomainAudioCommonParse(&def->output, outputNode, ctxt) < 0)
13280         goto error;
13281 
13282     switch (def->type) {
13283     case VIR_DOMAIN_AUDIO_TYPE_NONE:
13284         break;
13285 
13286     case VIR_DOMAIN_AUDIO_TYPE_ALSA:
13287         if (inputNode)
13288             virDomainAudioALSAParse(&def->backend.alsa.input, inputNode);
13289         if (outputNode)
13290             virDomainAudioALSAParse(&def->backend.alsa.output, outputNode);
13291         break;
13292 
13293     case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
13294         if (inputNode &&
13295             virDomainAudioCoreAudioParse(&def->backend.coreaudio.input, inputNode) < 0)
13296             goto error;
13297         if (outputNode &&
13298             virDomainAudioCoreAudioParse(&def->backend.coreaudio.output, outputNode) < 0)
13299             goto error;
13300         break;
13301 
13302     case VIR_DOMAIN_AUDIO_TYPE_JACK:
13303         if (inputNode &&
13304             virDomainAudioJackParse(&def->backend.jack.input, inputNode) < 0)
13305             goto error;
13306         if (outputNode &&
13307             virDomainAudioJackParse(&def->backend.jack.output, outputNode) < 0)
13308             goto error;
13309         break;
13310 
13311     case VIR_DOMAIN_AUDIO_TYPE_OSS: {
13312         int dspPolicySet;
13313 
13314         if (virXMLPropTristateBool(node, "tryMMap", VIR_XML_PROP_NONE,
13315                                    &def->backend.oss.tryMMap) < 0)
13316             goto error;
13317 
13318         if (virXMLPropTristateBool(node, "exclusive", VIR_XML_PROP_NONE,
13319                                    &def->backend.oss.exclusive) < 0)
13320             goto error;
13321 
13322         if ((dspPolicySet = virXMLPropInt(node, "dspPolicy", 10, VIR_XML_PROP_NONE,
13323                                      &def->backend.oss.dspPolicy, 0)) < 0)
13324             goto error;
13325 
13326         if (dspPolicySet != 0) {
13327             if (def->backend.oss.dspPolicy < 0) {
13328                 virReportError(VIR_ERR_XML_ERROR,
13329                                _("cannot parse 'dspPolicy' value '%i'"),
13330                                def->backend.oss.dspPolicy);
13331                 goto error;
13332             }
13333             def->backend.oss.dspPolicySet = true;
13334         }
13335 
13336         if (inputNode &&
13337             virDomainAudioOSSParse(&def->backend.oss.input, inputNode) < 0)
13338             goto error;
13339         if (outputNode &&
13340             virDomainAudioOSSParse(&def->backend.oss.output, outputNode) < 0)
13341             goto error;
13342         break;
13343     }
13344 
13345     case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
13346         def->backend.pulseaudio.serverName = virXMLPropString(node, "serverName");
13347 
13348         if (inputNode &&
13349             virDomainAudioPulseAudioParse(&def->backend.pulseaudio.input, inputNode) < 0)
13350             goto error;
13351         if (outputNode &&
13352             virDomainAudioPulseAudioParse(&def->backend.pulseaudio.output, outputNode) < 0)
13353             goto error;
13354         break;
13355 
13356     case VIR_DOMAIN_AUDIO_TYPE_SDL: {
13357         if (virXMLPropEnum(node, "driver", virDomainAudioSDLDriverTypeFromString,
13358                            VIR_XML_PROP_NONZERO, &def->backend.sdl.driver) < 0)
13359             goto error;
13360 
13361         if (inputNode &&
13362             virDomainAudioSDLParse(&def->backend.sdl.input, inputNode) < 0)
13363             goto error;
13364         if (outputNode &&
13365             virDomainAudioSDLParse(&def->backend.sdl.output, outputNode) < 0)
13366             goto error;
13367         break;
13368     }
13369 
13370     case VIR_DOMAIN_AUDIO_TYPE_SPICE:
13371         break;
13372 
13373     case VIR_DOMAIN_AUDIO_TYPE_FILE:
13374         def->backend.file.path = virXMLPropString(node, "path");
13375         break;
13376 
13377     case VIR_DOMAIN_AUDIO_TYPE_LAST:
13378     default:
13379         virReportEnumRangeError(virDomainAudioType, def->type);
13380         break;
13381     }
13382 
13383     return def;
13384 
13385  error:
13386     virDomainAudioDefFree(def);
13387     return NULL;
13388 }
13389 static virDomainWatchdogDef *
virDomainWatchdogDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)13390 virDomainWatchdogDefParseXML(virDomainXMLOption *xmlopt,
13391                              xmlNodePtr node,
13392                              xmlXPathContextPtr ctxt,
13393                              unsigned int flags)
13394 {
13395     virDomainWatchdogDef *def;
13396     g_autofree char *model = NULL;
13397     g_autofree char *action = NULL;
13398 
13399     def = g_new0(virDomainWatchdogDef, 1);
13400 
13401     model = virXMLPropString(node, "model");
13402     if (model == NULL) {
13403         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
13404                        _("watchdog must contain model name"));
13405         goto error;
13406     }
13407     def->model = virDomainWatchdogModelTypeFromString(model);
13408     if (def->model < 0) {
13409         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
13410                        _("unknown watchdog model '%s'"), model);
13411         goto error;
13412     }
13413 
13414     action = virXMLPropString(node, "action");
13415     if (action == NULL) {
13416         def->action = VIR_DOMAIN_WATCHDOG_ACTION_RESET;
13417     } else {
13418         def->action = virDomainWatchdogActionTypeFromString(action);
13419         if (def->action < 0) {
13420             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
13421                            _("unknown watchdog action '%s'"), action);
13422             goto error;
13423         }
13424     }
13425 
13426     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
13427         goto error;
13428 
13429     return def;
13430 
13431  error:
13432     virDomainWatchdogDefFree(def);
13433     return NULL;
13434 }
13435 
13436 
13437 static virDomainRNGDef *
virDomainRNGDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)13438 virDomainRNGDefParseXML(virDomainXMLOption *xmlopt,
13439                         xmlNodePtr node,
13440                         xmlXPathContextPtr ctxt,
13441                         unsigned int flags)
13442 {
13443     virDomainRNGDef *def;
13444     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13445     int nbackends;
13446     g_autofree xmlNodePtr *backends = NULL;
13447     g_autofree char *model = NULL;
13448     g_autofree char *backend = NULL;
13449     g_autofree char *type = NULL;
13450 
13451     def = g_new0(virDomainRNGDef, 1);
13452 
13453     if (!(model = virXMLPropString(node, "model"))) {
13454         virReportError(VIR_ERR_XML_ERROR, "%s", _("missing RNG device model"));
13455         goto error;
13456     }
13457 
13458     if ((def->model = virDomainRNGModelTypeFromString(model)) < 0) {
13459         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unknown RNG model '%s'"), model);
13460         goto error;
13461     }
13462 
13463     ctxt->node = node;
13464 
13465     if (virXPathUInt("string(./rate/@bytes)", ctxt, &def->rate) < -1) {
13466         virReportError(VIR_ERR_XML_ERROR, "%s",
13467                        _("invalid RNG rate bytes value"));
13468         goto error;
13469     }
13470 
13471     if (def->rate > 0 &&
13472         virXPathUInt("string(./rate/@period)", ctxt, &def->period) < -1) {
13473         virReportError(VIR_ERR_XML_ERROR, "%s",
13474                        _("invalid RNG rate period value"));
13475         goto error;
13476     }
13477 
13478     if ((nbackends = virXPathNodeSet("./backend", ctxt, &backends)) < 0)
13479         goto error;
13480 
13481     if (nbackends != 1) {
13482         virReportError(VIR_ERR_XML_ERROR, "%s",
13483                        _("only one RNG backend is supported"));
13484         goto error;
13485     }
13486 
13487     if (!(backend = virXMLPropString(backends[0], "model"))) {
13488         virReportError(VIR_ERR_XML_ERROR, "%s",
13489                        _("missing RNG device backend model"));
13490         goto error;
13491     }
13492 
13493     if ((def->backend = virDomainRNGBackendTypeFromString(backend)) < 0) {
13494         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
13495                        _("unknown RNG backend model '%s'"), backend);
13496         goto error;
13497     }
13498 
13499     switch ((virDomainRNGBackend) def->backend) {
13500     case VIR_DOMAIN_RNG_BACKEND_RANDOM:
13501         def->source.file = virXPathString("string(./backend)", ctxt);
13502         break;
13503 
13504     case VIR_DOMAIN_RNG_BACKEND_EGD:
13505         if (!(type = virXMLPropString(backends[0], "type"))) {
13506             virReportError(VIR_ERR_XML_ERROR, "%s",
13507                            _("missing EGD backend type"));
13508             goto error;
13509         }
13510 
13511         if (!(def->source.chardev = virDomainChrSourceDefNew(xmlopt)))
13512             goto error;
13513 
13514         def->source.chardev->type = virDomainChrTypeFromString(type);
13515         if (def->source.chardev->type < 0) {
13516             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
13517                            _("unknown backend type '%s' for egd"),
13518                            type);
13519             goto error;
13520         }
13521 
13522         if (virDomainChrSourceDefParseXML(def->source.chardev,
13523                                           backends[0], flags,
13524                                           NULL, ctxt) < 0)
13525             goto error;
13526         break;
13527 
13528     case VIR_DOMAIN_RNG_BACKEND_BUILTIN:
13529     case VIR_DOMAIN_RNG_BACKEND_LAST:
13530         break;
13531     }
13532 
13533     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
13534         goto error;
13535 
13536     if (virDomainVirtioOptionsParseXML(virXPathNode("./driver", ctxt),
13537                                        &def->virtio) < 0)
13538         goto error;
13539 
13540     return def;
13541 
13542  error:
13543     virDomainRNGDefFree(def);
13544     def = NULL;
13545     return NULL;
13546 }
13547 
13548 
13549 static virDomainMemballoonDef *
virDomainMemballoonDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)13550 virDomainMemballoonDefParseXML(virDomainXMLOption *xmlopt,
13551                                xmlNodePtr node,
13552                                xmlXPathContextPtr ctxt,
13553                                unsigned int flags)
13554 {
13555     virDomainMemballoonDef *def;
13556     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13557     xmlNodePtr stats;
13558 
13559     ctxt->node = node;
13560 
13561     def = g_new0(virDomainMemballoonDef, 1);
13562 
13563     if (virXMLPropEnum(node, "model", virDomainMemballoonModelTypeFromString,
13564                        VIR_XML_PROP_REQUIRED, &def->model) < 0)
13565         goto error;
13566 
13567     if (virXMLPropTristateSwitch(node, "autodeflate", VIR_XML_PROP_NONE,
13568                                  &def->autodeflate) < 0)
13569         goto error;
13570 
13571     if (virXMLPropTristateSwitch(node, "freePageReporting",
13572                                  VIR_XML_PROP_NONE,
13573                                  &def->free_page_reporting) < 0)
13574         goto error;
13575 
13576     if ((stats = virXPathNode("./stats", ctxt))) {
13577         if (virXMLPropInt(stats, "period", 0, VIR_XML_PROP_NONE,
13578                           &def->period, 0) < 0)
13579             goto error;
13580 
13581         if (def->period < 0)
13582             def->period = 0;
13583     }
13584 
13585     if (def->model == VIR_DOMAIN_MEMBALLOON_MODEL_NONE)
13586         VIR_DEBUG("Ignoring device address for none model Memballoon");
13587     else if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
13588                                          &def->info, flags) < 0)
13589         goto error;
13590 
13591     if (virDomainVirtioOptionsParseXML(virXPathNode("./driver", ctxt),
13592                                        &def->virtio) < 0)
13593         goto error;
13594 
13595     return def;
13596 
13597  error:
13598     virDomainMemballoonDefFree(def);
13599     return NULL;
13600 }
13601 
13602 static virDomainNVRAMDef *
virDomainNVRAMDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)13603 virDomainNVRAMDefParseXML(virDomainXMLOption *xmlopt,
13604                           xmlNodePtr node,
13605                           xmlXPathContextPtr ctxt,
13606                           unsigned int flags)
13607 {
13608     virDomainNVRAMDef *def;
13609 
13610     def = g_new0(virDomainNVRAMDef, 1);
13611 
13612     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
13613         goto error;
13614 
13615     return def;
13616 
13617  error:
13618     virDomainNVRAMDefFree(def);
13619     return NULL;
13620 }
13621 
13622 static virDomainShmemDef *
virDomainShmemDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)13623 virDomainShmemDefParseXML(virDomainXMLOption *xmlopt,
13624                           xmlNodePtr node,
13625                           xmlXPathContextPtr ctxt,
13626                           unsigned int flags)
13627 {
13628     g_autoptr(virDomainShmemDef) def = g_new0(virDomainShmemDef, 1);
13629     xmlNodePtr model;
13630     xmlNodePtr msi;
13631     xmlNodePtr server;
13632     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13633 
13634     ctxt->node = node;
13635 
13636     if ((model = virXPathNode("./model", ctxt))) {
13637         /* If there's none, we will automatically have the first one
13638          * (as default).  Unfortunately this has to be done for
13639          * compatibility reasons. */
13640         if (virXMLPropEnum(model, "type", virDomainShmemModelTypeFromString,
13641                            VIR_XML_PROP_NONE, &def->model) < 0)
13642             return NULL;
13643     }
13644 
13645     if (!(def->name = virXMLPropString(node, "name"))) {
13646         virReportError(VIR_ERR_XML_ERROR, "%s",
13647                        _("shmem element must contain 'name' attribute"));
13648         return NULL;
13649     }
13650 
13651     if (def->model != VIR_DOMAIN_SHMEM_MODEL_IVSHMEM) {
13652         if (virXMLPropEnum(node, "role", virDomainShmemRoleTypeFromString,
13653                            VIR_XML_PROP_NONZERO, &def->role) < 0)
13654             return NULL;
13655     }
13656 
13657     if (virParseScaledValue("./size[1]", NULL, ctxt,
13658                             &def->size, 1, ULLONG_MAX, false) < 0)
13659         return NULL;
13660 
13661     if ((server = virXPathNode("./server[1]", ctxt))) {
13662         g_autofree char *tmp = NULL;
13663 
13664         if (!(def->server.chr = virDomainChrSourceDefNew(xmlopt)))
13665             return NULL;
13666 
13667         def->server.enabled = true;
13668         def->server.chr->type = VIR_DOMAIN_CHR_TYPE_UNIX;
13669         def->server.chr->data.nix.listen = false;
13670         if ((tmp = virXMLPropString(server, "path")))
13671             def->server.chr->data.nix.path = virFileSanitizePath(tmp);
13672     }
13673 
13674     if ((msi = virXPathNode("./msi[1]", ctxt))) {
13675         def->msi.enabled = true;
13676 
13677         if (virXMLPropUInt(msi, "vectors", 0, VIR_XML_PROP_NONE,
13678                            &def->msi.vectors) < 0)
13679             return NULL;
13680 
13681         if (virXMLPropTristateSwitch(msi, "ioeventfd", VIR_XML_PROP_NONE,
13682                                      &def->msi.ioeventfd) < 0)
13683             return NULL;
13684     }
13685 
13686     /* msi option is only relevant with a server */
13687     if (def->msi.enabled && !def->server.enabled) {
13688         virReportError(VIR_ERR_XML_ERROR, "%s",
13689                        _("msi option is only supported with a server"));
13690         return NULL;
13691     }
13692 
13693     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
13694         return NULL;
13695 
13696 
13697     return g_steal_pointer(&def);
13698 }
13699 
13700 static int
virSysinfoBIOSParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virSysinfoBIOSDef ** bios)13701 virSysinfoBIOSParseXML(xmlNodePtr node,
13702                        xmlXPathContextPtr ctxt,
13703                        virSysinfoBIOSDef **bios)
13704 {
13705     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13706     int ret = -1;
13707     virSysinfoBIOSDef *def;
13708 
13709     ctxt->node = node;
13710 
13711     if (!virXMLNodeNameEqual(node, "bios")) {
13712         virReportError(VIR_ERR_XML_ERROR, "%s",
13713                        _("XML does not contain expected 'bios' element"));
13714         return ret;
13715     }
13716 
13717     def = g_new0(virSysinfoBIOSDef, 1);
13718 
13719     def->vendor = virXPathString("string(entry[@name='vendor'])", ctxt);
13720     def->version = virXPathString("string(entry[@name='version'])", ctxt);
13721     def->date = virXPathString("string(entry[@name='date'])", ctxt);
13722     def->release = virXPathString("string(entry[@name='release'])", ctxt);
13723     if (def->date != NULL) {
13724         char *ptr;
13725         int month, day, year;
13726 
13727         /* Validate just the format of the date
13728          * Expect mm/dd/yyyy or mm/dd/yy,
13729          * where yy must be 00->99 and would be assumed to be 19xx
13730          * a yyyy date should be 1900 and beyond
13731          */
13732         if (virStrToLong_i(def->date, &ptr, 10, &month) < 0 ||
13733             *ptr != '/' ||
13734             virStrToLong_i(ptr + 1, &ptr, 10, &day) < 0 ||
13735             *ptr != '/' ||
13736             virStrToLong_i(ptr + 1, &ptr, 10, &year) < 0 ||
13737             *ptr != '\0' ||
13738             (month < 1 || month > 12) ||
13739             (day < 1 || day > 31) ||
13740             (year < 0 || (year >= 100 && year < 1900))) {
13741             virReportError(VIR_ERR_XML_DETAIL, "%s",
13742                            _("Invalid BIOS 'date' format"));
13743             goto cleanup;
13744         }
13745     }
13746 
13747     if (!def->vendor && !def->version &&
13748         !def->date && !def->release) {
13749         virSysinfoBIOSDefFree(def);
13750         def = NULL;
13751     }
13752 
13753     *bios = g_steal_pointer(&def);
13754     ret = 0;
13755  cleanup:
13756     virSysinfoBIOSDefFree(def);
13757     return ret;
13758 }
13759 
13760 static int
virSysinfoSystemParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virSysinfoSystemDef ** sysdef,unsigned char * domUUID,bool uuid_generated)13761 virSysinfoSystemParseXML(xmlNodePtr node,
13762                          xmlXPathContextPtr ctxt,
13763                          virSysinfoSystemDef **sysdef,
13764                          unsigned char *domUUID,
13765                          bool uuid_generated)
13766 {
13767     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13768     int ret = -1;
13769     virSysinfoSystemDef *def;
13770     g_autofree char *tmpUUID = NULL;
13771 
13772     ctxt->node = node;
13773 
13774     if (!virXMLNodeNameEqual(node, "system")) {
13775         virReportError(VIR_ERR_XML_ERROR, "%s",
13776                        _("XML does not contain expected 'system' element"));
13777         return ret;
13778     }
13779 
13780     def = g_new0(virSysinfoSystemDef, 1);
13781 
13782     def->manufacturer =
13783         virXPathString("string(entry[@name='manufacturer'])", ctxt);
13784     def->product =
13785         virXPathString("string(entry[@name='product'])", ctxt);
13786     def->version =
13787         virXPathString("string(entry[@name='version'])", ctxt);
13788     def->serial =
13789         virXPathString("string(entry[@name='serial'])", ctxt);
13790     tmpUUID = virXPathString("string(entry[@name='uuid'])", ctxt);
13791     if (tmpUUID) {
13792         unsigned char uuidbuf[VIR_UUID_BUFLEN];
13793         char uuidstr[VIR_UUID_STRING_BUFLEN];
13794         if (virUUIDParse(tmpUUID, uuidbuf) < 0) {
13795             virReportError(VIR_ERR_XML_DETAIL,
13796                            "%s", _("malformed <sysinfo> uuid element"));
13797             goto cleanup;
13798         }
13799         if (uuid_generated) {
13800             memcpy(domUUID, uuidbuf, VIR_UUID_BUFLEN);
13801         } else if (memcmp(domUUID, uuidbuf, VIR_UUID_BUFLEN) != 0) {
13802             virReportError(VIR_ERR_XML_DETAIL, "%s",
13803                            _("UUID mismatch between <uuid> and "
13804                              "<sysinfo>"));
13805             goto cleanup;
13806         }
13807         /* Although we've validated the UUID as good, virUUIDParse() is
13808          * lax with respect to allowing extraneous "-" and " ", but the
13809          * underlying hypervisor may be less forgiving. Use virUUIDFormat()
13810          * to validate format in xml is right. If not, then format it
13811          * properly so that it's used correctly later.
13812          */
13813         virUUIDFormat(uuidbuf, uuidstr);
13814         def->uuid = g_strdup(uuidstr);
13815     }
13816     def->sku =
13817         virXPathString("string(entry[@name='sku'])", ctxt);
13818     def->family =
13819         virXPathString("string(entry[@name='family'])", ctxt);
13820 
13821     if (!def->manufacturer && !def->product && !def->version &&
13822         !def->serial && !def->uuid && !def->sku && !def->family) {
13823         virSysinfoSystemDefFree(def);
13824         def = NULL;
13825     }
13826 
13827     *sysdef = g_steal_pointer(&def);
13828     ret = 0;
13829  cleanup:
13830     virSysinfoSystemDefFree(def);
13831     return ret;
13832 }
13833 
13834 static int
virSysinfoBaseBoardParseXML(xmlXPathContextPtr ctxt,virSysinfoBaseBoardDef ** baseBoard,size_t * nbaseBoard)13835 virSysinfoBaseBoardParseXML(xmlXPathContextPtr ctxt,
13836                             virSysinfoBaseBoardDef **baseBoard,
13837                             size_t *nbaseBoard)
13838 {
13839     size_t i, nboards = 0;
13840     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13841     int n;
13842     g_autofree virSysinfoBaseBoardDef *boards = NULL;
13843     g_autofree xmlNodePtr *nodes = NULL;
13844 
13845     if ((n = virXPathNodeSet("./baseBoard", ctxt, &nodes)) < 0)
13846         return -1;
13847 
13848     if (n)
13849         boards = g_new0(virSysinfoBaseBoardDef, n);
13850 
13851     for (i = 0; i < n; i++) {
13852         virSysinfoBaseBoardDef *def = boards + nboards;
13853 
13854         ctxt->node = nodes[i];
13855 
13856         def->manufacturer =
13857             virXPathString("string(entry[@name='manufacturer'])", ctxt);
13858         def->product =
13859             virXPathString("string(entry[@name='product'])", ctxt);
13860         def->version =
13861             virXPathString("string(entry[@name='version'])", ctxt);
13862         def->serial =
13863             virXPathString("string(entry[@name='serial'])", ctxt);
13864         def->asset =
13865             virXPathString("string(entry[@name='asset'])", ctxt);
13866         def->location =
13867             virXPathString("string(entry[@name='location'])", ctxt);
13868 
13869         if (!def->manufacturer && !def->product && !def->version &&
13870             !def->serial && !def->asset && !def->location) {
13871             /* nada */
13872         } else {
13873             nboards++;
13874         }
13875     }
13876 
13877     *baseBoard = g_steal_pointer(&boards);
13878     *nbaseBoard = nboards;
13879 
13880     return 0;
13881 }
13882 
13883 
13884 static int
virSysinfoOEMStringsParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virSysinfoOEMStringsDef ** oem)13885 virSysinfoOEMStringsParseXML(xmlNodePtr node,
13886                              xmlXPathContextPtr ctxt,
13887                              virSysinfoOEMStringsDef **oem)
13888 {
13889     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13890     int ret = -1;
13891     virSysinfoOEMStringsDef *def;
13892     int nstrings;
13893     size_t i;
13894     g_autofree xmlNodePtr *strings = NULL;
13895 
13896     ctxt->node = node;
13897 
13898     nstrings = virXPathNodeSet("./entry", ctxt, &strings);
13899     if (nstrings < 0)
13900         return -1;
13901     if (nstrings == 0)
13902         return 0;
13903 
13904     def = g_new0(virSysinfoOEMStringsDef, 1);
13905 
13906     def->values = g_new0(char *, nstrings);
13907 
13908     def->nvalues = nstrings;
13909     for (i = 0; i < nstrings; i++) {
13910         if (!(def->values[i] = virXMLNodeContentString(strings[i])))
13911             goto cleanup;
13912     }
13913 
13914     *oem = g_steal_pointer(&def);
13915     ret = 0;
13916  cleanup:
13917     virSysinfoOEMStringsDefFree(def);
13918     return ret;
13919 }
13920 
13921 
13922 static int
virSysinfoChassisParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virSysinfoChassisDef ** chassisdef)13923 virSysinfoChassisParseXML(xmlNodePtr node,
13924                          xmlXPathContextPtr ctxt,
13925                          virSysinfoChassisDef **chassisdef)
13926 {
13927     VIR_XPATH_NODE_AUTORESTORE(ctxt)
13928     int ret = -1;
13929     virSysinfoChassisDef *def;
13930 
13931     ctxt->node = node;
13932 
13933     if (!xmlStrEqual(node->name, BAD_CAST "chassis")) {
13934         virReportError(VIR_ERR_XML_ERROR, "%s",
13935                        _("XML does not contain expected 'chassis' element"));
13936         return ret;
13937     }
13938 
13939     def = g_new0(virSysinfoChassisDef, 1);
13940 
13941     def->manufacturer =
13942         virXPathString("string(entry[@name='manufacturer'])", ctxt);
13943     def->version =
13944         virXPathString("string(entry[@name='version'])", ctxt);
13945     def->serial =
13946         virXPathString("string(entry[@name='serial'])", ctxt);
13947     def->asset =
13948         virXPathString("string(entry[@name='asset'])", ctxt);
13949     def->sku =
13950         virXPathString("string(entry[@name='sku'])", ctxt);
13951 
13952     if (!def->manufacturer && !def->version &&
13953         !def->serial && !def->asset && !def->sku) {
13954         virSysinfoChassisDefFree(def);
13955         def = NULL;
13956     }
13957 
13958     *chassisdef = g_steal_pointer(&def);
13959     ret = 0;
13960     virSysinfoChassisDefFree(def);
13961     return ret;
13962 }
13963 
13964 
13965 static int
virSysinfoParseSMBIOSDef(virSysinfoDef * def,xmlXPathContextPtr ctxt,unsigned char * domUUID,bool uuid_generated)13966 virSysinfoParseSMBIOSDef(virSysinfoDef *def,
13967                          xmlXPathContextPtr ctxt,
13968                          unsigned char *domUUID,
13969                          bool uuid_generated)
13970 {
13971     xmlNodePtr tmpnode;
13972 
13973     /* Extract BIOS related metadata */
13974     if ((tmpnode = virXPathNode("./bios[1]", ctxt)) != NULL) {
13975         if (virSysinfoBIOSParseXML(tmpnode, ctxt, &def->bios) < 0)
13976             return -1;
13977     }
13978 
13979     /* Extract system related metadata */
13980     if ((tmpnode = virXPathNode("./system[1]", ctxt)) != NULL) {
13981         if (virSysinfoSystemParseXML(tmpnode, ctxt, &def->system,
13982                                      domUUID, uuid_generated) < 0)
13983             return -1;
13984     }
13985 
13986     /* Extract system base board metadata */
13987     if (virSysinfoBaseBoardParseXML(ctxt, &def->baseBoard, &def->nbaseBoard) < 0)
13988         return -1;
13989 
13990     /* Extract chassis related metadata */
13991     if ((tmpnode = virXPathNode("./chassis[1]", ctxt)) != NULL) {
13992         if (virSysinfoChassisParseXML(tmpnode, ctxt, &def->chassis) < 0)
13993             return -1;
13994     }
13995 
13996     /* Extract system related metadata */
13997     if ((tmpnode = virXPathNode("./oemStrings[1]", ctxt)) != NULL) {
13998         if (virSysinfoOEMStringsParseXML(tmpnode, ctxt, &def->oemStrings) < 0)
13999             return -1;
14000     }
14001 
14002     return 0;
14003 }
14004 
14005 
14006 static int
virSysinfoParseFWCfgDef(virSysinfoDef * def,xmlNodePtr node,xmlXPathContextPtr ctxt)14007 virSysinfoParseFWCfgDef(virSysinfoDef *def,
14008                         xmlNodePtr node,
14009                         xmlXPathContextPtr ctxt)
14010 {
14011     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14012     g_autofree xmlNodePtr *nodes = NULL;
14013     int n;
14014     size_t i;
14015 
14016     ctxt->node = node;
14017 
14018     if ((n = virXPathNodeSet("./entry", ctxt, &nodes)) < 0)
14019         return -1;
14020 
14021     if (n == 0)
14022         return 0;
14023 
14024     def->fw_cfgs = g_new0(virSysinfoFWCfgDef, n);
14025 
14026     for (i = 0; i < n; i++) {
14027         g_autofree char *name = NULL;
14028         g_autofree char *value = NULL;
14029         g_autofree char *file = NULL;
14030         g_autofree char *sanitizedFile = NULL;
14031 
14032         if (!(name = virXMLPropString(nodes[i], "name"))) {
14033             virReportError(VIR_ERR_XML_ERROR, "%s",
14034                            _("Firmware entry is missing 'name' attribute"));
14035             return -1;
14036         }
14037 
14038         if (!(value = virXMLNodeContentString(nodes[i])))
14039             return -1;
14040 
14041         file = virXMLPropString(nodes[i], "file");
14042 
14043         if (virStringIsEmpty(value))
14044             VIR_FREE(value);
14045 
14046         if (!value && !file) {
14047             virReportError(VIR_ERR_XML_ERROR, "%s",
14048                            _("Firmware entry must have either value or "
14049                              "'file' attribute"));
14050             return -1;
14051         }
14052 
14053         if (file)
14054             sanitizedFile = virFileSanitizePath(file);
14055 
14056         def->fw_cfgs[i].name = g_steal_pointer(&name);
14057         def->fw_cfgs[i].value = g_steal_pointer(&value);
14058         def->fw_cfgs[i].file = g_steal_pointer(&sanitizedFile);
14059         def->nfw_cfgs++;
14060     }
14061 
14062     return 0;
14063 }
14064 
14065 
14066 static virSysinfoDef *
virSysinfoParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned char * domUUID,bool uuid_generated)14067 virSysinfoParseXML(xmlNodePtr node,
14068                    xmlXPathContextPtr ctxt,
14069                    unsigned char *domUUID,
14070                    bool uuid_generated)
14071 {
14072     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14073     virSysinfoDef *def;
14074     g_autofree char *typeStr = NULL;
14075     int type;
14076 
14077     ctxt->node = node;
14078 
14079     if (!virXMLNodeNameEqual(node, "sysinfo")) {
14080         virReportError(VIR_ERR_XML_ERROR, "%s",
14081                        _("XML does not contain expected 'sysinfo' element"));
14082         return NULL;
14083     }
14084 
14085     def = g_new0(virSysinfoDef, 1);
14086 
14087     typeStr = virXMLPropString(node, "type");
14088     if (typeStr == NULL) {
14089         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
14090                        _("sysinfo must contain a type attribute"));
14091         goto error;
14092     }
14093     if ((type = virSysinfoTypeFromString(typeStr)) < 0) {
14094         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14095                        _("unknown sysinfo type '%s'"), typeStr);
14096         goto error;
14097     }
14098     def->type = type;
14099 
14100     switch (def->type) {
14101     case VIR_SYSINFO_SMBIOS:
14102         if (virSysinfoParseSMBIOSDef(def, ctxt, domUUID, uuid_generated) < 0)
14103             goto error;
14104         break;
14105 
14106     case VIR_SYSINFO_FWCFG:
14107         if (virSysinfoParseFWCfgDef(def, node, ctxt) < 0)
14108             goto error;
14109         break;
14110 
14111     case VIR_SYSINFO_LAST:
14112         break;
14113     }
14114 
14115     return def;
14116 
14117  error:
14118     virSysinfoDefFree(def);
14119     return NULL;
14120 }
14121 
14122 unsigned int
virDomainVideoDefaultRAM(const virDomainDef * def,const virDomainVideoType type)14123 virDomainVideoDefaultRAM(const virDomainDef *def,
14124                          const virDomainVideoType type)
14125 {
14126     switch (type) {
14127     case VIR_DOMAIN_VIDEO_TYPE_VGA:
14128     case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
14129     case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
14130         if (def->virtType == VIR_DOMAIN_VIRT_VBOX)
14131             return 8 * 1024;
14132         else if (def->virtType == VIR_DOMAIN_VIRT_VMWARE)
14133             return 4 * 1024;
14134         else
14135             return 16 * 1024;
14136         break;
14137 
14138     case VIR_DOMAIN_VIDEO_TYPE_BOCHS:
14139         return 16 * 1024;
14140 
14141     case VIR_DOMAIN_VIDEO_TYPE_XEN:
14142         /* Original Xen PVFB hardcoded to 4 MB */
14143         return 4 * 1024;
14144 
14145     case VIR_DOMAIN_VIDEO_TYPE_QXL:
14146         /* QEMU use 64M as the minimal video memory for qxl device */
14147         return 64 * 1024;
14148 
14149     case VIR_DOMAIN_VIDEO_TYPE_DEFAULT:
14150     case VIR_DOMAIN_VIDEO_TYPE_VBOX:
14151     case VIR_DOMAIN_VIDEO_TYPE_PARALLELS:
14152     case VIR_DOMAIN_VIDEO_TYPE_VIRTIO:
14153     case VIR_DOMAIN_VIDEO_TYPE_GOP:
14154     case VIR_DOMAIN_VIDEO_TYPE_NONE:
14155     case VIR_DOMAIN_VIDEO_TYPE_RAMFB:
14156     case VIR_DOMAIN_VIDEO_TYPE_LAST:
14157     default:
14158         return 0;
14159     }
14160 }
14161 
14162 
14163 static virDomainVideoAccelDef *
virDomainVideoAccelDefParseXML(xmlNodePtr node)14164 virDomainVideoAccelDefParseXML(xmlNodePtr node)
14165 {
14166     g_autofree virDomainVideoAccelDef *def = NULL;
14167     int val;
14168     g_autofree char *accel2d = NULL;
14169     g_autofree char *accel3d = NULL;
14170     g_autofree char *rendernode = NULL;
14171 
14172     accel3d = virXMLPropString(node, "accel3d");
14173     accel2d = virXMLPropString(node, "accel2d");
14174     rendernode = virXMLPropString(node, "rendernode");
14175 
14176     if (!accel3d && !accel2d && !rendernode) {
14177         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
14178                        _("missing values for acceleration"));
14179         return NULL;
14180     }
14181 
14182     def = g_new0(virDomainVideoAccelDef, 1);
14183 
14184     if (accel3d) {
14185         if ((val = virTristateBoolTypeFromString(accel3d)) <= 0) {
14186             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14187                            _("unknown accel3d value '%s'"), accel3d);
14188             return NULL;
14189         }
14190         def->accel3d = val;
14191     }
14192 
14193     if (accel2d) {
14194         if ((val = virTristateBoolTypeFromString(accel2d)) <= 0) {
14195             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14196                            _("unknown accel2d value '%s'"), accel2d);
14197             return NULL;
14198         }
14199         def->accel2d = val;
14200     }
14201 
14202     if (rendernode)
14203         def->rendernode = virFileSanitizePath(rendernode);
14204 
14205     return g_steal_pointer(&def);
14206 }
14207 
14208 static virDomainVideoResolutionDef *
virDomainVideoResolutionDefParseXML(xmlNodePtr node)14209 virDomainVideoResolutionDefParseXML(xmlNodePtr node)
14210 {
14211     g_autofree virDomainVideoResolutionDef *def = NULL;
14212 
14213     def = g_new0(virDomainVideoResolutionDef, 1);
14214 
14215     if (virXMLPropUInt(node, "x", 10, VIR_XML_PROP_REQUIRED, &def->x) < 0)
14216         return NULL;
14217 
14218     if (virXMLPropUInt(node, "y", 10, VIR_XML_PROP_REQUIRED, &def->y) < 0)
14219         return NULL;
14220 
14221     return g_steal_pointer(&def);
14222 }
14223 
14224 static virDomainVideoDriverDef *
virDomainVideoDriverDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt)14225 virDomainVideoDriverDefParseXML(xmlNodePtr node,
14226                                 xmlXPathContextPtr ctxt)
14227 {
14228     g_autofree virDomainVideoDriverDef *def = NULL;
14229     xmlNodePtr driver = NULL;
14230     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14231 
14232     ctxt->node = node;
14233 
14234     if (!(driver = virXPathNode("./driver", ctxt)))
14235         return NULL;
14236 
14237     def = g_new0(virDomainVideoDriverDef, 1);
14238 
14239     if (virXMLPropEnum(driver, "vgaconf",
14240                        virDomainVideoVGAConfTypeFromString,
14241                        VIR_XML_PROP_NONE, &def->vgaconf) < 0)
14242         return NULL;
14243 
14244     return g_steal_pointer(&def);
14245 }
14246 
14247 static virDomainVideoDef *
virDomainVideoDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)14248 virDomainVideoDefParseXML(virDomainXMLOption *xmlopt,
14249                           xmlNodePtr node,
14250                           xmlXPathContextPtr ctxt,
14251                           unsigned int flags)
14252 {
14253     g_autoptr(virDomainVideoDef) def = NULL;
14254     xmlNodePtr driver;
14255     xmlNodePtr accel_node;
14256     xmlNodePtr res_node;
14257     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14258     g_autofree char *type = NULL;
14259     g_autofree char *heads = NULL;
14260     g_autofree char *vram = NULL;
14261     g_autofree char *vram64 = NULL;
14262     g_autofree char *ram = NULL;
14263     g_autofree char *vgamem = NULL;
14264     g_autofree char *primary = NULL;
14265 
14266     if (!(def = virDomainVideoDefNew(xmlopt)))
14267         return NULL;
14268 
14269     ctxt->node = node;
14270 
14271     if ((primary = virXPathString("string(./model/@primary)", ctxt)) != NULL)
14272         ignore_value(virStringParseYesNo(primary, &def->primary));
14273 
14274     if ((accel_node = virXPathNode("./model/acceleration", ctxt)) &&
14275         (def->accel = virDomainVideoAccelDefParseXML(accel_node)) == NULL)
14276         return NULL;
14277 
14278     if ((res_node = virXPathNode("./model/resolution", ctxt)) &&
14279         (def->res = virDomainVideoResolutionDefParseXML(res_node)) == NULL)
14280         return NULL;
14281 
14282     if ((driver = virXPathNode("./driver", ctxt))) {
14283         if (virXMLPropEnum(driver, "name",
14284                            virDomainVideoBackendTypeFromString,
14285                            VIR_XML_PROP_NONZERO, &def->backend) < 0)
14286             return NULL;
14287         if (virDomainVirtioOptionsParseXML(driver, &def->virtio) < 0)
14288             return NULL;
14289     }
14290 
14291     if ((type = virXPathString("string(./model/@type)", ctxt))) {
14292         if ((def->type = virDomainVideoTypeFromString(type)) < 0) {
14293             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14294                            _("unknown video model '%s'"), type);
14295             return NULL;
14296         }
14297     } else {
14298         def->type = VIR_DOMAIN_VIDEO_TYPE_DEFAULT;
14299     }
14300 
14301     if ((ram = virXPathString("string(./model/@ram)", ctxt))) {
14302         if (virStrToLong_uip(ram, NULL, 10, &def->ram) < 0) {
14303             virReportError(VIR_ERR_XML_ERROR,
14304                            _("cannot parse video ram '%s'"), ram);
14305             return NULL;
14306         }
14307     }
14308 
14309     if ((vram = virXPathString("string(./model/@vram)", ctxt))) {
14310         if (virStrToLong_uip(vram, NULL, 10, &def->vram) < 0) {
14311             virReportError(VIR_ERR_XML_ERROR,
14312                            _("cannot parse video vram '%s'"), vram);
14313             return NULL;
14314         }
14315     }
14316 
14317     if ((vram64 = virXPathString("string(./model/@vram64)", ctxt))) {
14318         if (virStrToLong_uip(vram64, NULL, 10, &def->vram64) < 0) {
14319             virReportError(VIR_ERR_XML_ERROR,
14320                            _("cannot parse video vram64 '%s'"), vram64);
14321             return NULL;
14322         }
14323     }
14324 
14325     if ((vgamem = virXPathString("string(./model/@vgamem)", ctxt))) {
14326         if (virStrToLong_uip(vgamem, NULL, 10, &def->vgamem) < 0) {
14327             virReportError(VIR_ERR_XML_ERROR,
14328                            _("cannot parse video vgamem '%s'"), vgamem);
14329             return NULL;
14330         }
14331     }
14332 
14333     if ((heads = virXPathString("string(./model/@heads)", ctxt))) {
14334         if (virStrToLong_uip(heads, NULL, 10, &def->heads) < 0) {
14335             virReportError(VIR_ERR_INTERNAL_ERROR,
14336                            _("cannot parse video heads '%s'"), heads);
14337             return NULL;
14338         }
14339     }
14340 
14341     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info, flags) < 0)
14342         return NULL;
14343 
14344     def->driver = virDomainVideoDriverDefParseXML(node, ctxt);
14345 
14346     return g_steal_pointer(&def);
14347 }
14348 
14349 static virDomainHostdevDef *
virDomainHostdevDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)14350 virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt,
14351                             xmlNodePtr node,
14352                             xmlXPathContextPtr ctxt,
14353                             unsigned int flags)
14354 {
14355     virDomainHostdevDef *def;
14356     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14357     g_autofree char *mode = virXMLPropString(node, "mode");
14358     g_autofree char *type = virXMLPropString(node, "type");
14359 
14360     ctxt->node = node;
14361 
14362     if (!(def = virDomainHostdevDefNew()))
14363         goto error;
14364 
14365     if (mode) {
14366         if ((def->mode = virDomainHostdevModeTypeFromString(mode)) < 0) {
14367             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14368                            _("unknown hostdev mode '%s'"), mode);
14369             goto error;
14370         }
14371     } else {
14372         def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
14373     }
14374 
14375     switch (def->mode) {
14376     case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
14377         /* parse managed/mode/type, and the <source> element */
14378         if (virDomainHostdevDefParseXMLSubsys(node, ctxt, type, def, flags, xmlopt) < 0)
14379             goto error;
14380         break;
14381     case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
14382         /* parse managed/mode/type, and the <source> element */
14383         if (virDomainHostdevDefParseXMLCaps(node, ctxt, type, def) < 0)
14384             goto error;
14385         break;
14386     default:
14387         virReportError(VIR_ERR_INTERNAL_ERROR,
14388                        _("Unexpected hostdev mode %d"), def->mode);
14389         goto error;
14390     }
14391 
14392     if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
14393         if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, def->info,
14394                                         flags  | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT
14395                                         | VIR_DOMAIN_DEF_PARSE_ALLOW_ROM) < 0)
14396             goto error;
14397     }
14398     if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
14399         switch ((virDomainHostdevSubsysType) def->source.subsys.type) {
14400         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
14401             if (virXPathBoolean("boolean(./readonly)", ctxt))
14402                 def->readonly = true;
14403             if (virXPathBoolean("boolean(./shareable)", ctxt))
14404                 def->shareable = true;
14405             break;
14406 
14407         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
14408         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
14409         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
14410         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
14411         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
14412             break;
14413         }
14414     }
14415 
14416     if (virDomainNetTeamingInfoParseXML(ctxt, &def->teaming) < 0)
14417         goto error;
14418 
14419     return def;
14420 
14421  error:
14422     virDomainHostdevDefFree(def);
14423     return NULL;
14424 }
14425 
14426 
14427 static virDomainRedirdevDef *
virDomainRedirdevDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)14428 virDomainRedirdevDefParseXML(virDomainXMLOption *xmlopt,
14429                              xmlNodePtr node,
14430                              xmlXPathContextPtr ctxt,
14431                              unsigned int flags)
14432 {
14433     virDomainRedirdevDef *def;
14434     g_autofree char *bus = NULL;
14435     g_autofree char *type = NULL;
14436 
14437     def = g_new0(virDomainRedirdevDef, 1);
14438 
14439     if (!(def->source = virDomainChrSourceDefNew(xmlopt)))
14440         goto error;
14441 
14442     bus = virXMLPropString(node, "bus");
14443     if (bus) {
14444         if ((def->bus = virDomainRedirdevBusTypeFromString(bus)) < 0) {
14445             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14446                            _("unknown redirdev bus '%s'"), bus);
14447             goto error;
14448         }
14449     } else {
14450         def->bus = VIR_DOMAIN_REDIRDEV_BUS_USB;
14451     }
14452 
14453     type = virXMLPropString(node, "type");
14454     if (type) {
14455         if ((def->source->type = virDomainChrTypeFromString(type)) < 0) {
14456             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14457                            _("unknown redirdev character device type '%s'"), type);
14458             goto error;
14459         }
14460     } else {
14461         virReportError(VIR_ERR_INTERNAL_ERROR,
14462                        "%s", _("missing type in redirdev"));
14463         goto error;
14464     }
14465 
14466     /* boot gets parsed in virDomainDeviceInfoParseXML
14467      * source gets parsed in virDomainChrSourceDefParseXML */
14468     if (virDomainChrSourceDefParseXML(def->source, node, flags,
14469                                       NULL, ctxt) < 0)
14470         goto error;
14471 
14472     if (def->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC)
14473         def->source->data.spicevmc = VIR_DOMAIN_CHR_SPICEVMC_USBREDIR;
14474 
14475     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &def->info,
14476                                     flags | VIR_DOMAIN_DEF_PARSE_ALLOW_BOOT) < 0)
14477         goto error;
14478 
14479     if (def->bus == VIR_DOMAIN_REDIRDEV_BUS_USB &&
14480         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
14481         def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
14482         virReportError(VIR_ERR_XML_ERROR, "%s",
14483                        _("Invalid address for a USB device"));
14484         goto error;
14485     }
14486 
14487     return def;
14488 
14489  error:
14490     virDomainRedirdevDefFree(def);
14491     return NULL;
14492 }
14493 
14494 /*
14495  * This is the helper function to convert USB device version from a
14496  * format of JJ.MN to a format of 0xJJMN where JJ is the major
14497  * version number, M is the minor version number and N is the
14498  * sub minor version number.
14499  * e.g. USB version 2.0 is reported as 0x0200,
14500  *      USB version 4.07 as 0x0407
14501  */
14502 static int
virDomainRedirFilterUSBVersionHelper(const char * version,virDomainRedirFilterUSBDevDef * def)14503 virDomainRedirFilterUSBVersionHelper(const char *version,
14504                                      virDomainRedirFilterUSBDevDef *def)
14505 {
14506     unsigned int major, minor;
14507     char *s = NULL;
14508 
14509     if ((virStrToLong_ui(version, &s, 10, &major)) < 0 ||
14510         *s++ != '.' ||
14511         (virStrToLong_ui(s, NULL, 10, &minor)) < 0)
14512         goto error;
14513 
14514     if (major >= 100 || minor >= 100)
14515         goto error;
14516 
14517     /* Treat JJ.M as JJ.M0, not JJ.0M */
14518     if (strlen(s) == 1)
14519         minor *= 10;
14520 
14521     def->version = (major / 10) << 12 | (major % 10) << 8 |
14522                    (minor / 10) << 4 | (minor % 10) << 0;
14523 
14524     return 0;
14525 
14526  error:
14527     virReportError(VIR_ERR_XML_ERROR,
14528                    _("Cannot parse USB device version %s"), version);
14529     return -1;
14530 }
14531 
14532 static virDomainRedirFilterUSBDevDef *
virDomainRedirFilterUSBDevDefParseXML(xmlNodePtr node)14533 virDomainRedirFilterUSBDevDefParseXML(xmlNodePtr node)
14534 {
14535     g_autofree virDomainRedirFilterUSBDevDef *def = NULL;
14536     g_autofree char *version = NULL;
14537     virTristateBool allow;
14538 
14539     def = g_new0(virDomainRedirFilterUSBDevDef, 1);
14540 
14541     if (virXMLPropInt(node, "class", 0, VIR_XML_PROP_NONE, &def->usbClass, -1) < 0)
14542         return NULL;
14543 
14544     if (def->usbClass != -1 && def->usbClass &~ 0xFF) {
14545         virReportError(VIR_ERR_INTERNAL_ERROR,
14546                        _("Invalid USB Class code 0x%x"), def->usbClass);
14547         return NULL;
14548     }
14549 
14550     if (virXMLPropInt(node, "vendor", 0, VIR_XML_PROP_NONE, &def->vendor, -1) < 0)
14551         return NULL;
14552 
14553     if (virXMLPropInt(node, "product", 0, VIR_XML_PROP_NONE, &def->product, -1) < 0)
14554         return NULL;
14555 
14556     version = virXMLPropString(node, "version");
14557     if (version) {
14558         if (STREQ(version, "-1"))
14559             def->version = -1;
14560         else if ((virDomainRedirFilterUSBVersionHelper(version, def)) < 0)
14561             return NULL;
14562     } else {
14563         def->version = -1;
14564     }
14565 
14566     if (virXMLPropTristateBool(node, "allow", VIR_XML_PROP_REQUIRED, &allow) < 0)
14567         return NULL;
14568 
14569     def->allow = allow == VIR_TRISTATE_BOOL_YES;
14570 
14571     return g_steal_pointer(&def);
14572 }
14573 
14574 static virDomainRedirFilterDef *
virDomainRedirFilterDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt)14575 virDomainRedirFilterDefParseXML(xmlNodePtr node,
14576                                 xmlXPathContextPtr ctxt)
14577 {
14578     int n;
14579     size_t i;
14580     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14581     virDomainRedirFilterDef *def = NULL;
14582     g_autofree xmlNodePtr *nodes = NULL;
14583 
14584     def = g_new0(virDomainRedirFilterDef, 1);
14585 
14586     ctxt->node = node;
14587     if ((n = virXPathNodeSet("./usbdev", ctxt, &nodes)) < 0)
14588         goto error;
14589 
14590     if (n)
14591         def->usbdevs = g_new0(virDomainRedirFilterUSBDevDef *, n);
14592 
14593     for (i = 0; i < n; i++) {
14594         virDomainRedirFilterUSBDevDef *usbdev =
14595             virDomainRedirFilterUSBDevDefParseXML(nodes[i]);
14596 
14597         if (!usbdev)
14598             goto error;
14599         def->usbdevs[def->nusbdevs++] = usbdev;
14600     }
14601 
14602     return def;
14603 
14604  error:
14605     virDomainRedirFilterDefFree(def);
14606     return NULL;
14607 }
14608 
14609 static int
virDomainEventActionParseXML(xmlXPathContextPtr ctxt,const char * name,const char * xpath,int * val,int defaultVal,virEventActionFromStringFunc convFunc)14610 virDomainEventActionParseXML(xmlXPathContextPtr ctxt,
14611                              const char *name,
14612                              const char *xpath,
14613                              int *val,
14614                              int defaultVal,
14615                              virEventActionFromStringFunc convFunc)
14616 {
14617     g_autofree char *tmp = virXPathString(xpath, ctxt);
14618 
14619     if (tmp == NULL) {
14620         *val = defaultVal;
14621     } else {
14622         *val = convFunc(tmp);
14623         if (*val < 0) {
14624             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14625                            _("unknown %s action: %s"), name, tmp);
14626             return -1;
14627         }
14628     }
14629     return 0;
14630 }
14631 
14632 static int
virDomainPMStateParseXML(xmlXPathContextPtr ctxt,const char * xpath,int * val)14633 virDomainPMStateParseXML(xmlXPathContextPtr ctxt,
14634                          const char *xpath,
14635                          int *val)
14636 {
14637     g_autofree char *tmp = virXPathString(xpath, ctxt);
14638 
14639     if (tmp) {
14640         *val = virTristateBoolTypeFromString(tmp);
14641         if (*val < 0) {
14642             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14643                            _("unknown PM state value %s"), tmp);
14644             return -1;
14645         }
14646     }
14647 
14648     return 0;
14649 }
14650 
14651 
14652 static int
virDomainPerfEventDefParseXML(virDomainPerfDef * perf,xmlNodePtr node)14653 virDomainPerfEventDefParseXML(virDomainPerfDef *perf,
14654                               xmlNodePtr node)
14655 {
14656     virPerfEventType name;
14657     virTristateBool enabled;
14658 
14659     if (virXMLPropEnum(node, "name", virPerfEventTypeFromString,
14660                        VIR_XML_PROP_REQUIRED, &name) < 0)
14661         return -1;
14662 
14663     if (virXMLPropTristateBool(node, "enabled", VIR_XML_PROP_REQUIRED, &enabled) < 0)
14664         return -1;
14665 
14666     if (perf->events[name] != VIR_TRISTATE_BOOL_ABSENT) {
14667         virReportError(VIR_ERR_XML_ERROR,
14668                        _("perf event '%s' was already specified"),
14669                        virPerfEventTypeToString(name));
14670         return -1;
14671     }
14672 
14673     perf->events[name] = enabled;
14674 
14675     return 0;
14676 }
14677 
14678 static int
virDomainPerfDefParseXML(virDomainDef * def,xmlXPathContextPtr ctxt)14679 virDomainPerfDefParseXML(virDomainDef *def,
14680                          xmlXPathContextPtr ctxt)
14681 {
14682     size_t i;
14683     int n;
14684     g_autofree xmlNodePtr *nodes = NULL;
14685 
14686     if ((n = virXPathNodeSet("./perf/event", ctxt, &nodes)) < 0)
14687         return n;
14688 
14689     for (i = 0; i < n; i++) {
14690         if (virDomainPerfEventDefParseXML(&def->perf, nodes[i]) < 0)
14691             return -1;
14692     }
14693 
14694     return 0;
14695 }
14696 
14697 static int
virDomainMemorySourceDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virDomainMemoryDef * def)14698 virDomainMemorySourceDefParseXML(xmlNodePtr node,
14699                                  xmlXPathContextPtr ctxt,
14700                                  virDomainMemoryDef *def)
14701 {
14702     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14703     g_autofree char *nodemask = NULL;
14704 
14705     ctxt->node = node;
14706 
14707     switch (def->model) {
14708     case VIR_DOMAIN_MEMORY_MODEL_DIMM:
14709     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
14710         if (virDomainParseMemory("./pagesize", "./pagesize/@unit", ctxt,
14711                                  &def->pagesize, false, false) < 0)
14712             return -1;
14713 
14714         if ((nodemask = virXPathString("string(./nodemask)", ctxt))) {
14715             if (virBitmapParse(nodemask, &def->sourceNodes,
14716                                VIR_DOMAIN_CPUMASK_LEN) < 0)
14717                 return -1;
14718 
14719             if (virBitmapIsAllClear(def->sourceNodes)) {
14720                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
14721                                _("Invalid value of 'nodemask': %s"), nodemask);
14722                 return -1;
14723             }
14724         }
14725         break;
14726 
14727     case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
14728         def->nvdimmPath = virXPathString("string(./path)", ctxt);
14729 
14730         if (virDomainParseMemory("./alignsize", "./alignsize/@unit", ctxt,
14731                                  &def->alignsize, false, false) < 0)
14732             return -1;
14733 
14734         if (virXPathBoolean("boolean(./pmem)", ctxt))
14735             def->nvdimmPmem = true;
14736 
14737         break;
14738 
14739     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
14740         def->nvdimmPath = virXPathString("string(./path)", ctxt);
14741         break;
14742 
14743     case VIR_DOMAIN_MEMORY_MODEL_NONE:
14744     case VIR_DOMAIN_MEMORY_MODEL_LAST:
14745         break;
14746     }
14747 
14748     return 0;
14749 }
14750 
14751 
14752 static int
virDomainMemoryTargetDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virDomainMemoryDef * def)14753 virDomainMemoryTargetDefParseXML(xmlNodePtr node,
14754                                  xmlXPathContextPtr ctxt,
14755                                  virDomainMemoryDef *def)
14756 {
14757     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14758     int rv;
14759 
14760     ctxt->node = node;
14761 
14762     /* initialize to value which marks that the user didn't specify it */
14763     def->targetNode = -1;
14764 
14765     if ((rv = virXPathInt("string(./node)", ctxt, &def->targetNode)) == -2 ||
14766         (rv == 0 && def->targetNode < 0)) {
14767         virReportError(VIR_ERR_XML_ERROR, "%s",
14768                        _("invalid value of memory device node"));
14769         return -1;
14770     }
14771 
14772     if (virDomainParseMemory("./size", "./size/@unit", ctxt,
14773                              &def->size, true, false) < 0)
14774         return -1;
14775 
14776     switch (def->model) {
14777     case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
14778         if (virDomainParseMemory("./label/size", "./label/size/@unit", ctxt,
14779                                  &def->labelsize, false, false) < 0)
14780             return -1;
14781 
14782         if (def->labelsize && def->labelsize < 128) {
14783             virReportError(VIR_ERR_XML_ERROR, "%s",
14784                            _("nvdimm label must be at least 128KiB"));
14785             return -1;
14786         }
14787 
14788         if (def->labelsize >= def->size) {
14789             virReportError(VIR_ERR_XML_ERROR, "%s",
14790                            _("label size must be smaller than NVDIMM size"));
14791             return -1;
14792         }
14793 
14794         if (virXPathBoolean("boolean(./readonly)", ctxt))
14795             def->readonly = true;
14796         break;
14797 
14798     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
14799         if (virDomainParseMemory("./block", "./block/@unit", ctxt,
14800                                  &def->blocksize, false, false) < 0)
14801             return -1;
14802 
14803         if (virDomainParseMemory("./requested", "./requested/@unit", ctxt,
14804                                  &def->requestedsize, false, false) < 0)
14805             return -1;
14806         break;
14807 
14808     case VIR_DOMAIN_MEMORY_MODEL_NONE:
14809     case VIR_DOMAIN_MEMORY_MODEL_DIMM:
14810     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
14811     case VIR_DOMAIN_MEMORY_MODEL_LAST:
14812         break;
14813     }
14814 
14815     return 0;
14816 }
14817 
14818 
14819 static int
virDomainSEVDefParseXML(virDomainSEVDef * def,xmlXPathContextPtr ctxt)14820 virDomainSEVDefParseXML(virDomainSEVDef *def,
14821                         xmlXPathContextPtr ctxt)
14822 {
14823     unsigned long policy;
14824     int rc;
14825 
14826     if (virXPathULongHex("string(./policy)", ctxt, &policy) < 0) {
14827         virReportError(VIR_ERR_XML_ERROR, "%s",
14828                        _("failed to get launch security policy"));
14829         return -1;
14830     }
14831 
14832     /* the following attributes are platform dependent and if missing, we can
14833      * autofill them from domain capabilities later
14834      */
14835     rc = virXPathUInt("string(./cbitpos)", ctxt, &def->cbitpos);
14836     if (rc == 0) {
14837         def->haveCbitpos = true;
14838     } else if (rc == -2) {
14839         virReportError(VIR_ERR_XML_ERROR, "%s",
14840                        _("Invalid format for launch security cbitpos"));
14841         return -1;
14842     }
14843 
14844     rc = virXPathUInt("string(./reducedPhysBits)", ctxt,
14845                       &def->reduced_phys_bits);
14846     if (rc == 0) {
14847         def->haveReducedPhysBits = true;
14848     } else if (rc == -2) {
14849         virReportError(VIR_ERR_XML_ERROR, "%s",
14850                        _("Invalid format for launch security "
14851                          "reduced-phys-bits"));
14852         return -1;
14853     }
14854 
14855     def->policy = policy;
14856     def->dh_cert = virXPathString("string(./dhCert)", ctxt);
14857     def->session = virXPathString("string(./session)", ctxt);
14858 
14859     return 0;
14860 }
14861 
14862 
14863 static virDomainSecDef *
virDomainSecDefParseXML(xmlNodePtr lsecNode,xmlXPathContextPtr ctxt)14864 virDomainSecDefParseXML(xmlNodePtr lsecNode,
14865                         xmlXPathContextPtr ctxt)
14866 {
14867     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14868     g_autoptr(virDomainSecDef) sec = g_new0(virDomainSecDef, 1);
14869 
14870     ctxt->node = lsecNode;
14871 
14872     if (virXMLPropEnum(lsecNode, "type", virDomainLaunchSecurityTypeFromString,
14873                        VIR_XML_PROP_NONZERO | VIR_XML_PROP_REQUIRED,
14874                        &sec->sectype) < 0)
14875         return NULL;
14876 
14877     switch ((virDomainLaunchSecurity) sec->sectype) {
14878     case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
14879         if (virDomainSEVDefParseXML(&sec->data.sev, ctxt) < 0)
14880             return NULL;
14881         break;
14882     case VIR_DOMAIN_LAUNCH_SECURITY_PV:
14883         break;
14884     case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
14885     case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
14886     default:
14887         virReportError(VIR_ERR_XML_ERROR,
14888                        _("unsupported launch security type '%s'"),
14889                        virDomainLaunchSecurityTypeToString(sec->sectype));
14890         return NULL;
14891     }
14892 
14893     return g_steal_pointer(&sec);
14894 }
14895 
14896 
14897 static virDomainMemoryDef *
virDomainMemoryDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr memdevNode,xmlXPathContextPtr ctxt,unsigned int flags)14898 virDomainMemoryDefParseXML(virDomainXMLOption *xmlopt,
14899                            xmlNodePtr memdevNode,
14900                            xmlXPathContextPtr ctxt,
14901                            unsigned int flags)
14902 {
14903     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14904     xmlNodePtr node;
14905     virDomainMemoryDef *def;
14906     g_autofree char *tmp = NULL;
14907 
14908     def = g_new0(virDomainMemoryDef, 1);
14909 
14910     ctxt->node = memdevNode;
14911 
14912     if (virXMLPropEnum(memdevNode, "model", virDomainMemoryModelTypeFromString,
14913                        VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
14914                        &def->model) < 0)
14915         goto error;
14916 
14917     if (virXMLPropEnum(memdevNode, "access", virDomainMemoryAccessTypeFromString,
14918                        VIR_XML_PROP_NONZERO, &def->access) < 0)
14919         goto error;
14920 
14921     if (virXMLPropTristateBool(memdevNode, "discard", VIR_XML_PROP_NONE,
14922                                &def->discard) < 0)
14923         goto error;
14924 
14925     /* Extract NVDIMM UUID. */
14926     if (def->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM &&
14927         (tmp = virXPathString("string(./uuid[1])", ctxt))) {
14928         def->uuid = g_new0(unsigned char, VIR_UUID_BUFLEN);
14929 
14930         if (virUUIDParse(tmp, def->uuid) < 0) {
14931             virReportError(VIR_ERR_INTERNAL_ERROR,
14932                            "%s", _("malformed uuid element"));
14933             goto error;
14934         }
14935     }
14936 
14937     /* source */
14938     if ((node = virXPathNode("./source", ctxt)) &&
14939         virDomainMemorySourceDefParseXML(node, ctxt, def) < 0)
14940         goto error;
14941 
14942     /* target */
14943     if (!(node = virXPathNode("./target", ctxt))) {
14944         virReportError(VIR_ERR_XML_ERROR, "%s",
14945                        _("missing <target> element for <memory> device"));
14946         goto error;
14947     }
14948 
14949     if (virDomainMemoryTargetDefParseXML(node, ctxt, def) < 0)
14950         goto error;
14951 
14952     if (virDomainDeviceInfoParseXML(xmlopt, memdevNode, ctxt,
14953                                     &def->info, flags) < 0)
14954         goto error;
14955 
14956     return def;
14957 
14958  error:
14959     virDomainMemoryDefFree(def);
14960     return NULL;
14961 }
14962 
14963 
14964 static virDomainIOMMUDef *
virDomainIOMMUDefParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt)14965 virDomainIOMMUDefParseXML(xmlNodePtr node,
14966                           xmlXPathContextPtr ctxt)
14967 {
14968     VIR_XPATH_NODE_AUTORESTORE(ctxt)
14969     xmlNodePtr driver;
14970     g_autoptr(virDomainIOMMUDef) iommu = NULL;
14971 
14972     ctxt->node = node;
14973 
14974     iommu = virDomainIOMMUDefNew();
14975 
14976     if (virXMLPropEnum(node, "model", virDomainIOMMUModelTypeFromString,
14977                        VIR_XML_PROP_REQUIRED, &iommu->model) < 0)
14978         return NULL;
14979 
14980     if ((driver = virXPathNode("./driver", ctxt))) {
14981         if (virXMLPropTristateSwitch(driver, "intremap", VIR_XML_PROP_NONE,
14982                                      &iommu->intremap) < 0)
14983             return NULL;
14984 
14985         if (virXMLPropTristateSwitch(driver, "caching_mode", VIR_XML_PROP_NONE,
14986                                      &iommu->caching_mode) < 0)
14987             return NULL;
14988 
14989         if (virXMLPropTristateSwitch(driver, "iotlb", VIR_XML_PROP_NONE,
14990                                      &iommu->iotlb) < 0)
14991             return NULL;
14992 
14993         if (virXMLPropTristateSwitch(driver, "eim", VIR_XML_PROP_NONE,
14994                                      &iommu->eim) < 0)
14995             return NULL;
14996 
14997         if (virXMLPropUInt(driver, "aw_bits", 10, VIR_XML_PROP_NONE,
14998                            &iommu->aw_bits) < 0)
14999             return NULL;
15000     }
15001 
15002     return g_steal_pointer(&iommu);
15003 }
15004 
15005 
15006 static virDomainVsockDef *
virDomainVsockDefParseXML(virDomainXMLOption * xmlopt,xmlNodePtr node,xmlXPathContextPtr ctxt,unsigned int flags)15007 virDomainVsockDefParseXML(virDomainXMLOption *xmlopt,
15008                           xmlNodePtr node,
15009                           xmlXPathContextPtr ctxt,
15010                           unsigned int flags)
15011 {
15012     VIR_XPATH_NODE_AUTORESTORE(ctxt)
15013     xmlNodePtr cid;
15014     g_autoptr(virDomainVsockDef) vsock = NULL;
15015 
15016     ctxt->node = node;
15017 
15018     if (!(vsock = virDomainVsockDefNew(xmlopt)))
15019         return NULL;
15020 
15021     if (virXMLPropEnum(node, "model", virDomainVsockModelTypeFromString,
15022                        VIR_XML_PROP_NONE, &vsock->model) < 0)
15023         return NULL;
15024 
15025     if ((cid = virXPathNode("./cid", ctxt))) {
15026         if (virXMLPropUInt(cid, "address", 10,
15027                            VIR_XML_PROP_NONZERO,
15028                            &vsock->guest_cid) < 0)
15029             return NULL;
15030 
15031         if (virXMLPropTristateBool(cid, "auto", VIR_XML_PROP_NONE,
15032                                    &vsock->auto_cid) < 0)
15033             return NULL;
15034     }
15035 
15036     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt, &vsock->info, flags) < 0)
15037         return NULL;
15038 
15039     if (virDomainVirtioOptionsParseXML(virXPathNode("./driver", ctxt),
15040                                        &vsock->virtio) < 0)
15041         return NULL;
15042 
15043 
15044     return g_steal_pointer(&vsock);
15045 }
15046 
15047 virDomainDeviceDef *
virDomainDeviceDefParse(const char * xmlStr,const virDomainDef * def,virDomainXMLOption * xmlopt,void * parseOpaque,unsigned int flags)15048 virDomainDeviceDefParse(const char *xmlStr,
15049                         const virDomainDef *def,
15050                         virDomainXMLOption *xmlopt,
15051                         void *parseOpaque,
15052                         unsigned int flags)
15053 {
15054     g_autoptr(xmlDoc) xml = NULL;
15055     xmlNodePtr node;
15056     g_autoptr(xmlXPathContext) ctxt = NULL;
15057     g_autoptr(virDomainDeviceDef) dev = NULL;
15058 
15059     if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"), &ctxt)))
15060         return NULL;
15061 
15062     node = ctxt->node;
15063 
15064     dev = g_new0(virDomainDeviceDef, 1);
15065 
15066     if ((dev->type = virDomainDeviceTypeFromString((const char *) node->name)) < 0) {
15067         /* Some crazy mapping of serial, parallel, console and channel to
15068          * VIR_DOMAIN_DEVICE_CHR. */
15069         if (virXMLNodeNameEqual(node, "channel") ||
15070             virXMLNodeNameEqual(node, "console") ||
15071             virXMLNodeNameEqual(node, "parallel") ||
15072             virXMLNodeNameEqual(node, "serial")) {
15073             dev->type = VIR_DOMAIN_DEVICE_CHR;
15074         } else {
15075             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
15076                            _("unknown device type '%s'"),
15077                            node->name);
15078             return NULL;
15079         }
15080     }
15081 
15082     switch ((virDomainDeviceType) dev->type) {
15083     case VIR_DOMAIN_DEVICE_DISK:
15084         if (!(dev->data.disk = virDomainDiskDefParseXML(xmlopt, node, ctxt,
15085                                                         flags)))
15086             return NULL;
15087         break;
15088     case VIR_DOMAIN_DEVICE_LEASE:
15089         if (!(dev->data.lease = virDomainLeaseDefParseXML(node, ctxt)))
15090             return NULL;
15091         break;
15092     case VIR_DOMAIN_DEVICE_FS:
15093         if (!(dev->data.fs = virDomainFSDefParseXML(xmlopt, node, ctxt, flags)))
15094             return NULL;
15095         break;
15096     case VIR_DOMAIN_DEVICE_NET:
15097         if (!(dev->data.net = virDomainNetDefParseXML(xmlopt, node, ctxt, flags)))
15098             return NULL;
15099         break;
15100     case VIR_DOMAIN_DEVICE_INPUT:
15101         if (!(dev->data.input = virDomainInputDefParseXML(xmlopt, def, node,
15102                                                           ctxt, flags)))
15103             return NULL;
15104         break;
15105     case VIR_DOMAIN_DEVICE_SOUND:
15106         if (!(dev->data.sound = virDomainSoundDefParseXML(xmlopt, node,
15107                                                           ctxt, flags)))
15108             return NULL;
15109         break;
15110     case VIR_DOMAIN_DEVICE_AUDIO:
15111         if (!(dev->data.audio = virDomainAudioDefParseXML(xmlopt, node, ctxt)))
15112             return NULL;
15113         break;
15114     case VIR_DOMAIN_DEVICE_WATCHDOG:
15115         if (!(dev->data.watchdog = virDomainWatchdogDefParseXML(xmlopt, node,
15116                                                                 ctxt, flags)))
15117             return NULL;
15118         break;
15119     case VIR_DOMAIN_DEVICE_VIDEO:
15120         if (!(dev->data.video = virDomainVideoDefParseXML(xmlopt, node,
15121                                                           ctxt, flags)))
15122             return NULL;
15123         break;
15124     case VIR_DOMAIN_DEVICE_HOSTDEV:
15125         if (!(dev->data.hostdev = virDomainHostdevDefParseXML(xmlopt, node,
15126                                                               ctxt,
15127                                                               flags)))
15128             return NULL;
15129         break;
15130     case VIR_DOMAIN_DEVICE_CONTROLLER:
15131         if (!(dev->data.controller = virDomainControllerDefParseXML(xmlopt, node,
15132                                                                     ctxt, flags)))
15133             return NULL;
15134         break;
15135     case VIR_DOMAIN_DEVICE_GRAPHICS:
15136         if (!(dev->data.graphics = virDomainGraphicsDefParseXML(xmlopt, node,
15137                                                                 ctxt, flags)))
15138             return NULL;
15139         break;
15140     case VIR_DOMAIN_DEVICE_HUB:
15141         if (!(dev->data.hub = virDomainHubDefParseXML(xmlopt, node,
15142                                                       ctxt, flags)))
15143             return NULL;
15144         break;
15145     case VIR_DOMAIN_DEVICE_REDIRDEV:
15146         if (!(dev->data.redirdev = virDomainRedirdevDefParseXML(xmlopt, node,
15147                                                                 ctxt, flags)))
15148             return NULL;
15149         break;
15150     case VIR_DOMAIN_DEVICE_RNG:
15151         if (!(dev->data.rng = virDomainRNGDefParseXML(xmlopt, node,
15152                                                       ctxt, flags)))
15153             return NULL;
15154         break;
15155     case VIR_DOMAIN_DEVICE_CHR:
15156         if (!(dev->data.chr = virDomainChrDefParseXML(xmlopt,
15157                                                       ctxt,
15158                                                       node,
15159                                                       flags)))
15160             return NULL;
15161         break;
15162     case VIR_DOMAIN_DEVICE_SMARTCARD:
15163         if (!(dev->data.smartcard = virDomainSmartcardDefParseXML(xmlopt, node,
15164                                                                   ctxt, flags)))
15165             return NULL;
15166         break;
15167     case VIR_DOMAIN_DEVICE_MEMBALLOON:
15168         if (!(dev->data.memballoon = virDomainMemballoonDefParseXML(xmlopt,
15169                                                                     node,
15170                                                                     ctxt,
15171                                                                     flags)))
15172             return NULL;
15173         break;
15174     case VIR_DOMAIN_DEVICE_NVRAM:
15175         if (!(dev->data.nvram = virDomainNVRAMDefParseXML(xmlopt, node,
15176                                                           ctxt, flags)))
15177             return NULL;
15178         break;
15179     case VIR_DOMAIN_DEVICE_SHMEM:
15180         if (!(dev->data.shmem = virDomainShmemDefParseXML(xmlopt, node,
15181                                                           ctxt, flags)))
15182             return NULL;
15183         break;
15184     case VIR_DOMAIN_DEVICE_TPM:
15185         if (!(dev->data.tpm = virDomainTPMDefParseXML(xmlopt, node, ctxt, flags)))
15186             return NULL;
15187         break;
15188     case VIR_DOMAIN_DEVICE_PANIC:
15189         if (!(dev->data.panic = virDomainPanicDefParseXML(xmlopt, node,
15190                                                           ctxt, flags)))
15191             return NULL;
15192         break;
15193     case VIR_DOMAIN_DEVICE_MEMORY:
15194         if (!(dev->data.memory = virDomainMemoryDefParseXML(xmlopt, node,
15195                                                             ctxt, flags)))
15196             return NULL;
15197         break;
15198     case VIR_DOMAIN_DEVICE_IOMMU:
15199         if (!(dev->data.iommu = virDomainIOMMUDefParseXML(node, ctxt)))
15200             return NULL;
15201         break;
15202     case VIR_DOMAIN_DEVICE_VSOCK:
15203         if (!(dev->data.vsock = virDomainVsockDefParseXML(xmlopt, node, ctxt,
15204                                                           flags)))
15205             return NULL;
15206         break;
15207     case VIR_DOMAIN_DEVICE_NONE:
15208     case VIR_DOMAIN_DEVICE_LAST:
15209         break;
15210     }
15211 
15212     /* callback to fill driver specific device aspects */
15213     if (virDomainDeviceDefPostParseOne(dev, def, flags,
15214                                        xmlopt, parseOpaque) < 0)
15215         return NULL;
15216 
15217     /* validate the configuration */
15218     if (virDomainDeviceDefValidate(dev, def, flags, xmlopt, parseOpaque) < 0)
15219         return NULL;
15220 
15221     return g_steal_pointer(&dev);
15222 }
15223 
15224 
15225 virDomainDiskDef *
virDomainDiskDefParse(const char * xmlStr,virDomainXMLOption * xmlopt,unsigned int flags)15226 virDomainDiskDefParse(const char *xmlStr,
15227                       virDomainXMLOption *xmlopt,
15228                       unsigned int flags)
15229 {
15230     g_autoptr(xmlDoc) xml = NULL;
15231     g_autoptr(xmlXPathContext) ctxt = NULL;
15232 
15233     if (!(xml = virXMLParseStringCtxtRoot(xmlStr, _("(disk_definition)"), "disk", &ctxt)))
15234         return NULL;
15235 
15236     return virDomainDiskDefParseXML(xmlopt, ctxt->node, ctxt, flags);
15237 }
15238 
15239 
15240 virStorageSource *
virDomainDiskDefParseSource(const char * xmlStr,virDomainXMLOption * xmlopt,unsigned int flags)15241 virDomainDiskDefParseSource(const char *xmlStr,
15242                             virDomainXMLOption *xmlopt,
15243                             unsigned int flags)
15244 {
15245     g_autoptr(xmlDoc) xml = NULL;
15246     g_autoptr(xmlXPathContext) ctxt = NULL;
15247     g_autoptr(virStorageSource) src = NULL;
15248     xmlNodePtr driverNode;
15249 
15250     if (!(xml = virXMLParseStringCtxtRoot(xmlStr, _("(disk_definition)"), "disk", &ctxt)))
15251         return NULL;
15252 
15253     if (!(src = virDomainDiskDefParseSourceXML(xmlopt, ctxt->node, ctxt, flags)))
15254         return NULL;
15255 
15256     if ((driverNode = virXPathNode("./driver", ctxt))) {
15257         if (virDomainDiskDefDriverSourceParseXML(src, driverNode, ctxt) < 0)
15258             return NULL;
15259     }
15260 
15261     if (virStorageSourceIsEmpty(src)) {
15262         virReportError(VIR_ERR_NO_SOURCE, NULL);
15263         return NULL;
15264     }
15265 
15266     if (virDomainDiskDefValidateSource(src) < 0)
15267         return NULL;
15268 
15269     return g_steal_pointer(&src);
15270 }
15271 
15272 
15273 static const char *
virDomainChrTargetTypeToString(int deviceType,int targetType)15274 virDomainChrTargetTypeToString(int deviceType,
15275                                int targetType)
15276 {
15277     const char *type = NULL;
15278 
15279     switch (deviceType) {
15280     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
15281         type = virDomainChrChannelTargetTypeToString(targetType);
15282         break;
15283     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
15284         type = virDomainChrConsoleTargetTypeToString(targetType);
15285         break;
15286     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
15287         type = virDomainChrSerialTargetTypeToString(targetType);
15288         break;
15289     default:
15290         break;
15291     }
15292 
15293     return type;
15294 }
15295 
15296 int
virDomainHostdevInsert(virDomainDef * def,virDomainHostdevDef * hostdev)15297 virDomainHostdevInsert(virDomainDef *def, virDomainHostdevDef *hostdev)
15298 {
15299     VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev);
15300 
15301     return 0;
15302 }
15303 
15304 virDomainHostdevDef *
virDomainHostdevRemove(virDomainDef * def,size_t i)15305 virDomainHostdevRemove(virDomainDef *def, size_t i)
15306 {
15307     virDomainHostdevDef *hostdev = def->hostdevs[i];
15308 
15309     VIR_DELETE_ELEMENT(def->hostdevs, i, def->nhostdevs);
15310     return hostdev;
15311 }
15312 
15313 
15314 static int
virDomainHostdevMatchSubsysUSB(virDomainHostdevDef * first,virDomainHostdevDef * second)15315 virDomainHostdevMatchSubsysUSB(virDomainHostdevDef *first,
15316                                virDomainHostdevDef *second)
15317 {
15318     virDomainHostdevSubsysUSB *first_usbsrc = &first->source.subsys.u.usb;
15319     virDomainHostdevSubsysUSB *second_usbsrc = &second->source.subsys.u.usb;
15320 
15321     if (first_usbsrc->bus && first_usbsrc->device) {
15322         /* specified by bus location on host */
15323         if (first_usbsrc->bus == second_usbsrc->bus &&
15324             first_usbsrc->device == second_usbsrc->device)
15325             return 1;
15326     } else {
15327         /* specified by product & vendor id */
15328         if (first_usbsrc->product == second_usbsrc->product &&
15329             first_usbsrc->vendor == second_usbsrc->vendor)
15330             return 1;
15331     }
15332     return 0;
15333 }
15334 
15335 static int
virDomainHostdevMatchSubsysPCI(virDomainHostdevDef * first,virDomainHostdevDef * second)15336 virDomainHostdevMatchSubsysPCI(virDomainHostdevDef *first,
15337                                virDomainHostdevDef *second)
15338 {
15339     virDomainHostdevSubsysPCI *first_pcisrc = &first->source.subsys.u.pci;
15340     virDomainHostdevSubsysPCI *second_pcisrc = &second->source.subsys.u.pci;
15341 
15342     if (first_pcisrc->addr.domain == second_pcisrc->addr.domain &&
15343         first_pcisrc->addr.bus == second_pcisrc->addr.bus &&
15344         first_pcisrc->addr.slot == second_pcisrc->addr.slot &&
15345         first_pcisrc->addr.function == second_pcisrc->addr.function)
15346         return 1;
15347     return 0;
15348 }
15349 
15350 static int
virDomainHostdevMatchSubsysSCSIHost(virDomainHostdevDef * first,virDomainHostdevDef * second)15351 virDomainHostdevMatchSubsysSCSIHost(virDomainHostdevDef *first,
15352                                     virDomainHostdevDef *second)
15353 {
15354     virDomainHostdevSubsysSCSIHost *first_scsihostsrc =
15355         &first->source.subsys.u.scsi.u.host;
15356     virDomainHostdevSubsysSCSIHost *second_scsihostsrc =
15357         &second->source.subsys.u.scsi.u.host;
15358 
15359     if (STREQ(first_scsihostsrc->adapter, second_scsihostsrc->adapter) &&
15360         first_scsihostsrc->bus == second_scsihostsrc->bus &&
15361         first_scsihostsrc->target == second_scsihostsrc->target &&
15362         first_scsihostsrc->unit == second_scsihostsrc->unit)
15363         return 1;
15364     return 0;
15365 }
15366 
15367 static int
virDomainHostdevMatchSubsysSCSIiSCSI(virDomainHostdevDef * first,virDomainHostdevDef * second)15368 virDomainHostdevMatchSubsysSCSIiSCSI(virDomainHostdevDef *first,
15369                                      virDomainHostdevDef *second)
15370 {
15371     virDomainHostdevSubsysSCSIiSCSI *first_iscsisrc =
15372         &first->source.subsys.u.scsi.u.iscsi;
15373     virDomainHostdevSubsysSCSIiSCSI *second_iscsisrc =
15374         &second->source.subsys.u.scsi.u.iscsi;
15375 
15376     if (STREQ(first_iscsisrc->src->hosts[0].name, second_iscsisrc->src->hosts[0].name) &&
15377         first_iscsisrc->src->hosts[0].port == second_iscsisrc->src->hosts[0].port &&
15378         STREQ(first_iscsisrc->src->path, second_iscsisrc->src->path))
15379         return 1;
15380     return 0;
15381 }
15382 
15383 static int
virDomainHostdevMatchSubsysMediatedDev(virDomainHostdevDef * a,virDomainHostdevDef * b)15384 virDomainHostdevMatchSubsysMediatedDev(virDomainHostdevDef *a,
15385                                        virDomainHostdevDef *b)
15386 {
15387     virDomainHostdevSubsysMediatedDev *src_a = &a->source.subsys.u.mdev;
15388     virDomainHostdevSubsysMediatedDev *src_b = &b->source.subsys.u.mdev;
15389 
15390     if (STREQ(src_a->uuidstr, src_b->uuidstr))
15391         return 1;
15392 
15393     return 0;
15394 }
15395 
15396 static int
virDomainHostdevMatchSubsys(virDomainHostdevDef * a,virDomainHostdevDef * b)15397 virDomainHostdevMatchSubsys(virDomainHostdevDef *a,
15398                             virDomainHostdevDef *b)
15399 {
15400     if (a->source.subsys.type != b->source.subsys.type)
15401         return 0;
15402 
15403     switch ((virDomainHostdevSubsysType) a->source.subsys.type) {
15404     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
15405         return virDomainHostdevMatchSubsysPCI(a, b);
15406     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
15407         return virDomainHostdevMatchSubsysUSB(a, b);
15408     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
15409         if (a->source.subsys.u.scsi.protocol !=
15410             b->source.subsys.u.scsi.protocol)
15411             return 0;
15412         if (a->source.subsys.u.scsi.protocol ==
15413             VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
15414             return virDomainHostdevMatchSubsysSCSIiSCSI(a, b);
15415         else
15416             return virDomainHostdevMatchSubsysSCSIHost(a, b);
15417     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
15418         if (a->source.subsys.u.scsi_host.protocol !=
15419             b->source.subsys.u.scsi_host.protocol)
15420             return 0;
15421         if (STREQ(a->source.subsys.u.scsi_host.wwpn,
15422                   b->source.subsys.u.scsi_host.wwpn))
15423             return 1;
15424         else
15425             return 0;
15426     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
15427         return virDomainHostdevMatchSubsysMediatedDev(a, b);
15428     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
15429         return 0;
15430     }
15431     return 0;
15432 }
15433 
15434 
15435 static int
virDomainHostdevMatchCapsStorage(virDomainHostdevDef * a,virDomainHostdevDef * b)15436 virDomainHostdevMatchCapsStorage(virDomainHostdevDef *a,
15437                                  virDomainHostdevDef *b)
15438 {
15439     return STREQ_NULLABLE(a->source.caps.u.storage.block,
15440                           b->source.caps.u.storage.block);
15441 }
15442 
15443 
15444 static int
virDomainHostdevMatchCapsMisc(virDomainHostdevDef * a,virDomainHostdevDef * b)15445 virDomainHostdevMatchCapsMisc(virDomainHostdevDef *a,
15446                               virDomainHostdevDef *b)
15447 {
15448     return STREQ_NULLABLE(a->source.caps.u.misc.chardev,
15449                           b->source.caps.u.misc.chardev);
15450 }
15451 
15452 static int
virDomainHostdevMatchCapsNet(virDomainHostdevDef * a,virDomainHostdevDef * b)15453 virDomainHostdevMatchCapsNet(virDomainHostdevDef *a,
15454                               virDomainHostdevDef *b)
15455 {
15456     return STREQ_NULLABLE(a->source.caps.u.net.ifname,
15457                           b->source.caps.u.net.ifname);
15458 }
15459 
15460 
15461 static int
virDomainHostdevMatchCaps(virDomainHostdevDef * a,virDomainHostdevDef * b)15462 virDomainHostdevMatchCaps(virDomainHostdevDef *a,
15463                           virDomainHostdevDef *b)
15464 {
15465     if (a->source.caps.type != b->source.caps.type)
15466         return 0;
15467 
15468     switch (a->source.caps.type) {
15469     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
15470         return virDomainHostdevMatchCapsStorage(a, b);
15471     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
15472         return virDomainHostdevMatchCapsMisc(a, b);
15473     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
15474         return virDomainHostdevMatchCapsNet(a, b);
15475     }
15476     return 0;
15477 }
15478 
15479 
15480 int
virDomainHostdevMatch(virDomainHostdevDef * a,virDomainHostdevDef * b)15481 virDomainHostdevMatch(virDomainHostdevDef *a,
15482                       virDomainHostdevDef *b)
15483 {
15484     if (a->mode != b->mode)
15485         return 0;
15486 
15487     switch (a->mode) {
15488     case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
15489         return virDomainHostdevMatchSubsys(a, b);
15490     case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
15491         return virDomainHostdevMatchCaps(a, b);
15492     }
15493     return 0;
15494 }
15495 
15496 /* Find an entry in hostdevs that matches the source spec in
15497  * @match. return pointer to the entry in @found (if found is
15498  * non-NULL). Returns index (within hostdevs) of matched entry, or -1
15499  * if no match was found.
15500  */
15501 int
virDomainHostdevFind(virDomainDef * def,virDomainHostdevDef * match,virDomainHostdevDef ** found)15502 virDomainHostdevFind(virDomainDef *def,
15503                      virDomainHostdevDef *match,
15504                      virDomainHostdevDef **found)
15505 {
15506     virDomainHostdevDef *local_found;
15507     size_t i;
15508 
15509     if (!found)
15510         found = &local_found;
15511     *found = NULL;
15512 
15513     for (i = 0; i < def->nhostdevs; i++) {
15514         if (virDomainHostdevMatch(match, def->hostdevs[i])) {
15515             *found = def->hostdevs[i];
15516             break;
15517         }
15518     }
15519     return *found ? i : -1;
15520 }
15521 
15522 static bool
virDomainDiskControllerMatch(int controller_type,int disk_bus)15523 virDomainDiskControllerMatch(int controller_type, int disk_bus)
15524 {
15525     if (controller_type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI &&
15526         disk_bus == VIR_DOMAIN_DISK_BUS_SCSI)
15527         return true;
15528 
15529     if (controller_type == VIR_DOMAIN_CONTROLLER_TYPE_FDC &&
15530         disk_bus == VIR_DOMAIN_DISK_BUS_FDC)
15531         return true;
15532 
15533     if (controller_type == VIR_DOMAIN_CONTROLLER_TYPE_IDE &&
15534         disk_bus == VIR_DOMAIN_DISK_BUS_IDE)
15535         return true;
15536 
15537     if (controller_type == VIR_DOMAIN_CONTROLLER_TYPE_SATA &&
15538         disk_bus == VIR_DOMAIN_DISK_BUS_SATA)
15539         return true;
15540 
15541     return false;
15542 }
15543 
15544 
15545 int
virDomainDiskIndexByAddress(virDomainDef * def,virPCIDeviceAddress * pci_address,virDomainDeviceCCWAddress * ccw_addr,unsigned int bus,unsigned int target,unsigned int unit)15546 virDomainDiskIndexByAddress(virDomainDef *def,
15547                             virPCIDeviceAddress *pci_address,
15548                             virDomainDeviceCCWAddress *ccw_addr,
15549                             unsigned int bus, unsigned int target,
15550                             unsigned int unit)
15551 {
15552     virDomainDiskDef *vdisk;
15553     virDomainControllerDef *controller = NULL;
15554     size_t i;
15555     int cidx;
15556 
15557     if ((cidx = virDomainControllerFindByPCIAddress(def, pci_address)) >= 0)
15558         controller = def->controllers[cidx];
15559 
15560     if (!controller && ccw_addr) {
15561         cidx = virDomainControllerFindByCCWAddress(def, ccw_addr);
15562         if (cidx >= 0)
15563             controller = def->controllers[cidx];
15564     }
15565 
15566     for (i = 0; i < def->ndisks; i++) {
15567         vdisk = def->disks[i];
15568         if (vdisk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
15569             virPCIDeviceAddressEqual(&vdisk->info.addr.pci, pci_address))
15570             return i;
15571         if (vdisk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
15572             ccw_addr &&
15573             virDomainDeviceCCWAddressEqual(&vdisk->info.addr.ccw, ccw_addr)) {
15574             return i;
15575         }
15576         if (vdisk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
15577             virDomainDeviceDriveAddress *drive = &vdisk->info.addr.drive;
15578             if (controller &&
15579                 virDomainDiskControllerMatch(controller->type, vdisk->bus) &&
15580                 drive->controller == controller->idx &&
15581                 drive->bus == bus && drive->target == target &&
15582                 drive->unit == unit)
15583                 return i;
15584         }
15585     }
15586     return -1;
15587 }
15588 
15589 virDomainDiskDef *
virDomainDiskByAddress(virDomainDef * def,virPCIDeviceAddress * pci_address,virDomainDeviceCCWAddress * ccw_addr,unsigned int bus,unsigned int target,unsigned int unit)15590 virDomainDiskByAddress(virDomainDef *def,
15591                        virPCIDeviceAddress *pci_address,
15592                        virDomainDeviceCCWAddress *ccw_addr,
15593                        unsigned int bus,
15594                        unsigned int target,
15595                        unsigned int unit)
15596 {
15597     int idx = virDomainDiskIndexByAddress(def, pci_address, ccw_addr,
15598                                           bus, target, unit);
15599     return idx < 0 ? NULL : def->disks[idx];
15600 }
15601 
15602 int
virDomainDiskIndexByName(virDomainDef * def,const char * name,bool allow_ambiguous)15603 virDomainDiskIndexByName(virDomainDef *def, const char *name,
15604                          bool allow_ambiguous)
15605 {
15606     virDomainDiskDef *vdisk;
15607     size_t i;
15608     int candidate = -1;
15609 
15610     /* We prefer the <target dev='name'/> name (it's shorter, required
15611      * for all disks, and should be unambiguous), but also support
15612      * <source file='name'/> (if unambiguous).  Assume dst if there is
15613      * no leading slash, source name otherwise.  */
15614     for (i = 0; i < def->ndisks; i++) {
15615         vdisk = def->disks[i];
15616         if (*name != '/') {
15617             if (STREQ(vdisk->dst, name))
15618                 return i;
15619         } else if (STREQ_NULLABLE(virDomainDiskGetSource(vdisk), name)) {
15620             if (allow_ambiguous)
15621                 return i;
15622             if (candidate >= 0)
15623                 return -1;
15624             candidate = i;
15625         }
15626     }
15627     return candidate;
15628 }
15629 
15630 virDomainDiskDef *
virDomainDiskByName(virDomainDef * def,const char * name,bool allow_ambiguous)15631 virDomainDiskByName(virDomainDef *def,
15632                     const char *name,
15633                     bool allow_ambiguous)
15634 {
15635     int idx = virDomainDiskIndexByName(def, name, allow_ambiguous);
15636 
15637     if (idx < 0)
15638         return NULL;
15639 
15640     return def->disks[idx];
15641 }
15642 
15643 
15644 virDomainDiskDef *
virDomainDiskByTarget(virDomainDef * def,const char * dst)15645 virDomainDiskByTarget(virDomainDef *def,
15646                       const char *dst)
15647 {
15648     size_t i;
15649 
15650     for (i = 0; i < def->ndisks; i++) {
15651         if (STREQ(def->disks[i]->dst, dst))
15652             return def->disks[i];
15653     }
15654 
15655     return NULL;
15656 }
15657 
15658 
virDomainDiskInsert(virDomainDef * def,virDomainDiskDef * disk)15659 void virDomainDiskInsert(virDomainDef *def,
15660                          virDomainDiskDef *disk)
15661 {
15662     int idx;
15663     /* Tentatively plan to insert disk at the end. */
15664     int insertAt = -1;
15665 
15666     /* Then work backwards looking for disks on
15667      * the same bus. If we find a disk with a drive
15668      * index greater than the new one, insert at
15669      * that position
15670      */
15671     for (idx = (def->ndisks - 1); idx >= 0; idx--) {
15672         /* If bus matches and current disk is after
15673          * new disk, then new disk should go here */
15674         if (def->disks[idx]->bus == disk->bus &&
15675             (virDiskNameToIndex(def->disks[idx]->dst) >
15676              virDiskNameToIndex(disk->dst))) {
15677             insertAt = idx;
15678         } else if (def->disks[idx]->bus == disk->bus &&
15679                    insertAt == -1) {
15680             /* Last disk with match bus is before the
15681              * new disk, then put new disk just after
15682              */
15683             insertAt = idx + 1;
15684         }
15685     }
15686 
15687     ignore_value(VIR_INSERT_ELEMENT(def->disks, insertAt, def->ndisks, disk));
15688 }
15689 
15690 
15691 virDomainDiskDef *
virDomainDiskRemove(virDomainDef * def,size_t i)15692 virDomainDiskRemove(virDomainDef *def, size_t i)
15693 {
15694     virDomainDiskDef *disk = def->disks[i];
15695 
15696     VIR_DELETE_ELEMENT(def->disks, i, def->ndisks);
15697     return disk;
15698 }
15699 
15700 virDomainDiskDef *
virDomainDiskRemoveByName(virDomainDef * def,const char * name)15701 virDomainDiskRemoveByName(virDomainDef *def, const char *name)
15702 {
15703     int idx = virDomainDiskIndexByName(def, name, false);
15704     if (idx < 0)
15705         return NULL;
15706     return virDomainDiskRemove(def, idx);
15707 }
15708 
virDomainNetInsert(virDomainDef * def,virDomainNetDef * net)15709 int virDomainNetInsert(virDomainDef *def, virDomainNetDef *net)
15710 {
15711     /* hostdev net devices must also exist in the hostdevs array */
15712     if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
15713         virDomainHostdevInsert(def, &net->data.hostdev.def) < 0)
15714         return -1;
15715 
15716     VIR_APPEND_ELEMENT(def->nets, def->nnets, net);
15717     return 0;
15718 }
15719 
15720 /**
15721  * virDomainNetFindIdx:
15722  * @def: domain definition
15723  * @net: interface definition
15724  *
15725  * Lookup domain's network interface based on passed @net
15726  * definition. If @net's MAC address was auto generated,
15727  * the MAC comparison is ignored.
15728  *
15729  * Return: index of match if unique match found,
15730  *         -1 otherwise and an error is logged.
15731  */
15732 int
virDomainNetFindIdx(virDomainDef * def,virDomainNetDef * net)15733 virDomainNetFindIdx(virDomainDef *def, virDomainNetDef *net)
15734 {
15735     size_t i;
15736     int matchidx = -1;
15737     char mac[VIR_MAC_STRING_BUFLEN];
15738     bool MACAddrSpecified = !net->mac_generated;
15739     bool PCIAddrSpecified = virDomainDeviceAddressIsValid(&net->info,
15740                                                           VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI);
15741     bool CCWAddrSpecified = virDomainDeviceAddressIsValid(&net->info,
15742                                                           VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW);
15743     g_autofree char *addr = NULL;
15744     const char *macAddr = _("(<null>)");
15745     const char *alias = _("(<null>)");
15746 
15747     if (MACAddrSpecified)
15748         macAddr = virMacAddrFormat(&net->mac, mac);
15749 
15750     for (i = 0; i < def->nnets; i++) {
15751         if (MACAddrSpecified &&
15752             virMacAddrCmp(&def->nets[i]->mac, &net->mac) != 0)
15753             continue;
15754 
15755         if (PCIAddrSpecified &&
15756             !virPCIDeviceAddressEqual(&def->nets[i]->info.addr.pci,
15757                                       &net->info.addr.pci))
15758             continue;
15759 
15760         if (CCWAddrSpecified &&
15761             !virDomainDeviceCCWAddressEqual(&def->nets[i]->info.addr.ccw,
15762                                             &net->info.addr.ccw))
15763             continue;
15764 
15765         if (net->info.alias && def->nets[i]->info.alias &&
15766             STRNEQ(def->nets[i]->info.alias, net->info.alias)) {
15767             continue;
15768         }
15769 
15770         if (matchidx >= 0) {
15771             /* there were multiple matches on mac address, and no
15772              * qualifying guest-side PCI/CCW address was given, so we must
15773              * fail (NB: a USB address isn't adequate, since it may
15774              * specify only vendor and product ID, and there may be
15775              * multiples of those.
15776              */
15777             if (MACAddrSpecified) {
15778                 virReportError(VIR_ERR_OPERATION_FAILED,
15779                                _("multiple devices matching MAC address %s found"),
15780                                macAddr);
15781             } else {
15782                 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
15783                                _("multiple matching devices found"));
15784             }
15785 
15786             return -1;
15787         }
15788 
15789         matchidx = i;
15790     }
15791 
15792     if (matchidx >= 0)
15793         return matchidx;
15794 
15795     if (net->info.alias)
15796         alias = net->info.alias;
15797 
15798     if (CCWAddrSpecified)
15799         addr = virDomainCCWAddressAsString(&net->info.addr.ccw);
15800     else if (PCIAddrSpecified)
15801         addr = virPCIDeviceAddressAsString(&net->info.addr.pci);
15802     else
15803         addr = g_strdup(_("(<null>)"));
15804 
15805     virReportError(VIR_ERR_DEVICE_MISSING,
15806                    _("no device found at address '%s' matching MAC address"
15807                      " '%s' and alias '%s'"),
15808                    addr, macAddr, alias);
15809     return -1;
15810 }
15811 
15812 bool
virDomainHasNet(virDomainDef * def,virDomainNetDef * net)15813 virDomainHasNet(virDomainDef *def, virDomainNetDef *net)
15814 {
15815     size_t i;
15816     bool PCIAddrSpecified = virDomainDeviceAddressIsValid(&net->info,
15817                                                           VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI);
15818 
15819     for (i = 0; i < def->nnets; i++) {
15820         if (virMacAddrCmp(&def->nets[i]->mac, &net->mac))
15821             continue;
15822 
15823         if (PCIAddrSpecified) {
15824             if (virPCIDeviceAddressEqual(&def->nets[i]->info.addr.pci,
15825                                          &net->info.addr.pci))
15826                 return true;
15827         } else {
15828             return true;
15829         }
15830     }
15831     return false;
15832 }
15833 
15834 void
virDomainNetRemoveHostdev(virDomainDef * def,virDomainNetDef * net)15835 virDomainNetRemoveHostdev(virDomainDef *def,
15836                           virDomainNetDef *net)
15837 {
15838     /* hostdev net devices are normally in the hostdevs array, but
15839      * might have already been removed by the time we get here */
15840     virDomainHostdevDef *hostdev = virDomainNetGetActualHostdev(net);
15841     size_t i;
15842 
15843     if (hostdev) {
15844         for (i = 0; i < def->nhostdevs; i++) {
15845             if (def->hostdevs[i] == hostdev) {
15846                 virDomainHostdevRemove(def, i);
15847                 break;
15848             }
15849         }
15850     }
15851 }
15852 
15853 
15854 virDomainNetDef *
virDomainNetRemove(virDomainDef * def,size_t i)15855 virDomainNetRemove(virDomainDef *def, size_t i)
15856 {
15857     virDomainNetDef *net = def->nets[i];
15858 
15859     virDomainNetRemoveHostdev(def, net);
15860     VIR_DELETE_ELEMENT(def->nets, i, def->nnets);
15861     return net;
15862 }
15863 
15864 
15865 virDomainNetDef *
virDomainNetRemoveByObj(virDomainDef * def,virDomainNetDef * net)15866 virDomainNetRemoveByObj(virDomainDef *def, virDomainNetDef *net)
15867 {
15868     size_t i;
15869 
15870     /* the device might have been added to hostdevs but not nets */
15871     virDomainNetRemoveHostdev(def, net);
15872 
15873     for (i = 0; i < def->nnets; i++) {
15874         if (def->nets[i] == net) {
15875             VIR_DELETE_ELEMENT(def->nets, i, def->nnets);
15876             break;
15877         }
15878     }
15879     return net;
15880 }
15881 
15882 
15883 int
virDomainNetUpdate(virDomainDef * def,size_t netidx,virDomainNetDef * newnet)15884 virDomainNetUpdate(virDomainDef *def,
15885                    size_t netidx,
15886                    virDomainNetDef *newnet)
15887 {
15888     size_t hostdevidx;
15889     virDomainNetDef *oldnet = def->nets[netidx];
15890     virDomainHostdevDef *oldhostdev = virDomainNetGetActualHostdev(oldnet);
15891     virDomainHostdevDef *newhostdev = virDomainNetGetActualHostdev(newnet);
15892 
15893     /*
15894      * if newnet or oldnet has a valid hostdev*, we need to update the
15895      * hostdevs list
15896      */
15897     if (oldhostdev) {
15898         for (hostdevidx = 0; hostdevidx < def->nhostdevs; hostdevidx++) {
15899             if (def->hostdevs[hostdevidx] == oldhostdev)
15900                 break;
15901         }
15902     }
15903 
15904     if (oldhostdev && hostdevidx < def->nhostdevs) {
15905         if (newhostdev) {
15906             /* update existing entry in def->hostdevs */
15907             def->hostdevs[hostdevidx] = newhostdev;
15908         } else {
15909             /* delete oldhostdev from def->hostdevs */
15910             virDomainHostdevRemove(def, hostdevidx);
15911         }
15912     } else if (newhostdev) {
15913         /* add newhostdev to end of def->hostdevs */
15914         VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, newhostdev);
15915     }
15916 
15917     def->nets[netidx] = newnet;
15918     return 0;
15919 }
15920 
15921 
15922 int
virDomainNetDHCPInterfaces(virDomainDef * def,virDomainInterfacePtr ** ifaces)15923 virDomainNetDHCPInterfaces(virDomainDef *def,
15924                            virDomainInterfacePtr **ifaces)
15925 {
15926     g_autoptr(virConnect) conn = NULL;
15927     virDomainInterfacePtr *ifaces_ret = NULL;
15928     size_t ifaces_count = 0;
15929     size_t i;
15930 
15931     if (!(conn = virGetConnectNetwork()))
15932         return -1;
15933 
15934     for (i = 0; i < def->nnets; i++) {
15935         g_autoptr(virNetwork) network = NULL;
15936         char macaddr[VIR_MAC_STRING_BUFLEN];
15937         virNetworkDHCPLeasePtr *leases = NULL;
15938         int n_leases = 0;
15939         virDomainInterfacePtr iface = NULL;
15940         size_t j;
15941 
15942         if (def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK)
15943             continue;
15944 
15945         virMacAddrFormat(&(def->nets[i]->mac), macaddr);
15946 
15947         network = virNetworkLookupByName(conn,
15948                                          def->nets[i]->data.network.name);
15949         if (!network)
15950             goto error;
15951 
15952         if ((n_leases = virNetworkGetDHCPLeases(network, macaddr,
15953                                                 &leases, 0)) < 0)
15954             goto error;
15955 
15956         if (n_leases) {
15957             ifaces_ret = g_renew(virDomainInterfacePtr, ifaces_ret, ifaces_count + 1);
15958             ifaces_ret[ifaces_count] = g_new0(virDomainInterface, 1);
15959             iface = ifaces_ret[ifaces_count];
15960             ifaces_count++;
15961 
15962             /* Assuming each lease corresponds to a separate IP */
15963             iface->naddrs = n_leases;
15964             iface->addrs = g_new0(virDomainIPAddress, iface->naddrs);
15965             iface->name = g_strdup(def->nets[i]->ifname);
15966             iface->hwaddr = g_strdup(macaddr);
15967         }
15968 
15969         for (j = 0; j < n_leases; j++) {
15970             virNetworkDHCPLeasePtr lease = leases[j];
15971             virDomainIPAddressPtr ip_addr = &iface->addrs[j];
15972 
15973             ip_addr->addr = g_strdup(lease->ipaddr);
15974             ip_addr->type = lease->type;
15975             ip_addr->prefix = lease->prefix;
15976 
15977             virNetworkDHCPLeaseFree(lease);
15978         }
15979 
15980         VIR_FREE(leases);
15981     }
15982 
15983     *ifaces = g_steal_pointer(&ifaces_ret);
15984     return ifaces_count;
15985 
15986  error:
15987     if (ifaces_ret) {
15988         for (i = 0; i < ifaces_count; i++)
15989             virDomainInterfaceFree(ifaces_ret[i]);
15990     }
15991     VIR_FREE(ifaces_ret);
15992 
15993     return -1;
15994 }
15995 
15996 
15997 int
virDomainNetARPInterfaces(virDomainDef * def,virDomainInterfacePtr ** ifaces)15998 virDomainNetARPInterfaces(virDomainDef *def,
15999                           virDomainInterfacePtr **ifaces)
16000 {
16001     size_t i, j;
16002     size_t ifaces_count = 0;
16003     int ret = -1;
16004     char macaddr[VIR_MAC_STRING_BUFLEN];
16005     virDomainInterfacePtr *ifaces_ret = NULL;
16006     virDomainInterfacePtr iface = NULL;
16007     virArpTable *table;
16008 
16009     table = virArpTableGet();
16010     if (!table)
16011         goto cleanup;
16012 
16013     for (i = 0; i < def->nnets; i++) {
16014         virMacAddrFormat(&(def->nets[i]->mac), macaddr);
16015         for (j = 0; j < table->n; j++) {
16016             virArpTableEntry entry = table->t[j];
16017 
16018             if (STREQ(entry.mac, macaddr)) {
16019                 iface = g_new0(virDomainInterface, 1);
16020 
16021                 iface->name = g_strdup(def->nets[i]->ifname);
16022 
16023                 iface->hwaddr = g_strdup(macaddr);
16024 
16025                 iface->addrs = g_new0(virDomainIPAddress, 1);
16026                 iface->naddrs = 1;
16027 
16028                 iface->addrs->addr = g_strdup(entry.ipaddr);
16029 
16030                 VIR_APPEND_ELEMENT(ifaces_ret, ifaces_count, iface);
16031             }
16032         }
16033     }
16034 
16035     *ifaces = g_steal_pointer(&ifaces_ret);
16036     ret = ifaces_count;
16037 
16038  cleanup:
16039     virArpTableFree(table);
16040     virDomainInterfaceFree(iface);
16041 
16042     if (ifaces_ret) {
16043         for (i = 0; i < ifaces_count; i++)
16044             virDomainInterfaceFree(ifaces_ret[i]);
16045     }
16046     VIR_FREE(ifaces_ret);
16047 
16048     return ret;
16049 }
16050 
16051 
virDomainControllerInsert(virDomainDef * def,virDomainControllerDef * controller)16052 void virDomainControllerInsert(virDomainDef *def,
16053                               virDomainControllerDef *controller)
16054 {
16055     def->controllers = g_renew(virDomainControllerDef *, def->controllers, def->ncontrollers + 1);
16056     virDomainControllerInsertPreAlloced(def, controller);
16057 }
16058 
virDomainControllerInsertPreAlloced(virDomainDef * def,virDomainControllerDef * controller)16059 void virDomainControllerInsertPreAlloced(virDomainDef *def,
16060                                          virDomainControllerDef *controller)
16061 {
16062     int idx;
16063     /* Tentatively plan to insert controller at the end. */
16064     int insertAt = -1;
16065     virDomainControllerDef *current = NULL;
16066 
16067     /* Then work backwards looking for controllers of
16068      * the same type. If we find a controller with a
16069      * index greater than the new one, insert at
16070      * that position
16071      */
16072     for (idx = (def->ncontrollers - 1); idx >= 0; idx--) {
16073         current = def->controllers[idx];
16074         if (current->type == controller->type) {
16075             if (controller->idx == -1) {
16076                 /* If the new controller doesn't have an index set
16077                  * yet, put it just past this controller, which until
16078                  * now was the last controller of this type.
16079                  */
16080                 insertAt = idx + 1;
16081                 break;
16082             }
16083             if (current->idx > controller->idx) {
16084                 /* If bus matches and current controller is after
16085                  * new controller, then new controller should go here
16086                  * */
16087                 insertAt = idx;
16088             } else if (controller->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_NONE &&
16089                        current->info.mastertype != VIR_DOMAIN_CONTROLLER_MASTER_NONE &&
16090                        current->idx == controller->idx) {
16091                 /* If bus matches and index matches and new controller is
16092                  * master and current isn't a master, then new controller
16093                  * should go here to be placed before its companion
16094                  */
16095                 insertAt = idx;
16096             } else if (insertAt == -1) {
16097                 /* Last controller with match bus is before the
16098                  * new controller, then put new controller just after
16099                  */
16100                 insertAt = idx + 1;
16101             }
16102         }
16103     }
16104 
16105     /* VIR_INSERT_ELEMENT_INPLACE will never return an error here. */
16106     ignore_value(VIR_INSERT_ELEMENT_INPLACE(def->controllers, insertAt,
16107                                             def->ncontrollers, controller));
16108 }
16109 
16110 int
virDomainControllerFind(const virDomainDef * def,int type,int idx)16111 virDomainControllerFind(const virDomainDef *def,
16112                         int type,
16113                         int idx)
16114 {
16115     size_t i;
16116 
16117     for (i = 0; i < def->ncontrollers; i++) {
16118         if ((def->controllers[i]->type == type) &&
16119             (def->controllers[i]->idx == idx)) {
16120             return i;
16121         }
16122     }
16123 
16124     return -1;
16125 }
16126 
16127 
16128 int
virDomainControllerFindUnusedIndex(virDomainDef const * def,int type)16129 virDomainControllerFindUnusedIndex(virDomainDef const *def, int type)
16130 {
16131     int idx = 0;
16132 
16133     while (virDomainControllerFind(def, type, idx) >= 0)
16134         idx++;
16135 
16136     return idx;
16137 }
16138 
16139 
16140 const char *
virDomainControllerAliasFind(const virDomainDef * def,int type,int idx)16141 virDomainControllerAliasFind(const virDomainDef *def,
16142                              int type,
16143                              int idx)
16144 {
16145     int contIndex;
16146     const char *contTypeStr = virDomainControllerTypeToString(type);
16147 
16148     if (!contTypeStr) {
16149         virReportError(VIR_ERR_INTERNAL_ERROR,
16150                        _("Unknown controller type %d"),
16151                        type);
16152         return NULL;
16153     }
16154 
16155     contIndex = virDomainControllerFind(def, type, idx);
16156     if (contIndex < 0) {
16157         virReportError(VIR_ERR_INTERNAL_ERROR,
16158                        _("Could not find %s controller with index %d "
16159                          "required for device"),
16160                        contTypeStr, idx);
16161         return NULL;
16162     }
16163     if (!def->controllers[contIndex]->info.alias) {
16164         virReportError(VIR_ERR_INTERNAL_ERROR,
16165                        _("Device alias was not set for %s controller "
16166                          "with index %d "),
16167                        contTypeStr, idx);
16168         return NULL;
16169     }
16170     return def->controllers[contIndex]->info.alias;
16171 }
16172 
16173 
16174 int
virDomainControllerFindByType(virDomainDef * def,int type)16175 virDomainControllerFindByType(virDomainDef *def,
16176                               int type)
16177 {
16178     size_t i;
16179 
16180     for (i = 0; i < def->ncontrollers; i++) {
16181         if (def->controllers[i]->type == type)
16182             return i;
16183     }
16184 
16185     return -1;
16186 }
16187 
16188 int
virDomainControllerFindByCCWAddress(virDomainDef * def,virDomainDeviceCCWAddress * addr)16189 virDomainControllerFindByCCWAddress(virDomainDef *def,
16190                                     virDomainDeviceCCWAddress *addr)
16191 {
16192     size_t i;
16193 
16194     for (i = 0; i < def->ncontrollers; i++) {
16195         virDomainDeviceInfo *info = &def->controllers[i]->info;
16196 
16197         if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
16198             virDomainDeviceCCWAddressEqual(&info->addr.ccw, addr))
16199             return i;
16200     }
16201 
16202     return -1;
16203 }
16204 
16205 int
virDomainControllerFindByPCIAddress(virDomainDef * def,virPCIDeviceAddress * addr)16206 virDomainControllerFindByPCIAddress(virDomainDef *def,
16207                                     virPCIDeviceAddress *addr)
16208 {
16209     size_t i;
16210 
16211     for (i = 0; i < def->ncontrollers; i++) {
16212         virDomainDeviceInfo *info = &def->controllers[i]->info;
16213 
16214         if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
16215             virPCIDeviceAddressEqual(&info->addr.pci, addr))
16216             return i;
16217     }
16218 
16219     return -1;
16220 }
16221 
16222 virDomainControllerDef *
virDomainControllerRemove(virDomainDef * def,size_t i)16223 virDomainControllerRemove(virDomainDef *def, size_t i)
16224 {
16225     virDomainControllerDef *controller = def->controllers[i];
16226 
16227     VIR_DELETE_ELEMENT(def->controllers, i, def->ncontrollers);
16228     return controller;
16229 }
16230 
virDomainLeaseIndex(virDomainDef * def,virDomainLeaseDef * lease)16231 int virDomainLeaseIndex(virDomainDef *def,
16232                         virDomainLeaseDef *lease)
16233 {
16234     virDomainLeaseDef *vlease;
16235     size_t i;
16236 
16237     for (i = 0; i < def->nleases; i++) {
16238         vlease = def->leases[i];
16239         /* Either both must have lockspaces present which match.. */
16240         if (vlease->lockspace && lease->lockspace) {
16241             if (STRNEQ(vlease->lockspace, lease->lockspace))
16242                 continue;
16243         /* ...or neither must have a lockspace present */
16244         } else if (vlease->lockspace || lease->lockspace) {
16245             continue;
16246         }
16247 
16248         if (STREQ(vlease->key, lease->key))
16249             return i;
16250     }
16251     return -1;
16252 }
16253 
16254 
virDomainLeaseInsertPreAlloc(virDomainDef * def)16255 void virDomainLeaseInsertPreAlloc(virDomainDef *def)
16256 {
16257     VIR_EXPAND_N(def->leases, def->nleases, 1);
16258 }
16259 
virDomainLeaseInsert(virDomainDef * def,virDomainLeaseDef * lease)16260 void virDomainLeaseInsert(virDomainDef *def, virDomainLeaseDef *lease)
16261 {
16262     virDomainLeaseInsertPreAlloc(def);
16263     virDomainLeaseInsertPreAlloced(def, lease);
16264 }
16265 
16266 
virDomainLeaseInsertPreAlloced(virDomainDef * def,virDomainLeaseDef * lease)16267 void virDomainLeaseInsertPreAlloced(virDomainDef *def,
16268                                     virDomainLeaseDef *lease)
16269 {
16270     if (lease == NULL)
16271         VIR_SHRINK_N(def->leases, def->nleases, 1);
16272     else
16273         def->leases[def->nleases-1] = lease;
16274 }
16275 
16276 
16277 virDomainLeaseDef *
virDomainLeaseRemoveAt(virDomainDef * def,size_t i)16278 virDomainLeaseRemoveAt(virDomainDef *def, size_t i)
16279 {
16280     virDomainLeaseDef *lease = def->leases[i];
16281 
16282     VIR_DELETE_ELEMENT(def->leases, i, def->nleases);
16283     return lease;
16284 }
16285 
16286 
16287 virDomainLeaseDef *
virDomainLeaseRemove(virDomainDef * def,virDomainLeaseDef * lease)16288 virDomainLeaseRemove(virDomainDef *def,
16289                      virDomainLeaseDef *lease)
16290 {
16291     int idx = virDomainLeaseIndex(def, lease);
16292     if (idx < 0)
16293         return NULL;
16294     return virDomainLeaseRemoveAt(def, idx);
16295 }
16296 
16297 bool
virDomainChrEquals(virDomainChrDef * src,virDomainChrDef * tgt)16298 virDomainChrEquals(virDomainChrDef *src,
16299                    virDomainChrDef *tgt)
16300 {
16301     if (!src || !tgt)
16302         return src == tgt;
16303 
16304     if (src->deviceType != tgt->deviceType ||
16305         !virDomainChrSourceDefIsEqual(src->source, tgt->source))
16306         return false;
16307 
16308     switch ((virDomainChrDeviceType) src->deviceType) {
16309     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
16310         if (src->targetType != tgt->targetType)
16311             return false;
16312         switch ((virDomainChrChannelTargetType) src->targetType) {
16313         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
16314         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
16315             return STREQ_NULLABLE(src->target.name, tgt->target.name);
16316         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
16317             if (!src->target.addr || !tgt->target.addr)
16318                 return src->target.addr == tgt->target.addr;
16319             return memcmp(src->target.addr, tgt->target.addr,
16320                           sizeof(*src->target.addr)) == 0;
16321 
16322         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
16323         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
16324             /* shouldn't happen */
16325             break;
16326         }
16327         break;
16328 
16329     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
16330         if (src->targetType != tgt->targetType)
16331             return false;
16332 
16333         G_GNUC_FALLTHROUGH;
16334 
16335     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
16336     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
16337         return src->target.port == tgt->target.port;
16338     case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
16339         /* shouldn't happen */
16340         break;
16341     }
16342     return false;
16343 }
16344 
16345 virDomainChrDef *
virDomainChrFind(virDomainDef * def,virDomainChrDef * target)16346 virDomainChrFind(virDomainDef *def,
16347                  virDomainChrDef *target)
16348 {
16349     virDomainChrDef *chr;
16350     const virDomainChrDef **arrPtr;
16351     size_t i, cnt;
16352 
16353     virDomainChrGetDomainPtrs(def, target->deviceType, &arrPtr, &cnt);
16354 
16355     for (i = 0; i < cnt; i++) {
16356         /* Cast away const */
16357         chr = (virDomainChrDef *) arrPtr[i];
16358         if (virDomainChrEquals(chr, target))
16359             return chr;
16360     }
16361     return NULL;
16362 }
16363 
16364 
16365 /* Return the address within vmdef to be modified when working with a
16366  * chrdefptr of the given type.  */
16367 static int G_GNUC_WARN_UNUSED_RESULT
virDomainChrGetDomainPtrsInternal(virDomainDef * vmdef,virDomainChrDeviceType type,virDomainChrDef **** arrPtr,size_t ** cntPtr)16368 virDomainChrGetDomainPtrsInternal(virDomainDef *vmdef,
16369                                   virDomainChrDeviceType type,
16370                                   virDomainChrDef ****arrPtr,
16371                                   size_t **cntPtr)
16372 {
16373     switch (type) {
16374     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
16375         *arrPtr = &vmdef->parallels;
16376         *cntPtr = &vmdef->nparallels;
16377         return 0;
16378 
16379     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
16380         *arrPtr = &vmdef->serials;
16381         *cntPtr = &vmdef->nserials;
16382         return 0;
16383 
16384     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
16385         *arrPtr = &vmdef->consoles;
16386         *cntPtr = &vmdef->nconsoles;
16387         return 0;
16388 
16389     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
16390         *arrPtr = &vmdef->channels;
16391         *cntPtr = &vmdef->nchannels;
16392         return 0;
16393 
16394     case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
16395         break;
16396     }
16397 
16398     virReportError(VIR_ERR_INTERNAL_ERROR,
16399                    _("Unknown char device type: %d"), type);
16400     return -1;
16401 }
16402 
16403 
16404 /* Return the array within vmdef that can contain a chrdefptr of the
16405  * given type.  */
16406 void
virDomainChrGetDomainPtrs(const virDomainDef * vmdef,virDomainChrDeviceType type,const virDomainChrDef *** arrPtr,size_t * cntPtr)16407 virDomainChrGetDomainPtrs(const virDomainDef *vmdef,
16408                           virDomainChrDeviceType type,
16409                           const virDomainChrDef ***arrPtr,
16410                           size_t *cntPtr)
16411 {
16412     virDomainChrDef ***arrVar = NULL;
16413     size_t *cntVar = NULL;
16414 
16415     /* Cast away const; we add it back in the final assignment.  */
16416     if (virDomainChrGetDomainPtrsInternal((virDomainDef *) vmdef, type,
16417                                           &arrVar, &cntVar) < 0) {
16418         *arrPtr = NULL;
16419         *cntPtr = 0;
16420     } else {
16421         *arrPtr = (const virDomainChrDef **) *arrVar;
16422         *cntPtr = *cntVar;
16423     }
16424 }
16425 
16426 
16427 int
virDomainChrPreAlloc(virDomainDef * vmdef,virDomainChrDef * chr)16428 virDomainChrPreAlloc(virDomainDef *vmdef,
16429                      virDomainChrDef *chr)
16430 {
16431     virDomainChrDef ***arrPtr = NULL;
16432     size_t *cntPtr = NULL;
16433 
16434     if (virDomainChrGetDomainPtrsInternal(vmdef, chr->deviceType,
16435                                           &arrPtr, &cntPtr) < 0)
16436         return -1;
16437 
16438     VIR_REALLOC_N(*arrPtr, *cntPtr + 1);
16439     return 0;
16440 }
16441 
16442 void
virDomainChrInsertPreAlloced(virDomainDef * vmdef,virDomainChrDef * chr)16443 virDomainChrInsertPreAlloced(virDomainDef *vmdef,
16444                              virDomainChrDef *chr)
16445 {
16446     virDomainChrDef ***arrPtr = NULL;
16447     size_t *cntPtr = NULL;
16448 
16449     if (virDomainChrGetDomainPtrsInternal(vmdef, chr->deviceType,
16450                                           &arrPtr, &cntPtr) < 0)
16451         return;
16452 
16453     VIR_APPEND_ELEMENT_INPLACE(*arrPtr, *cntPtr, chr);
16454 }
16455 
16456 virDomainChrDef *
virDomainChrRemove(virDomainDef * vmdef,virDomainChrDef * chr)16457 virDomainChrRemove(virDomainDef *vmdef,
16458                    virDomainChrDef *chr)
16459 {
16460     virDomainChrDef *ret = NULL;
16461     virDomainChrDef ***arrPtr = NULL;
16462     size_t i, *cntPtr = NULL;
16463 
16464     if (virDomainChrGetDomainPtrsInternal(vmdef, chr->deviceType,
16465                                           &arrPtr, &cntPtr) < 0)
16466         return NULL;
16467 
16468     for (i = 0; i < *cntPtr; i++) {
16469         ret = (*arrPtr)[i];
16470 
16471         if (virDomainChrEquals(ret, chr))
16472             break;
16473     }
16474 
16475     if (i == *cntPtr)
16476         return NULL;
16477 
16478     VIR_DELETE_ELEMENT(*arrPtr, i, *cntPtr);
16479     return ret;
16480 }
16481 
16482 
16483 ssize_t
virDomainRNGFind(virDomainDef * def,virDomainRNGDef * rng)16484 virDomainRNGFind(virDomainDef *def,
16485                  virDomainRNGDef *rng)
16486 {
16487     size_t i;
16488 
16489     for (i = 0; i < def->nrngs; i++) {
16490         virDomainRNGDef *tmp = def->rngs[i];
16491 
16492         if (rng->model != tmp->model || rng->backend != tmp->backend)
16493             continue;
16494 
16495         if (rng->rate != tmp->rate || rng->period != tmp->period)
16496             continue;
16497 
16498         switch ((virDomainRNGBackend) rng->backend) {
16499         case VIR_DOMAIN_RNG_BACKEND_RANDOM:
16500             if (STRNEQ_NULLABLE(rng->source.file, tmp->source.file))
16501                 continue;
16502             break;
16503 
16504         case VIR_DOMAIN_RNG_BACKEND_EGD:
16505             if (!virDomainChrSourceDefIsEqual(rng->source.chardev,
16506                                               tmp->source.chardev))
16507                 continue;
16508             break;
16509 
16510         case VIR_DOMAIN_RNG_BACKEND_BUILTIN:
16511         case VIR_DOMAIN_RNG_BACKEND_LAST:
16512             break;
16513         }
16514 
16515         if (rng->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
16516             !virDomainDeviceInfoAddressIsEqual(&rng->info, &tmp->info))
16517             continue;
16518 
16519         break;
16520     }
16521 
16522     if (i < def->nrngs)
16523         return i;
16524 
16525     return -1;
16526 }
16527 
16528 
16529 virDomainRNGDef *
virDomainRNGRemove(virDomainDef * def,size_t idx)16530 virDomainRNGRemove(virDomainDef *def,
16531                    size_t idx)
16532 {
16533     virDomainRNGDef *ret = def->rngs[idx];
16534 
16535     VIR_DELETE_ELEMENT(def->rngs, idx, def->nrngs);
16536 
16537     return ret;
16538 }
16539 
16540 
16541 static int
virDomainMemoryFindByDefInternal(virDomainDef * def,virDomainMemoryDef * mem,bool allowAddressFallback)16542 virDomainMemoryFindByDefInternal(virDomainDef *def,
16543                                  virDomainMemoryDef *mem,
16544                                  bool allowAddressFallback)
16545 {
16546     size_t i;
16547 
16548     for (i = 0; i < def->nmems; i++) {
16549         virDomainMemoryDef *tmp = def->mems[i];
16550 
16551         /* address, if present */
16552         if (allowAddressFallback) {
16553             if (tmp->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
16554                 continue;
16555         } else {
16556             if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
16557                 !virDomainDeviceInfoAddressIsEqual(&tmp->info, &mem->info))
16558                 continue;
16559         }
16560 
16561         /* alias, if present */
16562         if (mem->info.alias &&
16563             STRNEQ_NULLABLE(tmp->info.alias, mem->info.alias))
16564             continue;
16565 
16566         /* target info -> always present */
16567         if (tmp->model != mem->model ||
16568             tmp->targetNode != mem->targetNode ||
16569             tmp->size != mem->size ||
16570             tmp->blocksize != mem->blocksize ||
16571             tmp->requestedsize != mem->requestedsize)
16572             continue;
16573 
16574         switch (mem->model) {
16575         case VIR_DOMAIN_MEMORY_MODEL_DIMM:
16576         case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
16577             /* source stuff -> match with device */
16578             if (tmp->pagesize != mem->pagesize)
16579                 continue;
16580 
16581             if (!virBitmapEqual(tmp->sourceNodes, mem->sourceNodes))
16582                 continue;
16583             break;
16584 
16585         case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
16586             if (STRNEQ(tmp->nvdimmPath, mem->nvdimmPath))
16587                 continue;
16588             break;
16589 
16590         case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
16591             if (STRNEQ(tmp->nvdimmPath, mem->nvdimmPath))
16592                 continue;
16593             break;
16594 
16595         case VIR_DOMAIN_MEMORY_MODEL_NONE:
16596         case VIR_DOMAIN_MEMORY_MODEL_LAST:
16597             break;
16598         }
16599 
16600         break;
16601     }
16602 
16603     if (i == def->nmems)
16604         return -1;
16605 
16606     return i;
16607 }
16608 
16609 
16610 int
virDomainMemoryFindByDef(virDomainDef * def,virDomainMemoryDef * mem)16611 virDomainMemoryFindByDef(virDomainDef *def,
16612                          virDomainMemoryDef *mem)
16613 {
16614     return virDomainMemoryFindByDefInternal(def, mem, false);
16615 }
16616 
16617 
16618 int
virDomainMemoryFindInactiveByDef(virDomainDef * def,virDomainMemoryDef * mem)16619 virDomainMemoryFindInactiveByDef(virDomainDef *def,
16620                                  virDomainMemoryDef *mem)
16621 {
16622     int ret;
16623 
16624     if ((ret = virDomainMemoryFindByDefInternal(def, mem, false)) < 0)
16625         ret = virDomainMemoryFindByDefInternal(def, mem, true);
16626 
16627     return ret;
16628 }
16629 
16630 
16631 /**
16632  * virDomainMemoryFindByDeviceInfo:
16633  * @def: domain definition
16634  * @info: device info to match
16635  * @pos: store position within array
16636  *
16637  * For given domain definition @def find <memory/> device with
16638  * matching address and matching device alias (if set in @info,
16639  * otherwise ignored).
16640  *
16641  * If @pos is not NULL then the position of the matched device
16642  * within the array is stored there.
16643  *
16644  * Returns: device if found,
16645  *          NULL otherwise.
16646  */
16647 virDomainMemoryDef *
virDomainMemoryFindByDeviceInfo(virDomainDef * def,virDomainDeviceInfo * info,int * pos)16648 virDomainMemoryFindByDeviceInfo(virDomainDef *def,
16649                                 virDomainDeviceInfo *info,
16650                                 int *pos)
16651 {
16652     size_t i;
16653 
16654     for (i = 0; i < def->nmems; i++) {
16655         virDomainMemoryDef *tmp = def->mems[i];
16656 
16657         if (!virDomainDeviceInfoAddressIsEqual(&tmp->info, info))
16658             continue;
16659 
16660         /* alias, if present */
16661         if (info->alias &&
16662             STRNEQ_NULLABLE(tmp->info.alias, info->alias))
16663             continue;
16664 
16665         if (pos)
16666             *pos = i;
16667 
16668         return tmp;
16669     }
16670 
16671     return NULL;
16672 }
16673 
16674 
16675 virDomainMemoryDef *
virDomainMemoryFindByDeviceAlias(virDomainDef * def,const char * alias)16676 virDomainMemoryFindByDeviceAlias(virDomainDef *def,
16677                                  const char *alias)
16678 {
16679     size_t i;
16680 
16681     for (i = 0; i < def->nmems; i++) {
16682         virDomainMemoryDef *tmp = def->mems[i];
16683 
16684         if (STREQ_NULLABLE(tmp->info.alias, alias))
16685             return tmp;
16686     }
16687 
16688     return NULL;
16689 }
16690 
16691 
16692 /**
16693  * virDomainMemoryInsert:
16694  *
16695  * Inserts a memory device definition into the domain definition. This helper
16696  * should be used only in hot/cold-plug cases as it's blindly modifying the
16697  * total memory size.
16698  */
16699 int
virDomainMemoryInsert(virDomainDef * def,virDomainMemoryDef * mem)16700 virDomainMemoryInsert(virDomainDef *def,
16701                       virDomainMemoryDef *mem)
16702 {
16703     unsigned long long memory = virDomainDefGetMemoryTotal(def);
16704     int id = def->nmems;
16705 
16706     if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
16707         virDomainDefHasDeviceAddress(def, &mem->info)) {
16708         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
16709                        _("Domain already contains a device with the same "
16710                          "address"));
16711         return -1;
16712     }
16713 
16714     VIR_APPEND_ELEMENT_COPY(def->mems, def->nmems, mem);
16715 
16716     virDomainDefSetMemoryTotal(def, memory + mem->size);
16717 
16718     return id;
16719 }
16720 
16721 
16722 /**
16723  * virDomainMemoryRemove:
16724  *
16725  * Removes a memory device definition from the domain definition. This helper
16726  * should be used only in hot/cold-plug cases as it's blindly modifying the
16727  * total memory size.
16728  */
16729 virDomainMemoryDef *
virDomainMemoryRemove(virDomainDef * def,int idx)16730 virDomainMemoryRemove(virDomainDef *def,
16731                       int idx)
16732 {
16733     unsigned long long memory = virDomainDefGetMemoryTotal(def);
16734     virDomainMemoryDef *ret = def->mems[idx];
16735 
16736     VIR_DELETE_ELEMENT(def->mems, idx, def->nmems);
16737 
16738     /* fix total memory size of the domain */
16739     virDomainDefSetMemoryTotal(def, memory - ret->size);
16740 
16741     return ret;
16742 }
16743 
16744 
16745 ssize_t
virDomainRedirdevDefFind(virDomainDef * def,virDomainRedirdevDef * redirdev)16746 virDomainRedirdevDefFind(virDomainDef *def,
16747                          virDomainRedirdevDef *redirdev)
16748 {
16749     size_t i;
16750 
16751     for (i = 0; i < def->nredirdevs; i++) {
16752         virDomainRedirdevDef *tmp = def->redirdevs[i];
16753 
16754         if (redirdev->bus != tmp->bus)
16755             continue;
16756 
16757         if (!virDomainChrSourceDefIsEqual(redirdev->source, tmp->source))
16758             continue;
16759 
16760         if (redirdev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
16761             !virDomainDeviceInfoAddressIsEqual(&redirdev->info, &tmp->info))
16762             continue;
16763 
16764         if (redirdev->info.alias &&
16765             STRNEQ_NULLABLE(redirdev->info.alias, tmp->info.alias))
16766             continue;
16767 
16768         return i;
16769     }
16770 
16771     return -1;
16772 }
16773 
16774 
16775 virDomainRedirdevDef *
virDomainRedirdevDefRemove(virDomainDef * def,size_t idx)16776 virDomainRedirdevDefRemove(virDomainDef *def, size_t idx)
16777 {
16778     virDomainRedirdevDef *ret = def->redirdevs[idx];
16779 
16780     VIR_DELETE_ELEMENT(def->redirdevs, idx, def->nredirdevs);
16781 
16782     return ret;
16783 }
16784 
16785 
16786 int
virDomainShmemDefInsert(virDomainDef * def,virDomainShmemDef * shmem)16787 virDomainShmemDefInsert(virDomainDef *def,
16788                         virDomainShmemDef *shmem)
16789 {
16790     VIR_APPEND_ELEMENT(def->shmems, def->nshmems, shmem);
16791 
16792     return 0;
16793 }
16794 
16795 
16796 bool
virDomainShmemDefEquals(virDomainShmemDef * src,virDomainShmemDef * dst)16797 virDomainShmemDefEquals(virDomainShmemDef *src,
16798                         virDomainShmemDef *dst)
16799 {
16800     if (STRNEQ_NULLABLE(src->name, dst->name))
16801         return false;
16802 
16803     if (src->size != dst->size)
16804         return false;
16805 
16806     if (src->model != dst->model)
16807         return false;
16808 
16809     if (src->role != dst->role)
16810         return false;
16811 
16812     if (src->server.enabled != dst->server.enabled)
16813         return false;
16814 
16815     if (src->server.enabled) {
16816         if (STRNEQ_NULLABLE(src->server.chr->data.nix.path,
16817                             dst->server.chr->data.nix.path))
16818             return false;
16819     }
16820 
16821     if (src->msi.enabled != dst->msi.enabled)
16822         return false;
16823 
16824     if (src->msi.enabled) {
16825         if (src->msi.vectors != dst->msi.vectors)
16826             return false;
16827         if (src->msi.ioeventfd != dst->msi.ioeventfd)
16828             return false;
16829     }
16830 
16831     if (src->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
16832         !virDomainDeviceInfoAddressIsEqual(&src->info, &dst->info))
16833         return false;
16834 
16835     return true;
16836 }
16837 
16838 
16839 ssize_t
virDomainShmemDefFind(virDomainDef * def,virDomainShmemDef * shmem)16840 virDomainShmemDefFind(virDomainDef *def,
16841                       virDomainShmemDef *shmem)
16842 {
16843     size_t i;
16844 
16845     for (i = 0; i < def->nshmems; i++) {
16846         if (virDomainShmemDefEquals(shmem, def->shmems[i]))
16847             return i;
16848     }
16849 
16850     return -1;
16851 }
16852 
16853 
16854 virDomainShmemDef *
virDomainShmemDefRemove(virDomainDef * def,size_t idx)16855 virDomainShmemDefRemove(virDomainDef *def,
16856                         size_t idx)
16857 {
16858     virDomainShmemDef *ret = def->shmems[idx];
16859 
16860     VIR_DELETE_ELEMENT(def->shmems, idx, def->nshmems);
16861 
16862     return ret;
16863 }
16864 
16865 
16866 static bool
virDomainInputDefEquals(const virDomainInputDef * a,const virDomainInputDef * b)16867 virDomainInputDefEquals(const virDomainInputDef *a,
16868                         const virDomainInputDef *b)
16869 {
16870     if (a->type != b->type)
16871         return false;
16872 
16873     if (a->bus != b->bus)
16874         return false;
16875 
16876     if (a->type == VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH &&
16877         STRNEQ_NULLABLE(a->source.evdev, b->source.evdev))
16878         return false;
16879 
16880     if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
16881         !virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
16882         return false;
16883 
16884     return true;
16885 }
16886 
16887 
16888 ssize_t
virDomainInputDefFind(const virDomainDef * def,const virDomainInputDef * input)16889 virDomainInputDefFind(const virDomainDef *def,
16890                       const virDomainInputDef *input)
16891 {
16892     size_t i;
16893 
16894     for (i = 0; i < def->ninputs; i++) {
16895         if (virDomainInputDefEquals(input, def->inputs[i]))
16896             return i;
16897     }
16898 
16899     return -1;
16900 }
16901 
16902 
16903 bool
virDomainVsockDefEquals(const virDomainVsockDef * a,const virDomainVsockDef * b)16904 virDomainVsockDefEquals(const virDomainVsockDef *a,
16905                         const virDomainVsockDef *b)
16906 {
16907     if (a->model != b->model)
16908         return false;
16909 
16910     if (a->auto_cid != b->auto_cid)
16911         return false;
16912 
16913     if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
16914         !virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
16915         return false;
16916 
16917     return true;
16918 }
16919 
16920 
16921 char *
virDomainDefGetDefaultEmulator(virDomainDef * def,virCaps * caps)16922 virDomainDefGetDefaultEmulator(virDomainDef *def,
16923                                virCaps *caps)
16924 {
16925     char *retemu;
16926     g_autofree virCapsDomainData *capsdata = NULL;
16927 
16928     if (!(capsdata = virCapabilitiesDomainDataLookup(caps, def->os.type,
16929             def->os.arch, def->virtType, NULL, NULL)))
16930         return NULL;
16931 
16932     retemu = g_strdup(capsdata->emulator);
16933 
16934     return retemu;
16935 }
16936 
16937 static int
virDomainDefParseBootXML(xmlXPathContextPtr ctxt,virDomainDef * def)16938 virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
16939                          virDomainDef *def)
16940 {
16941     xmlNodePtr node;
16942     size_t i;
16943     int n;
16944     g_autofree char *tmp = NULL;
16945     g_autofree xmlNodePtr *nodes = NULL;
16946 
16947     /* analysis of the boot devices */
16948     if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0)
16949         return -1;
16950 
16951     for (i = 0; i < n && i < VIR_DOMAIN_BOOT_LAST; i++) {
16952         int val;
16953         g_autofree char *dev = virXMLPropString(nodes[i], "dev");
16954         if (!dev) {
16955             virReportError(VIR_ERR_INTERNAL_ERROR,
16956                            "%s", _("missing boot device"));
16957             return -1;
16958         }
16959         if ((val = virDomainBootTypeFromString(dev)) < 0) {
16960             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
16961                            _("unknown boot device '%s'"),
16962                            dev);
16963             return -1;
16964         }
16965         def->os.bootDevs[def->os.nBootDevs++] = val;
16966     }
16967 
16968     if ((node = virXPathNode("./os/bootmenu[1]", ctxt))) {
16969         tmp = virXMLPropString(node, "enable");
16970         if (tmp) {
16971             def->os.bootmenu = virTristateBoolTypeFromString(tmp);
16972             if (def->os.bootmenu <= 0) {
16973                 /* In order not to break misconfigured machines, this
16974                  * should not emit an error, but rather set the bootmenu
16975                  * to disabled */
16976                 VIR_WARN("disabling bootmenu due to unknown option '%s'",
16977                          tmp);
16978                 def->os.bootmenu = VIR_TRISTATE_BOOL_NO;
16979             }
16980             VIR_FREE(tmp);
16981         }
16982 
16983         tmp = virXMLPropString(node, "timeout");
16984         if (tmp && def->os.bootmenu == VIR_TRISTATE_BOOL_YES) {
16985             if (virStrToLong_uip(tmp, NULL, 0, &def->os.bm_timeout) < 0) {
16986                 virReportError(VIR_ERR_XML_ERROR, "%s",
16987                                _("invalid value for boot menu timeout"));
16988                 return -1;
16989             }
16990             def->os.bm_timeout_set = true;
16991         }
16992         VIR_FREE(tmp);
16993     }
16994 
16995     if ((node = virXPathNode("./os/bios[1]", ctxt))) {
16996         tmp = virXMLPropString(node, "useserial");
16997         if (tmp) {
16998             bool state = false;
16999             ignore_value(virStringParseYesNo(tmp, &state));
17000             def->os.bios.useserial = virTristateBoolFromBool(state);
17001             VIR_FREE(tmp);
17002         }
17003 
17004         tmp = virXMLPropString(node, "rebootTimeout");
17005         if (tmp) {
17006             /* that was really just for the check if it is there */
17007 
17008             if (virStrToLong_i(tmp, NULL, 0, &def->os.bios.rt_delay) < 0) {
17009                 virReportError(VIR_ERR_XML_ERROR, "%s",
17010                                _("invalid value for rebootTimeout"));
17011                 return -1;
17012             }
17013             def->os.bios.rt_set = true;
17014         }
17015     }
17016 
17017     return 0;
17018 }
17019 
17020 
virDomainIdMapEntrySort(const void * a,const void * b)17021 static int virDomainIdMapEntrySort(const void *a, const void *b)
17022 {
17023     const virDomainIdMapEntry *entrya = a;
17024     const virDomainIdMapEntry *entryb = b;
17025 
17026     if (entrya->start > entryb->start)
17027         return 1;
17028     else if (entrya->start < entryb->start)
17029         return -1;
17030     else
17031         return 0;
17032 }
17033 
17034 /* Parse the XML definition for user namespace id map.
17035  *
17036  * idmap has the form of
17037  *
17038  *   <uid start='0' target='1000' count='10'/>
17039  *   <gid start='0' target='1000' count='10'/>
17040  */
17041 static virDomainIdMapEntry *
virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt,xmlNodePtr * node,size_t num)17042 virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt,
17043                           xmlNodePtr *node,
17044                           size_t num)
17045 {
17046     size_t i;
17047     virDomainIdMapEntry *idmap = NULL;
17048     VIR_XPATH_NODE_AUTORESTORE(ctxt)
17049 
17050     idmap = g_new0(virDomainIdMapEntry, num);
17051 
17052     for (i = 0; i < num; i++) {
17053         ctxt->node = node[i];
17054         if (virXPathUInt("string(./@start)", ctxt, &idmap[i].start) < 0 ||
17055             virXPathUInt("string(./@target)", ctxt, &idmap[i].target) < 0 ||
17056             virXPathUInt("string(./@count)", ctxt, &idmap[i].count) < 0) {
17057             virReportError(VIR_ERR_XML_ERROR, "%s",
17058                            _("invalid idmap start/target/count settings"));
17059             VIR_FREE(idmap);
17060             return NULL;
17061         }
17062     }
17063 
17064     qsort(idmap, num, sizeof(idmap[0]), virDomainIdMapEntrySort);
17065 
17066     return idmap;
17067 }
17068 
17069 /* Parse the XML definition for an IOThread ID
17070  *
17071  * Format is :
17072  *
17073  *     <iothreads>4</iothreads>
17074  *     <iothreadids>
17075  *       <iothread id='1'/>
17076  *       <iothread id='3'/>
17077  *       <iothread id='5'/>
17078  *       <iothread id='7'/>
17079  *     </iothreadids>
17080  */
17081 static virDomainIOThreadIDDef *
virDomainIOThreadIDDefParseXML(xmlNodePtr node)17082 virDomainIOThreadIDDefParseXML(xmlNodePtr node)
17083 {
17084     g_autoptr(virDomainIOThreadIDDef) iothrid = g_new0(virDomainIOThreadIDDef, 1);
17085 
17086     if (virXMLPropUInt(node, "id", 10,
17087                        VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
17088                        &iothrid->iothread_id) < 0)
17089         return NULL;
17090 
17091     return g_steal_pointer(&iothrid);
17092 }
17093 
17094 
17095 static int
virDomainDefParseIOThreads(virDomainDef * def,xmlXPathContextPtr ctxt)17096 virDomainDefParseIOThreads(virDomainDef *def,
17097                            xmlXPathContextPtr ctxt)
17098 {
17099     size_t i;
17100     int n = 0;
17101     unsigned int iothreads = 0;
17102     g_autofree char *tmp = NULL;
17103     g_autofree xmlNodePtr *nodes = NULL;
17104 
17105     tmp = virXPathString("string(./iothreads[1])", ctxt);
17106     if (tmp && virStrToLong_uip(tmp, NULL, 10, &iothreads) < 0) {
17107         virReportError(VIR_ERR_XML_ERROR,
17108                        _("invalid iothreads count '%s'"), tmp);
17109         return -1;
17110     }
17111 
17112     /* Extract any iothread id's defined */
17113     if ((n = virXPathNodeSet("./iothreadids/iothread", ctxt, &nodes)) < 0)
17114         return -1;
17115 
17116     if (n > iothreads)
17117         iothreads = n;
17118 
17119     if (n)
17120         def->iothreadids = g_new0(virDomainIOThreadIDDef *, n);
17121 
17122     for (i = 0; i < n; i++) {
17123         virDomainIOThreadIDDef *iothrid = NULL;
17124         if (!(iothrid = virDomainIOThreadIDDefParseXML(nodes[i])))
17125             return -1;
17126 
17127         if (virDomainIOThreadIDFind(def, iothrid->iothread_id)) {
17128             virReportError(VIR_ERR_XML_ERROR,
17129                            _("duplicate iothread id '%u' found"),
17130                            iothrid->iothread_id);
17131             virDomainIOThreadIDDefFree(iothrid);
17132             return -1;
17133         }
17134         def->iothreadids[def->niothreadids++] = iothrid;
17135     }
17136 
17137     return virDomainIOThreadIDDefArrayInit(def, iothreads);
17138 }
17139 
17140 
17141 /* Parse the XML definition for a vcpupin
17142  *
17143  * vcpupin has the form of
17144  *   <vcpupin vcpu='0' cpuset='0'/>
17145  */
17146 static int
virDomainVcpuPinDefParseXML(virDomainDef * def,xmlNodePtr node)17147 virDomainVcpuPinDefParseXML(virDomainDef *def,
17148                             xmlNodePtr node)
17149 {
17150     virDomainVcpuDef *vcpu;
17151     unsigned int vcpuid;
17152     g_autofree char *tmp = NULL;
17153 
17154     if (virXMLPropUInt(node, "vcpu", 10, VIR_XML_PROP_REQUIRED, &vcpuid) < 0)
17155         return -1;
17156 
17157     if (!(vcpu = virDomainDefGetVcpu(def, vcpuid))) {
17158         VIR_WARN("Ignoring vcpupin for missing vcpus");
17159         return 0;
17160     }
17161 
17162     if (!(tmp = virXMLPropString(node, "cpuset"))) {
17163         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
17164                        _("missing cpuset for vcpupin"));
17165         return -1;
17166     }
17167 
17168     if (vcpu->cpumask) {
17169         virReportError(VIR_ERR_INTERNAL_ERROR,
17170                        _("duplicate vcpupin for vcpu '%d'"), vcpuid);
17171         return -1;
17172     }
17173 
17174     if (virBitmapParse(tmp, &vcpu->cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0)
17175         return -1;
17176 
17177     if (virBitmapIsAllClear(vcpu->cpumask)) {
17178         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17179                        _("Invalid value of 'cpuset': %s"), tmp);
17180         return -1;
17181     }
17182 
17183     return 0;
17184 }
17185 
17186 
17187 /* Parse the XML definition for a iothreadpin
17188  * and an iothreadspin has the form
17189  *   <iothreadpin iothread='1' cpuset='2'/>
17190  */
17191 static int
virDomainIOThreadPinDefParseXML(xmlNodePtr node,virDomainDef * def)17192 virDomainIOThreadPinDefParseXML(xmlNodePtr node,
17193                                 virDomainDef *def)
17194 {
17195     virDomainIOThreadIDDef *iothrid;
17196     unsigned int iothreadid;
17197     g_autofree char *tmp = NULL;
17198     g_autoptr(virBitmap) cpumask = NULL;
17199 
17200     if (virXMLPropUInt(node, "iothread", 10,
17201                        VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
17202                        &iothreadid) < 0)
17203         return -1;
17204 
17205     if (!(iothrid = virDomainIOThreadIDFind(def, iothreadid))) {
17206         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17207                        _("Cannot find 'iothread' : %u"),
17208                        iothreadid);
17209         return -1;
17210     }
17211 
17212     if (!(tmp = virXMLPropString(node, "cpuset"))) {
17213         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
17214                        _("missing cpuset for iothreadpin"));
17215         return -1;
17216     }
17217 
17218     if (virBitmapParse(tmp, &cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0)
17219         return -1;
17220 
17221     if (virBitmapIsAllClear(cpumask)) {
17222         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17223                        _("Invalid value of 'cpuset': %s"),
17224                        tmp);
17225         return -1;
17226     }
17227 
17228     if (iothrid->cpumask) {
17229         virReportError(VIR_ERR_INTERNAL_ERROR,
17230                        _("duplicate iothreadpin for same iothread '%u'"),
17231                        iothreadid);
17232         return -1;
17233     }
17234 
17235     iothrid->cpumask = g_steal_pointer(&cpumask);
17236     return 0;
17237 }
17238 
17239 
17240 /* Parse the XML definition for emulatorpin.
17241  * emulatorpin has the form of
17242  *   <emulatorpin cpuset='0'/>
17243  */
17244 static virBitmap *
virDomainEmulatorPinDefParseXML(xmlNodePtr node)17245 virDomainEmulatorPinDefParseXML(xmlNodePtr node)
17246 {
17247     g_autofree char *tmp = NULL;
17248     g_autoptr(virBitmap) def = NULL;
17249 
17250     if (!(tmp = virXMLPropString(node, "cpuset"))) {
17251         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
17252                        _("missing cpuset for emulatorpin"));
17253         return NULL;
17254     }
17255 
17256     if (virBitmapParse(tmp, &def, VIR_DOMAIN_CPUMASK_LEN) < 0)
17257         return NULL;
17258 
17259     if (virBitmapIsAllClear(def)) {
17260         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17261                        _("Invalid value of 'cpuset': %s"), tmp);
17262         return NULL;
17263     }
17264 
17265     return g_steal_pointer(&def);
17266 }
17267 
17268 
17269 virDomainControllerDef *
virDomainDefAddController(virDomainDef * def,int type,int idx,int model)17270 virDomainDefAddController(virDomainDef *def, int type, int idx, int model)
17271 {
17272     virDomainControllerDef *cont;
17273 
17274     if (!(cont = virDomainControllerDefNew(type)))
17275         return NULL;
17276 
17277     if (idx < 0)
17278         idx = virDomainControllerFindUnusedIndex(def, type);
17279 
17280     cont->idx = idx;
17281     cont->model = model;
17282 
17283     VIR_APPEND_ELEMENT_COPY(def->controllers, def->ncontrollers, cont);
17284 
17285     return cont;
17286 }
17287 
17288 
17289 /**
17290  * virDomainDefAddUSBController:
17291  * @def:   the domain
17292  * @idx:   index for new controller (or -1 for "lowest unused index")
17293  * @model: VIR_DOMAIN_CONTROLLER_MODEL_USB_* or -1
17294  *
17295  * Add a USB controller of the specified model (or default model for
17296  * current machinetype if model == -1). If model is ich9-usb-ehci,
17297  * also add companion uhci1, uhci2, and uhci3 controllers at the same
17298  * index.
17299  *
17300  * Returns 0 on success, -1 on failure.
17301  */
17302 int
virDomainDefAddUSBController(virDomainDef * def,int idx,int model)17303 virDomainDefAddUSBController(virDomainDef *def, int idx, int model)
17304 {
17305     virDomainControllerDef *cont; /* this is a *copy* of the virDomainControllerDef */
17306 
17307     cont = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_USB,
17308                                      idx, model);
17309     if (!cont)
17310         return -1;
17311 
17312     if (model != VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1)
17313         return 0;
17314 
17315     /* When the initial controller is ich9-usb-ehci, also add the
17316      * companion controllers
17317      */
17318 
17319     idx = cont->idx; /* in case original request was "-1" */
17320 
17321     if (!(cont = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_USB,
17322                                            idx, VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1)))
17323         return -1;
17324     cont->info.mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
17325     cont->info.master.usb.startport = 0;
17326 
17327     if (!(cont = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_USB,
17328                                            idx, VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2)))
17329         return -1;
17330     cont->info.mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
17331     cont->info.master.usb.startport = 2;
17332 
17333     if (!(cont = virDomainDefAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_USB,
17334                                            idx, VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3)))
17335         return -1;
17336     cont->info.mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
17337     cont->info.master.usb.startport = 4;
17338 
17339     return 0;
17340 }
17341 
17342 
17343 int
virDomainDefMaybeAddController(virDomainDef * def,int type,int idx,int model)17344 virDomainDefMaybeAddController(virDomainDef *def,
17345                                int type,
17346                                int idx,
17347                                int model)
17348 {
17349     /* skip if a specific index was given and it is already
17350      * in use for that type of controller
17351      */
17352     if (idx >= 0 && virDomainControllerFind(def, type, idx) >= 0)
17353         return 0;
17354 
17355     if (virDomainDefAddController(def, type, idx, model))
17356         return 1;
17357     return -1;
17358 }
17359 
17360 
17361 int
virDomainDefMaybeAddInput(virDomainDef * def,int type,int bus)17362 virDomainDefMaybeAddInput(virDomainDef *def,
17363                           int type,
17364                           int bus)
17365 {
17366     size_t i;
17367     virDomainInputDef *input;
17368 
17369     for (i = 0; i < def->ninputs; i++) {
17370         if (def->inputs[i]->type == type &&
17371             def->inputs[i]->bus == bus)
17372             return 0;
17373     }
17374 
17375     input = g_new0(virDomainInputDef, 1);
17376 
17377     input->type = type;
17378     input->bus = bus;
17379 
17380     VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input);
17381 
17382     return 0;
17383 }
17384 
17385 
17386 static int
virDomainHugepagesParseXML(xmlNodePtr node,xmlXPathContextPtr ctxt,virDomainHugePage * hugepage)17387 virDomainHugepagesParseXML(xmlNodePtr node,
17388                            xmlXPathContextPtr ctxt,
17389                            virDomainHugePage *hugepage)
17390 {
17391     VIR_XPATH_NODE_AUTORESTORE(ctxt)
17392     g_autofree char *nodeset = NULL;
17393 
17394     ctxt->node = node;
17395 
17396     if (virDomainParseMemory("./@size", "./@unit", ctxt,
17397                              &hugepage->size, true, false) < 0)
17398         return -1;
17399 
17400     if (!hugepage->size) {
17401         virReportError(VIR_ERR_XML_DETAIL, "%s",
17402                        _("hugepage size can't be zero"));
17403         return -1;
17404     }
17405 
17406     if ((nodeset = virXMLPropString(node, "nodeset"))) {
17407         if (virBitmapParse(nodeset, &hugepage->nodemask,
17408                            VIR_DOMAIN_CPUMASK_LEN) < 0)
17409             return -1;
17410 
17411         if (virBitmapIsAllClear(hugepage->nodemask)) {
17412             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17413                            _("Invalid value of 'nodeset': %s"), nodeset);
17414             return -1;
17415         }
17416     }
17417 
17418     return 0;
17419 }
17420 
17421 
17422 static virDomainResourceDef *
virDomainResourceDefParse(xmlNodePtr node,xmlXPathContextPtr ctxt)17423 virDomainResourceDefParse(xmlNodePtr node,
17424                           xmlXPathContextPtr ctxt)
17425 {
17426     VIR_XPATH_NODE_AUTORESTORE(ctxt)
17427     virDomainResourceDef *def = NULL;
17428     char *partition = NULL;
17429     char *appid = NULL;
17430 
17431     ctxt->node = node;
17432 
17433     partition = virXPathString("string(./partition)", ctxt);
17434     appid = virXPathString("string(./fibrechannel/@appid)", ctxt);
17435 
17436     if (!partition && !appid)
17437         return NULL;
17438 
17439     def = g_new0(virDomainResourceDef, 1);
17440     def->partition = partition;
17441     def->appid = appid;
17442 
17443     return def;
17444 }
17445 
17446 
17447 static int
virDomainFeaturesHyperVDefParse(virDomainDef * def,xmlNodePtr node)17448 virDomainFeaturesHyperVDefParse(virDomainDef *def,
17449                                 xmlNodePtr node)
17450 {
17451     def->features[VIR_DOMAIN_FEATURE_HYPERV] = VIR_TRISTATE_SWITCH_ON;
17452 
17453     node = xmlFirstElementChild(node);
17454     while (node != NULL) {
17455         int feature;
17456         virTristateSwitch value;
17457         xmlNodePtr child;
17458 
17459         feature = virDomainHypervTypeFromString((const char *)node->name);
17460         if (feature < 0) {
17461             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17462                            _("unsupported HyperV Enlightenment feature: %s"),
17463                            node->name);
17464             return -1;
17465         }
17466 
17467         if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_REQUIRED,
17468                                      &value) < 0)
17469             return -1;
17470 
17471         def->hyperv_features[feature] = value;
17472 
17473         switch ((virDomainHyperv) feature) {
17474         case VIR_DOMAIN_HYPERV_RELAXED:
17475         case VIR_DOMAIN_HYPERV_VAPIC:
17476         case VIR_DOMAIN_HYPERV_VPINDEX:
17477         case VIR_DOMAIN_HYPERV_RUNTIME:
17478         case VIR_DOMAIN_HYPERV_SYNIC:
17479         case VIR_DOMAIN_HYPERV_RESET:
17480         case VIR_DOMAIN_HYPERV_FREQUENCIES:
17481         case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
17482         case VIR_DOMAIN_HYPERV_TLBFLUSH:
17483         case VIR_DOMAIN_HYPERV_IPI:
17484         case VIR_DOMAIN_HYPERV_EVMCS:
17485             break;
17486 
17487         case VIR_DOMAIN_HYPERV_STIMER:
17488             if (value != VIR_TRISTATE_SWITCH_ON)
17489                 break;
17490 
17491             child = xmlFirstElementChild(node);
17492             while (child) {
17493                 if (STRNEQ((const char *)child->name, "direct")) {
17494                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17495                                    _("unsupported Hyper-V stimer feature: %s"),
17496                                    child->name);
17497                     return -1;
17498                 }
17499 
17500                 if (virXMLPropTristateSwitch(child, "state", VIR_XML_PROP_REQUIRED,
17501                                              &def->hyperv_stimer_direct) < 0)
17502                     return -1;
17503 
17504                 child = xmlNextElementSibling(child);
17505             }
17506             break;
17507 
17508         case VIR_DOMAIN_HYPERV_SPINLOCKS:
17509             if (value != VIR_TRISTATE_SWITCH_ON)
17510                 break;
17511 
17512             if (virXMLPropUInt(node, "retries", 0, VIR_XML_PROP_REQUIRED,
17513                                &def->hyperv_spinlocks) < 0)
17514                 return -1;
17515 
17516             if (def->hyperv_spinlocks < 0xFFF) {
17517                 virReportError(VIR_ERR_XML_ERROR, "%s",
17518                                _("HyperV spinlock retry count must be at least 4095"));
17519                 return -1;
17520             }
17521             break;
17522 
17523         case VIR_DOMAIN_HYPERV_VENDOR_ID:
17524             if (value != VIR_TRISTATE_SWITCH_ON)
17525                 break;
17526 
17527             if (!(def->hyperv_vendor_id = virXMLPropString(node, "value"))) {
17528                 virReportError(VIR_ERR_XML_ERROR, "%s",
17529                                _("missing 'value' attribute for HyperV feature 'vendor_id'"));
17530                 return -1;
17531             }
17532 
17533             if (strlen(def->hyperv_vendor_id) > VIR_DOMAIN_HYPERV_VENDOR_ID_MAX) {
17534                 virReportError(VIR_ERR_XML_ERROR,
17535                                _("HyperV vendor_id value must not be more than %d characters."),
17536                                VIR_DOMAIN_HYPERV_VENDOR_ID_MAX);
17537                 return -1;
17538             }
17539 
17540             /* ensure that the string can be passed to qemu */
17541             if (strchr(def->hyperv_vendor_id, ',')) {
17542                 virReportError(VIR_ERR_XML_ERROR, "%s",
17543                                _("HyperV vendor_id value is invalid"));
17544                 return -1;
17545             }
17546             break;
17547 
17548         case VIR_DOMAIN_HYPERV_LAST:
17549             break;
17550         }
17551 
17552         node = xmlNextElementSibling(node);
17553     }
17554 
17555     return 0;
17556 }
17557 
17558 
17559 static int
virDomainFeaturesKVMDefParse(virDomainDef * def,xmlNodePtr node)17560 virDomainFeaturesKVMDefParse(virDomainDef *def,
17561                              xmlNodePtr node)
17562 {
17563     def->features[VIR_DOMAIN_FEATURE_KVM] = VIR_TRISTATE_SWITCH_ON;
17564 
17565     node = xmlFirstElementChild(node);
17566     while (node) {
17567         int feature;
17568         virTristateSwitch value;
17569 
17570         feature = virDomainKVMTypeFromString((const char *)node->name);
17571         if (feature < 0) {
17572             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17573                            _("unsupported KVM feature: %s"),
17574                            node->name);
17575             return -1;
17576         }
17577 
17578         if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_REQUIRED,
17579                                      &value) < 0)
17580             return -1;
17581 
17582         def->kvm_features[feature] = value;
17583 
17584         node = xmlNextElementSibling(node);
17585     }
17586 
17587     return 0;
17588 }
17589 
17590 
17591 static int
virDomainFeaturesXENDefParse(virDomainDef * def,xmlNodePtr node)17592 virDomainFeaturesXENDefParse(virDomainDef *def,
17593                              xmlNodePtr node)
17594 {
17595     def->features[VIR_DOMAIN_FEATURE_XEN] = VIR_TRISTATE_SWITCH_ON;
17596 
17597     node = xmlFirstElementChild(node);
17598     while (node) {
17599         int feature;
17600         virTristateSwitch value;
17601 
17602         feature = virDomainXenTypeFromString((const char *)node->name);
17603         if (feature < 0) {
17604             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17605                            _("unsupported Xen feature: %s"),
17606                            node->name);
17607             return -1;
17608         }
17609 
17610         if (virXMLPropTristateSwitch(node, "state",
17611                                      VIR_XML_PROP_REQUIRED, &value) < 0)
17612             return -1;
17613 
17614         def->xen_features[feature] = value;
17615 
17616         switch ((virDomainXen) feature) {
17617         case VIR_DOMAIN_XEN_E820_HOST:
17618             break;
17619 
17620         case VIR_DOMAIN_XEN_PASSTHROUGH:
17621             if (value != VIR_TRISTATE_SWITCH_ON)
17622                 break;
17623 
17624             if (virXMLPropEnum(node, "mode",
17625                                virDomainXenPassthroughModeTypeFromString,
17626                                VIR_XML_PROP_NONZERO,
17627                                &def->xen_passthrough_mode) < 0)
17628                 return -1;
17629             break;
17630 
17631             case VIR_DOMAIN_XEN_LAST:
17632                 break;
17633         }
17634 
17635         node = xmlNextElementSibling(node);
17636     }
17637 
17638     return 0;
17639 }
17640 
17641 
17642 static int
virDomainFeaturesCapabilitiesDefParse(virDomainDef * def,xmlNodePtr node)17643 virDomainFeaturesCapabilitiesDefParse(virDomainDef *def,
17644                                       xmlNodePtr node)
17645 {
17646     virDomainCapabilitiesPolicy policy;
17647 
17648     if (virXMLPropEnumDefault(node, "policy",
17649                               virDomainCapabilitiesPolicyTypeFromString,
17650                               VIR_XML_PROP_NONE, &policy,
17651                               VIR_DOMAIN_CAPABILITIES_POLICY_DEFAULT) < 0)
17652         return -1;
17653 
17654     def->features[VIR_DOMAIN_FEATURE_CAPABILITIES] = policy;
17655 
17656     node = xmlFirstElementChild(node);
17657     while (node) {
17658         virTristateSwitch state;
17659         int val = virDomainProcessCapsFeatureTypeFromString((const char *)node->name);
17660         if (val < 0) {
17661             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17662                            _("unexpected capability feature '%s'"), node->name);
17663             return -1;
17664         }
17665 
17666 
17667         if (virXMLPropTristateSwitch(node, "state", VIR_XML_PROP_NONE, &state) < 0)
17668             return -1;
17669 
17670         if (state == VIR_TRISTATE_SWITCH_ABSENT)
17671             state = VIR_TRISTATE_SWITCH_ON;
17672 
17673         def->caps_features[val] = state;
17674         node = xmlNextElementSibling(node);
17675     }
17676 
17677     return 0;
17678 }
17679 
17680 
17681 static int
virDomainFeaturesDefParse(virDomainDef * def,xmlXPathContextPtr ctxt)17682 virDomainFeaturesDefParse(virDomainDef *def,
17683                           xmlXPathContextPtr ctxt)
17684 {
17685     g_autofree xmlNodePtr *nodes = NULL;
17686     size_t i;
17687     int n;
17688 
17689     if ((n = virXPathNodeSet("./features/*", ctxt, &nodes)) < 0)
17690         return -1;
17691 
17692     for (i = 0; i < n; i++) {
17693         int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name);
17694         if (val < 0) {
17695             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17696                            _("unexpected feature '%s'"), nodes[i]->name);
17697             return -1;
17698         }
17699 
17700         switch ((virDomainFeature) val) {
17701         case VIR_DOMAIN_FEATURE_ACPI:
17702         case VIR_DOMAIN_FEATURE_PAE:
17703         case VIR_DOMAIN_FEATURE_VIRIDIAN:
17704         case VIR_DOMAIN_FEATURE_PRIVNET:
17705             def->features[val] = VIR_TRISTATE_SWITCH_ON;
17706             break;
17707 
17708         case VIR_DOMAIN_FEATURE_APIC: {
17709             virTristateSwitch eoi;
17710             if (virXMLPropTristateSwitch(nodes[i], "eoi", VIR_XML_PROP_NONE, &eoi) < 0)
17711                 return -1;
17712 
17713             def->features[val] = VIR_TRISTATE_SWITCH_ON;
17714             def->apic_eoi = eoi;
17715             break;
17716         }
17717 
17718         case VIR_DOMAIN_FEATURE_MSRS: {
17719             virDomainMsrsUnknown unknown;
17720             if (virXMLPropEnum(nodes[i], "unknown",
17721                                virDomainMsrsUnknownTypeFromString,
17722                                VIR_XML_PROP_REQUIRED, &unknown) < 0)
17723                 return -1;
17724 
17725             def->features[val] = VIR_TRISTATE_SWITCH_ON;
17726             def->msrs_features[VIR_DOMAIN_MSRS_UNKNOWN] = unknown;
17727             break;
17728         }
17729 
17730         case VIR_DOMAIN_FEATURE_HYPERV:
17731             if (virDomainFeaturesHyperVDefParse(def, nodes[i]) < 0)
17732                 return -1;
17733             break;
17734 
17735         case VIR_DOMAIN_FEATURE_KVM:
17736             if (virDomainFeaturesKVMDefParse(def, nodes[i]) < 0)
17737                 return -1;
17738             break;
17739 
17740         case VIR_DOMAIN_FEATURE_XEN:
17741             if (virDomainFeaturesXENDefParse(def, nodes[i]) < 0)
17742                 return -1;
17743             break;
17744 
17745         case VIR_DOMAIN_FEATURE_CAPABILITIES: {
17746             if (virDomainFeaturesCapabilitiesDefParse(def, nodes[i]) < 0)
17747                 return -1;
17748             break;
17749         }
17750 
17751         case VIR_DOMAIN_FEATURE_VMCOREINFO:
17752         case VIR_DOMAIN_FEATURE_HAP:
17753         case VIR_DOMAIN_FEATURE_PMU:
17754         case VIR_DOMAIN_FEATURE_PVSPINLOCK:
17755         case VIR_DOMAIN_FEATURE_VMPORT: {
17756             virTristateSwitch state;
17757 
17758             if (virXMLPropTristateSwitch(nodes[i], "state",
17759                                          VIR_XML_PROP_NONE, &state) < 0)
17760                 return -1;
17761 
17762             if (state == VIR_TRISTATE_SWITCH_ABSENT)
17763                 state = VIR_TRISTATE_SWITCH_ON;
17764 
17765             def->features[val] = state;
17766             break;
17767         }
17768 
17769         case VIR_DOMAIN_FEATURE_SMM: {
17770             virTristateSwitch state;
17771 
17772             if (virXMLPropTristateSwitch(nodes[i], "state",
17773                                          VIR_XML_PROP_NONE, &state) < 0)
17774                 return -1;
17775 
17776             if ((state == VIR_TRISTATE_SWITCH_ABSENT) ||
17777                 (state == VIR_TRISTATE_SWITCH_ON)) {
17778                 int rv = virParseScaledValue("string(./features/smm/tseg)",
17779                                              "string(./features/smm/tseg/@unit)",
17780                                              ctxt,
17781                                              &def->tseg_size,
17782                                              1024 * 1024, /* Defaults to mebibytes */
17783                                              ULLONG_MAX,
17784                                              false);
17785                 if (rv < 0)
17786                     return -1;
17787 
17788                 def->features[val] = VIR_TRISTATE_SWITCH_ON;
17789                 def->tseg_specified = rv != 0;
17790             }
17791             break;
17792         }
17793 
17794         case VIR_DOMAIN_FEATURE_GIC:
17795             if (virXMLPropEnum(nodes[i], "version", virGICVersionTypeFromString,
17796                                VIR_XML_PROP_NONZERO, &def->gic_version) < 0)
17797                 return -1;
17798 
17799             def->features[val] = VIR_TRISTATE_SWITCH_ON;
17800             break;
17801 
17802         case VIR_DOMAIN_FEATURE_IOAPIC: {
17803             virDomainIOAPIC driver;
17804 
17805             if (virXMLPropEnumDefault(nodes[i], "driver", virDomainIOAPICTypeFromString,
17806                                       VIR_XML_PROP_NONZERO, &driver,
17807                                       VIR_DOMAIN_IOAPIC_NONE) < 0)
17808                 return -1;
17809 
17810             def->features[val] = driver;
17811             break;
17812         }
17813 
17814         case VIR_DOMAIN_FEATURE_HPT:
17815             if (virXMLPropEnum(nodes[i], "resizing",
17816                                virDomainHPTResizingTypeFromString,
17817                                VIR_XML_PROP_NONZERO, &def->hpt_resizing) < 0)
17818                 return -1;
17819 
17820             if (virParseScaledValue("./features/hpt/maxpagesize",
17821                                     NULL,
17822                                     ctxt,
17823                                     &def->hpt_maxpagesize,
17824                                     1024,
17825                                     ULLONG_MAX,
17826                                     false) < 0) {
17827                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
17828                                "%s",
17829                                _("Unable to parse HPT maxpagesize setting"));
17830                 return -1;
17831             }
17832             def->hpt_maxpagesize = VIR_DIV_UP(def->hpt_maxpagesize, 1024);
17833 
17834             if (def->hpt_resizing != VIR_DOMAIN_HPT_RESIZING_NONE ||
17835                 def->hpt_maxpagesize > 0) {
17836                 def->features[val] = VIR_TRISTATE_SWITCH_ON;
17837             }
17838             break;
17839 
17840         case VIR_DOMAIN_FEATURE_CFPC: {
17841             virDomainCFPC value;
17842 
17843             if (virXMLPropEnumDefault(nodes[i], "value", virDomainCFPCTypeFromString,
17844                                       VIR_XML_PROP_NONZERO, &value,
17845                                       VIR_DOMAIN_CFPC_NONE) < 0)
17846                 return -1;
17847 
17848             def->features[val] = value;
17849             break;
17850         }
17851 
17852         case VIR_DOMAIN_FEATURE_SBBC: {
17853             virDomainSBBC value;
17854 
17855             if (virXMLPropEnumDefault(nodes[i], "value", virDomainSBBCTypeFromString,
17856                                       VIR_XML_PROP_NONZERO, &value,
17857                                       VIR_DOMAIN_SBBC_NONE) < 0)
17858                 return -1;
17859 
17860             def->features[val] = value;
17861             break;
17862         }
17863 
17864         case VIR_DOMAIN_FEATURE_IBS: {
17865             virDomainIBS value;
17866 
17867             if (virXMLPropEnumDefault(nodes[i], "value", virDomainIBSTypeFromString,
17868                                       VIR_XML_PROP_NONZERO, &value,
17869                                       VIR_DOMAIN_IBS_NONE) < 0)
17870                 return -1;
17871 
17872             def->features[val] = value;
17873             break;
17874         }
17875 
17876         case VIR_DOMAIN_FEATURE_HTM:
17877         case VIR_DOMAIN_FEATURE_NESTED_HV:
17878         case VIR_DOMAIN_FEATURE_CCF_ASSIST: {
17879             virTristateSwitch state;
17880 
17881             if (virXMLPropTristateSwitch(nodes[i], "state",
17882                                          VIR_XML_PROP_REQUIRED, &state) < 0)
17883                 return -1;
17884 
17885             def->features[val] = state;
17886             break;
17887         }
17888 
17889         case VIR_DOMAIN_FEATURE_LAST:
17890             break;
17891         }
17892     }
17893 
17894     return 0;
17895 }
17896 
17897 
17898 static int
virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDef * def)17899 virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDef *def)
17900 {
17901     /* Look for any hostdev scsi dev */
17902     size_t i;
17903     int maxController = -1;
17904     virDomainHostdevDef *hostdev;
17905     int newModel = -1;
17906 
17907     for (i = 0; i < def->nhostdevs; i++) {
17908         hostdev = def->hostdevs[i];
17909         if (virHostdevIsSCSIDevice(hostdev) &&
17910             (int)hostdev->info->addr.drive.controller > maxController) {
17911             virDomainControllerDef *cont;
17912 
17913             maxController = hostdev->info->addr.drive.controller;
17914             /* We may be creating a new controller because this one is full.
17915              * So let's grab the model from it and update the model we're
17916              * going to add as long as this one isn't undefined. The premise
17917              * being keeping the same controller model for all SCSI hostdevs. */
17918             cont = virDomainDeviceFindSCSIController(def, &hostdev->info->addr.drive);
17919             if (cont && cont->model != -1)
17920                 newModel = cont->model;
17921         }
17922     }
17923 
17924     if (maxController == -1)
17925         return 0;
17926 
17927     for (i = 0; i <= maxController; i++) {
17928         if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
17929                                            i, newModel) < 0)
17930             return -1;
17931     }
17932 
17933     return 0;
17934 }
17935 
17936 static int
virDomainLoaderDefParseXML(xmlNodePtr node,virDomainLoaderDef * loader,bool fwAutoSelect)17937 virDomainLoaderDefParseXML(xmlNodePtr node,
17938                            virDomainLoaderDef *loader,
17939                            bool fwAutoSelect)
17940 {
17941     if (!fwAutoSelect) {
17942         if (virXMLPropTristateBool(node, "readonly", VIR_XML_PROP_NONE,
17943                                    &loader->readonly) < 0)
17944             return -1;
17945 
17946         if (virXMLPropEnum(node, "type", virDomainLoaderTypeFromString,
17947                            VIR_XML_PROP_NONZERO, &loader->type) < 0)
17948             return -1;
17949 
17950         if (!(loader->path = virXMLNodeContentString(node)))
17951             return -1;
17952 
17953         if (STREQ(loader->path, ""))
17954             VIR_FREE(loader->path);
17955     }
17956 
17957     if (virXMLPropTristateBool(node, "secure", VIR_XML_PROP_NONE,
17958                                &loader->secure) < 0)
17959         return -1;
17960 
17961     return 0;
17962 }
17963 
17964 
17965 static int
virDomainSchedulerParseCommonAttrs(xmlNodePtr node,virProcessSchedPolicy * policy,int * priority)17966 virDomainSchedulerParseCommonAttrs(xmlNodePtr node,
17967                                    virProcessSchedPolicy *policy,
17968                                    int *priority)
17969 {
17970     if (virXMLPropEnum(node, "scheduler", virProcessSchedPolicyTypeFromString,
17971                        VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO,
17972                        policy) < 0)
17973         return -1;
17974 
17975     if (*policy == VIR_PROC_POLICY_FIFO || *policy == VIR_PROC_POLICY_RR) {
17976         if (virXMLPropInt(node, "priority", 10, VIR_XML_PROP_REQUIRED,
17977                           priority, 0) < 0)
17978             return -1;
17979     }
17980 
17981     return 0;
17982 }
17983 
17984 
17985 static int
virDomainEmulatorSchedParse(xmlNodePtr node,virDomainDef * def)17986 virDomainEmulatorSchedParse(xmlNodePtr node,
17987                             virDomainDef *def)
17988 {
17989     g_autofree virDomainThreadSchedParam *sched = NULL;
17990 
17991     sched = g_new0(virDomainThreadSchedParam, 1);
17992 
17993     if (virDomainSchedulerParseCommonAttrs(node,
17994                                            &sched->policy,
17995                                            &sched->priority) < 0)
17996         return -1;
17997 
17998     def->cputune.emulatorsched = g_steal_pointer(&sched);
17999     return 0;
18000 }
18001 
18002 
18003 static virBitmap *
virDomainSchedulerParse(xmlNodePtr node,const char * elementName,const char * attributeName,virProcessSchedPolicy * policy,int * priority)18004 virDomainSchedulerParse(xmlNodePtr node,
18005                         const char *elementName,
18006                         const char *attributeName,
18007                         virProcessSchedPolicy *policy,
18008                         int *priority)
18009 {
18010     virBitmap *ret = NULL;
18011     g_autofree char *tmp = NULL;
18012 
18013     if (!(tmp = virXMLPropString(node, attributeName))) {
18014         virReportError(VIR_ERR_XML_ERROR,
18015                        _("Missing attribute '%s' in element '%s'"),
18016                        attributeName, elementName);
18017         goto error;
18018     }
18019 
18020     if (virBitmapParse(tmp, &ret, VIR_DOMAIN_CPUMASK_LEN) < 0)
18021         goto error;
18022 
18023     if (virBitmapIsAllClear(ret)) {
18024         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18025                        _("'%s' scheduler bitmap '%s' is empty"),
18026                        attributeName, tmp);
18027         goto error;
18028     }
18029 
18030     if (virDomainSchedulerParseCommonAttrs(node, policy, priority) < 0)
18031         goto error;
18032 
18033     return ret;
18034 
18035  error:
18036     virBitmapFree(ret);
18037     return NULL;
18038 }
18039 
18040 
18041 static int
virDomainThreadSchedParseHelper(xmlNodePtr node,const char * elementName,const char * attributeName,virDomainThreadSchedParam * (* func)(virDomainDef *,unsigned int),virDomainDef * def)18042 virDomainThreadSchedParseHelper(xmlNodePtr node,
18043                                 const char *elementName,
18044                                 const char *attributeName,
18045                                 virDomainThreadSchedParam *(*func)(virDomainDef *, unsigned int),
18046                                 virDomainDef *def)
18047 {
18048     ssize_t next = -1;
18049     virDomainThreadSchedParam *sched = NULL;
18050     virProcessSchedPolicy policy = 0;
18051     int priority = 0;
18052     g_autoptr(virBitmap) map = NULL;
18053 
18054     if (!(map = virDomainSchedulerParse(node, elementName, attributeName,
18055                                         &policy, &priority)))
18056         return -1;
18057 
18058     while ((next = virBitmapNextSetBit(map, next)) > -1) {
18059         if (!(sched = func(def, next)))
18060             return -1;
18061 
18062         if (sched->policy != VIR_PROC_POLICY_NONE) {
18063             virReportError(VIR_ERR_XML_DETAIL,
18064                            _("'%s' attributes '%s' must not overlap"),
18065                            elementName, attributeName);
18066             return -1;
18067         }
18068 
18069         sched->policy = policy;
18070         sched->priority = priority;
18071     }
18072 
18073     return 0;
18074 }
18075 
18076 
18077 static int
virDomainVcpuThreadSchedParse(xmlNodePtr node,virDomainDef * def)18078 virDomainVcpuThreadSchedParse(xmlNodePtr node,
18079                               virDomainDef *def)
18080 {
18081     return virDomainThreadSchedParseHelper(node,
18082                                            "vcpusched",
18083                                            "vcpus",
18084                                            virDomainDefGetVcpuSched,
18085                                            def);
18086 }
18087 
18088 
18089 static virDomainThreadSchedParam *
virDomainDefGetIOThreadSched(virDomainDef * def,unsigned int iothread)18090 virDomainDefGetIOThreadSched(virDomainDef *def,
18091                              unsigned int iothread)
18092 {
18093     virDomainIOThreadIDDef *iothrinfo;
18094 
18095     if (!(iothrinfo = virDomainIOThreadIDFind(def, iothread))) {
18096         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18097                        _("Cannot find 'iothread' : %u"),
18098                        iothread);
18099         return NULL;
18100     }
18101 
18102     return &iothrinfo->sched;
18103 }
18104 
18105 
18106 static int
virDomainIOThreadSchedParse(xmlNodePtr node,virDomainDef * def)18107 virDomainIOThreadSchedParse(xmlNodePtr node,
18108                             virDomainDef *def)
18109 {
18110     return virDomainThreadSchedParseHelper(node,
18111                                            "iothreadsched",
18112                                            "iothreads",
18113                                            virDomainDefGetIOThreadSched,
18114                                            def);
18115 }
18116 
18117 
18118 static int
virDomainVcpuParse(virDomainDef * def,xmlXPathContextPtr ctxt,virDomainXMLOption * xmlopt)18119 virDomainVcpuParse(virDomainDef *def,
18120                    xmlXPathContextPtr ctxt,
18121                    virDomainXMLOption *xmlopt)
18122 {
18123     int n;
18124     xmlNodePtr vcpuNode;
18125     size_t i;
18126     unsigned int maxvcpus;
18127     unsigned int vcpus;
18128     g_autofree char *tmp = NULL;
18129     g_autofree xmlNodePtr *nodes = NULL;
18130     int rc;
18131 
18132     vcpus = maxvcpus = 1;
18133 
18134     if ((vcpuNode = virXPathNode("./vcpu[1]", ctxt))) {
18135         if (!(tmp = virXMLNodeContentString(vcpuNode)))
18136             return -1;
18137 
18138         if (virStrToLong_ui(tmp, NULL, 10, &maxvcpus) < 0) {
18139             virReportError(VIR_ERR_XML_ERROR, "%s",
18140                            _("maximum vcpus count must be an integer"));
18141             return -1;
18142         }
18143         VIR_FREE(tmp);
18144 
18145         if ((rc = virXMLPropUInt(vcpuNode, "current", 10, VIR_XML_PROP_NONE, &vcpus)) < 0) {
18146             return -1;
18147         } else if (rc == 0) {
18148             vcpus = maxvcpus;
18149         }
18150 
18151         if (virXMLPropEnumDefault(vcpuNode, "placement",
18152                                   virDomainCpuPlacementModeTypeFromString,
18153                                   VIR_XML_PROP_NONE, &def->placement_mode,
18154                                   VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC) < 0)
18155             return -1;
18156 
18157         if (def->placement_mode != VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
18158             tmp = virXMLPropString(vcpuNode, "cpuset");
18159             if (tmp) {
18160                 if (virBitmapParse(tmp, &def->cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0)
18161                     return -1;
18162 
18163                 if (virBitmapIsAllClear(def->cpumask)) {
18164                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18165                                    _("Invalid value of 'cpuset': %s"), tmp);
18166                     return -1;
18167                 }
18168 
18169                 VIR_FREE(tmp);
18170             }
18171         }
18172     }
18173 
18174     if (virDomainDefSetVcpusMax(def, maxvcpus, xmlopt) < 0)
18175         return -1;
18176 
18177     if ((n = virXPathNodeSet("./vcpus/vcpu", ctxt, &nodes)) < 0)
18178         return -1;
18179 
18180     if (n) {
18181         /* if individual vcpu states are provided take them as master */
18182         def->individualvcpus = true;
18183 
18184         for (i = 0; i < n; i++) {
18185             virDomainVcpuDef *vcpu;
18186             virTristateBool state;
18187             unsigned int id;
18188 
18189             if (virXMLPropUInt(nodes[i], "id", 10, VIR_XML_PROP_REQUIRED, &id) < 0)
18190                 return -1;
18191 
18192             if (id >= def->maxvcpus) {
18193                 virReportError(VIR_ERR_XML_ERROR,
18194                                _("vcpu id '%u' is out of range of maximum "
18195                                  "vcpu count"), id);
18196                 return -1;
18197             }
18198 
18199             vcpu = virDomainDefGetVcpu(def, id);
18200 
18201             if (virXMLPropTristateBool(nodes[i], "enabled",
18202                                        VIR_XML_PROP_REQUIRED, &state) < 0)
18203                 return -1;
18204 
18205             vcpu->online = state == VIR_TRISTATE_BOOL_YES;
18206 
18207             if (virXMLPropTristateBool(nodes[i], "hotpluggable",
18208                                        VIR_XML_PROP_NONE,
18209                                        &vcpu->hotpluggable) < 0)
18210                 return -1;
18211 
18212             if (virXMLPropUInt(nodes[i], "order", 10, VIR_XML_PROP_NONE,
18213                                &vcpu->order) < 0)
18214                 return -1;
18215         }
18216     } else {
18217         if (virDomainDefSetVcpus(def, vcpus) < 0)
18218             return -1;
18219     }
18220 
18221     return 0;
18222 }
18223 
18224 
18225 static int
virDomainDefParseBootInitOptions(virDomainDef * def,xmlXPathContextPtr ctxt)18226 virDomainDefParseBootInitOptions(virDomainDef *def,
18227                                  xmlXPathContextPtr ctxt)
18228 {
18229     char *name = NULL;
18230     size_t i;
18231     int n;
18232     g_autofree xmlNodePtr *nodes = NULL;
18233 
18234     def->os.init = virXPathString("string(./os/init[1])", ctxt);
18235     def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
18236     def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
18237     def->os.inituser = virXPathString("string(./os/inituser[1])", ctxt);
18238     def->os.initgroup = virXPathString("string(./os/initgroup[1])", ctxt);
18239 
18240     if ((n = virXPathNodeSet("./os/initarg", ctxt, &nodes)) < 0)
18241         return -1;
18242 
18243     def->os.initargv = g_new0(char *, n+1);
18244     for (i = 0; i < n; i++) {
18245         if (!nodes[i]->children ||
18246             !nodes[i]->children->content) {
18247             virReportError(VIR_ERR_XML_ERROR, "%s",
18248                            _("No data supplied for <initarg> element"));
18249             return -1;
18250         }
18251         def->os.initargv[i] = g_strdup((const char *)nodes[i]->children->content);
18252     }
18253     def->os.initargv[n] = NULL;
18254     VIR_FREE(nodes);
18255 
18256     if ((n = virXPathNodeSet("./os/initenv", ctxt, &nodes)) < 0)
18257         return -1;
18258 
18259     def->os.initenv = g_new0(virDomainOSEnv *, n + 1);
18260     for (i = 0; i < n; i++) {
18261         if (!(name = virXMLPropString(nodes[i], "name"))) {
18262             virReportError(VIR_ERR_XML_ERROR, "%s",
18263                            _("No name supplied for <initenv> element"));
18264             return -1;
18265         }
18266 
18267         if (!nodes[i]->children ||
18268             !nodes[i]->children->content) {
18269             virReportError(VIR_ERR_XML_ERROR,
18270                            _("No value supplied for <initenv name='%s'> element"),
18271                            name);
18272             return -1;
18273         }
18274 
18275         def->os.initenv[i] = g_new0(virDomainOSEnv, 1);
18276         def->os.initenv[i]->name = name;
18277         def->os.initenv[i]->value = g_strdup((const char *)nodes[i]->children->content);
18278     }
18279     def->os.initenv[n] = NULL;
18280 
18281     return 0;
18282 }
18283 
18284 
18285 static void
virDomainDefParseBootKernelOptions(virDomainDef * def,xmlXPathContextPtr ctxt)18286 virDomainDefParseBootKernelOptions(virDomainDef *def,
18287                                    xmlXPathContextPtr ctxt)
18288 {
18289     def->os.kernel = virXPathString("string(./os/kernel[1])", ctxt);
18290     def->os.initrd = virXPathString("string(./os/initrd[1])", ctxt);
18291     def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
18292     def->os.dtb = virXPathString("string(./os/dtb[1])", ctxt);
18293     def->os.root = virXPathString("string(./os/root[1])", ctxt);
18294 }
18295 
18296 
18297 static int
virDomainDefParseBootFirmwareOptions(virDomainDef * def,xmlXPathContextPtr ctxt)18298 virDomainDefParseBootFirmwareOptions(virDomainDef *def,
18299                                      xmlXPathContextPtr ctxt)
18300 {
18301     g_autofree char *firmware = virXPathString("string(./os/@firmware)", ctxt);
18302     g_autofree xmlNodePtr *nodes = NULL;
18303     g_autofree int *features = NULL;
18304     int fw = 0;
18305     int n = 0;
18306     size_t i;
18307 
18308     if (!firmware)
18309         return 0;
18310 
18311     fw = virDomainOsDefFirmwareTypeFromString(firmware);
18312 
18313     if (fw <= 0) {
18314         virReportError(VIR_ERR_XML_ERROR,
18315                        _("unknown firmware value %s"),
18316                        firmware);
18317         return -1;
18318     }
18319 
18320     def->os.firmware = fw;
18321 
18322     if ((n = virXPathNodeSet("./os/firmware/feature", ctxt, &nodes)) < 0)
18323         return -1;
18324 
18325     if (n > 0)
18326         features = g_new0(int, VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_LAST);
18327 
18328     for (i = 0; i < n; i++) {
18329         g_autofree char *name = virXMLPropString(nodes[i], "name");
18330         g_autofree char *enabled = virXMLPropString(nodes[i], "enabled");
18331         int feature = virDomainOsDefFirmwareFeatureTypeFromString(name);
18332         int val = virTristateBoolTypeFromString(enabled);
18333 
18334         if (feature < 0) {
18335             virReportError(VIR_ERR_XML_ERROR,
18336                            _("invalid firmware feature name '%s'"),
18337                            name);
18338             return -1;
18339         }
18340 
18341         if (val < 0) {
18342             virReportError(VIR_ERR_XML_ERROR,
18343                            _("invalid firmware feature enabled value '%s'"),
18344                            enabled);
18345             return -1;
18346         }
18347 
18348         features[feature] = val;
18349     }
18350 
18351     def->os.firmwareFeatures = g_steal_pointer(&features);
18352 
18353     return 0;
18354 }
18355 
18356 
18357 static int
virDomainDefParseBootLoaderOptions(virDomainDef * def,xmlXPathContextPtr ctxt)18358 virDomainDefParseBootLoaderOptions(virDomainDef *def,
18359                                    xmlXPathContextPtr ctxt)
18360 {
18361     xmlNodePtr loader_node = virXPathNode("./os/loader[1]", ctxt);
18362     const bool fwAutoSelect = def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_NONE;
18363 
18364     if (!loader_node)
18365         return 0;
18366 
18367     def->os.loader = g_new0(virDomainLoaderDef, 1);
18368 
18369     if (virDomainLoaderDefParseXML(loader_node,
18370                                    def->os.loader,
18371                                    fwAutoSelect) < 0)
18372         return -1;
18373 
18374     def->os.loader->nvram = virXPathString("string(./os/nvram[1])", ctxt);
18375     if (!fwAutoSelect)
18376         def->os.loader->templt = virXPathString("string(./os/nvram[1]/@template)", ctxt);
18377 
18378     return 0;
18379 }
18380 
18381 
18382 static int
virDomainDefParseBootAcpiOptions(virDomainDef * def,xmlXPathContextPtr ctxt)18383 virDomainDefParseBootAcpiOptions(virDomainDef *def,
18384                                  xmlXPathContextPtr ctxt)
18385 {
18386     int n;
18387     g_autofree xmlNodePtr *nodes = NULL;
18388     g_autofree char *tmp = NULL;
18389 
18390     if ((n = virXPathNodeSet("./os/acpi/table", ctxt, &nodes)) < 0)
18391         return -1;
18392 
18393     if (n > 1) {
18394         virReportError(VIR_ERR_XML_ERROR, "%s",
18395                        _("Only one acpi table is supported"));
18396         return -1;
18397     }
18398 
18399     if (n == 1) {
18400         tmp = virXMLPropString(nodes[0], "type");
18401 
18402         if (!tmp) {
18403             virReportError(VIR_ERR_XML_ERROR, "%s",
18404                            _("Missing acpi table type"));
18405             return -1;
18406         }
18407 
18408         if (STREQ_NULLABLE(tmp, "slic")) {
18409             VIR_FREE(tmp);
18410             if (!(tmp = virXMLNodeContentString(nodes[0])))
18411                 return -1;
18412 
18413             def->os.slic_table = virFileSanitizePath(tmp);
18414         } else {
18415             virReportError(VIR_ERR_XML_ERROR,
18416                            _("Unknown acpi table type: %s"),
18417                            tmp);
18418             return -1;
18419         }
18420     }
18421 
18422     return 0;
18423 }
18424 
18425 
18426 static int
virDomainDefParseBootOptions(virDomainDef * def,xmlXPathContextPtr ctxt)18427 virDomainDefParseBootOptions(virDomainDef *def,
18428                              xmlXPathContextPtr ctxt)
18429 {
18430     /*
18431      * Booting options for different OS types....
18432      *
18433      *   - A bootloader (and optional kernel+initrd)  (xen)
18434      *   - A kernel + initrd                          (xen)
18435      *   - A boot device (and optional kernel+initrd) (hvm)
18436      *   - An init script                             (exe)
18437      */
18438 
18439     switch ((virDomainOSType) def->os.type) {
18440     case VIR_DOMAIN_OSTYPE_HVM:
18441         virDomainDefParseBootKernelOptions(def, ctxt);
18442 
18443         if (virDomainDefParseBootFirmwareOptions(def, ctxt) < 0)
18444             return -1;
18445 
18446         if (virDomainDefParseBootLoaderOptions(def, ctxt) < 0)
18447             return -1;
18448 
18449         if (virDomainDefParseBootAcpiOptions(def, ctxt) < 0)
18450             return -1;
18451 
18452         if (virDomainDefParseBootXML(ctxt, def) < 0)
18453             return -1;
18454 
18455         break;
18456 
18457     case VIR_DOMAIN_OSTYPE_XEN:
18458     case VIR_DOMAIN_OSTYPE_XENPVH:
18459     case VIR_DOMAIN_OSTYPE_UML:
18460         virDomainDefParseBootKernelOptions(def, ctxt);
18461 
18462         if (virDomainDefParseBootLoaderOptions(def, ctxt) < 0)
18463             return -1;
18464 
18465         break;
18466 
18467     case VIR_DOMAIN_OSTYPE_EXE:
18468         if (virDomainDefParseBootInitOptions(def, ctxt) < 0)
18469             return -1;
18470 
18471         break;
18472 
18473     case VIR_DOMAIN_OSTYPE_LINUX:
18474     case VIR_DOMAIN_OSTYPE_LAST:
18475         break;
18476     }
18477 
18478     return 0;
18479 }
18480 
18481 
18482 static int
virDomainResctrlParseVcpus(virDomainDef * def,xmlNodePtr node,virBitmap ** vcpus)18483 virDomainResctrlParseVcpus(virDomainDef *def,
18484                            xmlNodePtr node,
18485                            virBitmap **vcpus)
18486 {
18487     g_autofree char *vcpus_str = NULL;
18488 
18489     vcpus_str = virXMLPropString(node, "vcpus");
18490     if (!vcpus_str) {
18491         virReportError(VIR_ERR_XML_ERROR, _("Missing %s attribute 'vcpus'"),
18492                        node->name);
18493         return -1;
18494     }
18495     if (virBitmapParse(vcpus_str, vcpus, VIR_DOMAIN_CPUMASK_LEN) < 0) {
18496         virReportError(VIR_ERR_XML_ERROR,
18497                        _("Invalid %s attribute 'vcpus' value '%s'"),
18498                        node->name, vcpus_str);
18499         return -1;
18500     }
18501 
18502     /* We need to limit the bitmap to number of vCPUs.  If there's nothing left,
18503      * then we can just clean up and return 0 immediately */
18504     virBitmapShrink(*vcpus, def->maxvcpus);
18505 
18506     return 0;
18507 }
18508 
18509 
18510 static int
virDomainResctrlVcpuMatch(virDomainDef * def,virBitmap * vcpus,virDomainResctrlDef ** resctrl)18511 virDomainResctrlVcpuMatch(virDomainDef *def,
18512                           virBitmap *vcpus,
18513                           virDomainResctrlDef **resctrl)
18514 {
18515     ssize_t i = 0;
18516 
18517     for (i = 0; i < def->nresctrls; i++) {
18518         /* vcpus group has been created, directly use the existing one.
18519          * Just updating memory allocation information of that group
18520          */
18521         if (virBitmapEqual(def->resctrls[i]->vcpus, vcpus)) {
18522             *resctrl = def->resctrls[i];
18523             break;
18524         }
18525         if (virBitmapOverlaps(def->resctrls[i]->vcpus, vcpus)) {
18526             virReportError(VIR_ERR_XML_ERROR, "%s",
18527                            _("Overlapping vcpus in resctrls"));
18528             return -1;
18529         }
18530     }
18531     return 0;
18532 }
18533 
18534 
18535 static int
virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt,xmlNodePtr node,virResctrlAlloc * alloc)18536 virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt,
18537                                 xmlNodePtr node,
18538                                 virResctrlAlloc *alloc)
18539 {
18540     VIR_XPATH_NODE_AUTORESTORE(ctxt)
18541     unsigned int level;
18542     unsigned int cache;
18543     virCacheType type;
18544     unsigned long long size;
18545 
18546     ctxt->node = node;
18547 
18548     if (virXMLPropUInt(node, "id", 10, VIR_XML_PROP_REQUIRED, &cache) < 0)
18549         return -1;
18550 
18551     if (virXMLPropUInt(node, "level", 10, VIR_XML_PROP_REQUIRED, &level) < 0)
18552         return -1;
18553 
18554     if (virXMLPropEnum(node, "type", virCacheTypeFromString,
18555                        VIR_XML_PROP_REQUIRED, &type) < 0)
18556         return -1;
18557 
18558     if (virParseScaledValue("./@size", "./@unit",
18559                             ctxt, &size, 1024,
18560                             ULLONG_MAX, true) < 0)
18561         return -1;
18562 
18563     if (virResctrlAllocSetCacheSize(alloc, level, type, cache, size) < 0)
18564         return -1;
18565 
18566     return 0;
18567 }
18568 
18569 
18570 /* Checking if the monitor's vcpus and tag is conflicted with existing
18571  * allocation and monitors.
18572  *
18573  * Returns 1 if @monitor->vcpus equals to @resctrl->vcpus, then the monitor
18574  * will share the underlying resctrl group with @resctrl->alloc. Returns -1
18575  * if any conflict found. Returns 0 if no conflict and @monitor->vcpus is
18576  * not equal  to @resctrl->vcpus.
18577  */
18578 static int
virDomainResctrlValidateMonitor(virDomainResctrlDef * resctrl,virDomainResctrlMonDef * monitor)18579 virDomainResctrlValidateMonitor(virDomainResctrlDef *resctrl,
18580                                 virDomainResctrlMonDef *monitor)
18581 {
18582     size_t i = 0;
18583     int vcpu = -1;
18584     bool vcpus_overlap_any = false;
18585     bool vcpus_equal_to_resctrl = false;
18586     bool vcpus_overlap_no_resctrl = false;
18587     bool default_alloc_monitor = virResctrlAllocIsEmpty(resctrl->alloc);
18588 
18589     if (virBitmapIsAllClear(monitor->vcpus)) {
18590         virReportError(VIR_ERR_INVALID_ARG, "%s",
18591                        _("vcpus is empty"));
18592         return -1;
18593     }
18594 
18595     while ((vcpu = virBitmapNextSetBit(monitor->vcpus, vcpu)) >= 0) {
18596         if (!virBitmapIsBitSet(resctrl->vcpus, vcpu)) {
18597             virReportError(VIR_ERR_INVALID_ARG, "%s",
18598                            _("Monitor vcpus conflicts with allocation"));
18599             return -1;
18600         }
18601     }
18602 
18603     vcpus_equal_to_resctrl = virBitmapEqual(monitor->vcpus, resctrl->vcpus);
18604 
18605     for (i = 0; i < resctrl->nmonitors; i++) {
18606         if (virBitmapEqual(monitor->vcpus, resctrl->monitors[i]->vcpus)) {
18607             if (monitor->tag != resctrl->monitors[i]->tag) {
18608                 continue;
18609             } else {
18610                 virReportError(VIR_ERR_INVALID_ARG, "%s",
18611                                _("Identical vcpus found in same type monitors"));
18612                 return -1;
18613             }
18614         }
18615 
18616         if (virBitmapOverlaps(monitor->vcpus, resctrl->monitors[i]->vcpus))
18617             vcpus_overlap_any = true;
18618 
18619         if (vcpus_equal_to_resctrl ||
18620             virBitmapEqual(resctrl->monitors[i]->vcpus, resctrl->vcpus))
18621             continue;
18622 
18623         if (virBitmapOverlaps(monitor->vcpus, resctrl->monitors[i]->vcpus))
18624             vcpus_overlap_no_resctrl = true;
18625     }
18626 
18627     if (vcpus_overlap_no_resctrl ||
18628         (default_alloc_monitor && vcpus_overlap_any)) {
18629         virReportError(VIR_ERR_INVALID_ARG, "%s",
18630                        _("vcpus overlaps in resctrl groups"));
18631         return -1;
18632     }
18633 
18634     if (vcpus_equal_to_resctrl && !default_alloc_monitor)
18635         return 1;
18636 
18637     return 0;
18638 }
18639 
18640 
18641 #define VIR_DOMAIN_RESCTRL_MONITOR_CACHELEVEL 3
18642 
18643 static int
virDomainResctrlMonDefParse(virDomainDef * def,xmlXPathContextPtr ctxt,xmlNodePtr node,virResctrlMonitorType tag,virDomainResctrlDef * resctrl)18644 virDomainResctrlMonDefParse(virDomainDef *def,
18645                             xmlXPathContextPtr ctxt,
18646                             xmlNodePtr node,
18647                             virResctrlMonitorType tag,
18648                             virDomainResctrlDef *resctrl)
18649 {
18650     virDomainResctrlMonDef *domresmon = NULL;
18651     VIR_XPATH_NODE_AUTORESTORE(ctxt)
18652     unsigned int level = 0;
18653     size_t i = 0;
18654     int n = 0;
18655     int rv = -1;
18656     int ret = -1;
18657     g_autofree xmlNodePtr *nodes = NULL;
18658     g_autofree char *tmp = NULL;
18659     g_autofree char *id = NULL;
18660 
18661     ctxt->node = node;
18662 
18663     if ((n = virXPathNodeSet("./monitor", ctxt, &nodes)) < 0) {
18664         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
18665                        _("Cannot extract monitor nodes"));
18666         goto cleanup;
18667     }
18668 
18669     for (i = 0; i < n; i++) {
18670         domresmon = g_new0(virDomainResctrlMonDef, 1);
18671 
18672         domresmon->tag = tag;
18673 
18674         domresmon->instance = virResctrlMonitorNew();
18675         if (!domresmon->instance) {
18676             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
18677                            _("Could not create monitor"));
18678             goto cleanup;
18679         }
18680 
18681         if (tag == VIR_RESCTRL_MONITOR_TYPE_CACHE) {
18682             if (virXMLPropUInt(nodes[i], "level", 10, VIR_XML_PROP_REQUIRED,
18683                                &level) < 0)
18684                 goto cleanup;
18685 
18686             if (level != VIR_DOMAIN_RESCTRL_MONITOR_CACHELEVEL) {
18687                 virReportError(VIR_ERR_XML_ERROR,
18688                                _("Invalid monitor cache level '%d'"),
18689                                level);
18690                 goto cleanup;
18691             }
18692         }
18693 
18694         if (virDomainResctrlParseVcpus(def, nodes[i], &domresmon->vcpus) < 0)
18695             goto cleanup;
18696 
18697         rv = virDomainResctrlValidateMonitor(resctrl, domresmon);
18698         if (rv < 0)
18699             goto cleanup;
18700 
18701         /* If monitor's vcpu list is identical to the vcpu list of the
18702          * associated allocation, set monitor's id to the same value
18703          * as the allocation. */
18704         if (rv == 1) {
18705             const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
18706 
18707             id = g_strdup(alloc_id);
18708         } else {
18709             if (!(tmp = virBitmapFormat(domresmon->vcpus)))
18710                 goto cleanup;
18711 
18712             id = g_strdup_printf("vcpus_%s", tmp);
18713         }
18714 
18715         virResctrlMonitorSetAlloc(domresmon->instance, resctrl->alloc);
18716 
18717         if (virResctrlMonitorSetID(domresmon->instance, id) < 0)
18718             goto cleanup;
18719 
18720         VIR_APPEND_ELEMENT(resctrl->monitors, resctrl->nmonitors, domresmon);
18721 
18722         VIR_FREE(id);
18723         VIR_FREE(tmp);
18724     }
18725 
18726     ret = 0;
18727  cleanup:
18728     virDomainResctrlMonDefFree(domresmon);
18729     return ret;
18730 }
18731 
18732 
18733 static virDomainResctrlDef *
virDomainResctrlNew(xmlNodePtr node,virResctrlAlloc * alloc,virBitmap * vcpus,unsigned int flags)18734 virDomainResctrlNew(xmlNodePtr node,
18735                     virResctrlAlloc *alloc,
18736                     virBitmap *vcpus,
18737                     unsigned int flags)
18738 {
18739     virDomainResctrlDef *resctrl = NULL;
18740     g_autofree char *vcpus_str = NULL;
18741     g_autofree char *alloc_id = NULL;
18742 
18743     /* We need to format it back because we need to be consistent in the naming
18744      * even when users specify some "sub-optimal" string there. */
18745     vcpus_str = virBitmapFormat(vcpus);
18746     if (!vcpus_str)
18747         return NULL;
18748 
18749     if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
18750         alloc_id = virXMLPropString(node, "id");
18751 
18752     if (!alloc_id) {
18753         /* The number of allocations is limited and the directory structure is flat,
18754          * not hierarchical, so we need to have all same allocations in one
18755          * directory, so it's nice to have it named appropriately.  For now it's
18756          * 'vcpus_...' but it's designed in order for it to be changeable in the
18757          * future (it's part of the status XML). */
18758         alloc_id = g_strdup_printf("vcpus_%s", vcpus_str);
18759     }
18760 
18761     if (virResctrlAllocSetID(alloc, alloc_id) < 0)
18762         return NULL;
18763 
18764     resctrl = g_new0(virDomainResctrlDef, 1);
18765     resctrl->vcpus = virBitmapNewCopy(vcpus);
18766     resctrl->alloc = virObjectRef(alloc);
18767 
18768     return resctrl;
18769 }
18770 
18771 
18772 static int
virDomainCachetuneDefParse(virDomainDef * def,xmlXPathContextPtr ctxt,xmlNodePtr node,unsigned int flags)18773 virDomainCachetuneDefParse(virDomainDef *def,
18774                            xmlXPathContextPtr ctxt,
18775                            xmlNodePtr node,
18776                            unsigned int flags)
18777 {
18778     VIR_XPATH_NODE_AUTORESTORE(ctxt)
18779     virDomainResctrlDef *resctrl = NULL;
18780     ssize_t i = 0;
18781     int n;
18782     int ret = -1;
18783     g_autoptr(virBitmap) vcpus = NULL;
18784     g_autofree xmlNodePtr *nodes = NULL;
18785     g_autoptr(virResctrlAlloc) alloc = NULL;
18786 
18787     ctxt->node = node;
18788 
18789     if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0)
18790         return -1;
18791 
18792     if (virBitmapIsAllClear(vcpus))
18793         return 0;
18794 
18795     if ((n = virXPathNodeSet("./cache", ctxt, &nodes)) < 0) {
18796         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
18797                        _("Cannot extract cache nodes under cachetune"));
18798         return -1;
18799     }
18800 
18801     if (virDomainResctrlVcpuMatch(def, vcpus, &resctrl) < 0)
18802         return -1;
18803 
18804     if (resctrl) {
18805         virReportError(VIR_ERR_XML_ERROR, "%s",
18806                        _("Identical vcpus in cachetunes found"));
18807         return -1;
18808     }
18809 
18810     if (!(alloc = virResctrlAllocNew()))
18811         return -1;
18812 
18813     for (i = 0; i < n; i++) {
18814         if (virDomainCachetuneDefParseCache(ctxt, nodes[i], alloc) < 0)
18815             return -1;
18816     }
18817 
18818     if (!(resctrl = virDomainResctrlNew(node, alloc, vcpus, flags)))
18819         return -1;
18820 
18821     if (virDomainResctrlMonDefParse(def, ctxt, node,
18822                                     VIR_RESCTRL_MONITOR_TYPE_CACHE,
18823                                     resctrl) < 0)
18824         goto cleanup;
18825 
18826     /* If no <cache> element or <monitor> element in <cachetune>, do not
18827      * append any resctrl element */
18828     if (!resctrl->nmonitors && n == 0) {
18829         ret = 0;
18830         goto cleanup;
18831     }
18832 
18833     VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, resctrl);
18834 
18835     ret = 0;
18836  cleanup:
18837     virDomainResctrlDefFree(resctrl);
18838     return ret;
18839 }
18840 
18841 
18842 static int
virDomainDefParseIDs(virDomainDef * def,xmlXPathContextPtr ctxt,unsigned int flags,bool * uuid_generated)18843 virDomainDefParseIDs(virDomainDef *def,
18844                      xmlXPathContextPtr ctxt,
18845                      unsigned int flags,
18846                      bool *uuid_generated)
18847 {
18848     g_autofree xmlNodePtr *nodes = NULL;
18849     g_autofree char *tmp = NULL;
18850     long id = -1;
18851     int n;
18852 
18853     if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE))
18854         if (virXPathLong("string(./@id)", ctxt, &id) < 0)
18855             id = -1;
18856     def->id = (int)id;
18857 
18858     /* Extract domain name */
18859     if (!(def->name = virXPathString("string(./name[1])", ctxt))) {
18860         virReportError(VIR_ERR_NO_NAME, NULL);
18861         return -1;
18862     }
18863 
18864     /* Extract domain uuid. If both uuid and sysinfo/system/entry/uuid
18865      * exist, they must match; and if only the latter exists, it can
18866      * also serve as the uuid. */
18867     tmp = virXPathString("string(./uuid[1])", ctxt);
18868     if (!tmp) {
18869         if (virUUIDGenerate(def->uuid) < 0) {
18870             virReportError(VIR_ERR_INTERNAL_ERROR,
18871                            "%s", _("Failed to generate UUID"));
18872             return -1;
18873         }
18874         *uuid_generated = true;
18875     } else {
18876         if (virUUIDParse(tmp, def->uuid) < 0) {
18877             virReportError(VIR_ERR_INTERNAL_ERROR,
18878                            "%s", _("malformed uuid element"));
18879             return -1;
18880         }
18881         VIR_FREE(tmp);
18882     }
18883 
18884     /* Extract domain genid - a genid can either be provided or generated */
18885     if ((n = virXPathNodeSet("./genid", ctxt, &nodes)) < 0)
18886         return -1;
18887 
18888     if (n > 0) {
18889         if (n != 1) {
18890             virReportError(VIR_ERR_XML_ERROR, "%s",
18891                            _("element 'genid' can only appear once"));
18892             return -1;
18893         }
18894         def->genidRequested = true;
18895         if (!(tmp = virXPathString("string(./genid)", ctxt))) {
18896             if (virUUIDGenerate(def->genid) < 0) {
18897                 virReportError(VIR_ERR_INTERNAL_ERROR,
18898                                "%s", _("Failed to generate genid"));
18899                 return -1;
18900             }
18901             def->genidGenerated = true;
18902         } else {
18903             if (virUUIDParse(tmp, def->genid) < 0) {
18904                 virReportError(VIR_ERR_INTERNAL_ERROR,
18905                                "%s", _("malformed genid element"));
18906                 return -1;
18907             }
18908             VIR_FREE(tmp);
18909         }
18910     }
18911     VIR_FREE(nodes);
18912     return 0;
18913 }
18914 
18915 
18916 static int
virDomainDefParseCaps(virDomainDef * def,xmlXPathContextPtr ctxt,virDomainXMLOption * xmlopt)18917 virDomainDefParseCaps(virDomainDef *def,
18918                       xmlXPathContextPtr ctxt,
18919                       virDomainXMLOption *xmlopt)
18920 {
18921     g_autofree char *virttype = NULL;
18922     g_autofree char *arch = NULL;
18923     g_autofree char *ostype = NULL;
18924 
18925     virttype = virXPathString("string(./@type)", ctxt);
18926     ostype = virXPathString("string(./os/type[1])", ctxt);
18927     arch = virXPathString("string(./os/type[1]/@arch)", ctxt);
18928 
18929     def->os.bootloader = virXPathString("string(./bootloader)", ctxt);
18930     def->os.bootloaderArgs = virXPathString("string(./bootloader_args)", ctxt);
18931     def->os.machine = virXPathString("string(./os/type[1]/@machine)", ctxt);
18932     def->emulator = virXPathString("string(./devices/emulator[1])", ctxt);
18933 
18934     if (!virttype) {
18935         virReportError(VIR_ERR_INTERNAL_ERROR,
18936                        "%s", _("missing domain type attribute"));
18937         return -1;
18938     }
18939     if ((def->virtType = virDomainVirtTypeFromString(virttype)) < 0) {
18940         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18941                        _("invalid domain type %s"), virttype);
18942         return -1;
18943     }
18944 
18945     if (!ostype) {
18946         if (def->os.bootloader) {
18947             def->os.type = VIR_DOMAIN_OSTYPE_XEN;
18948         } else {
18949             virReportError(VIR_ERR_XML_ERROR, "%s",
18950                            _("an os <type> must be specified"));
18951             return -1;
18952         }
18953     } else {
18954         if ((def->os.type = virDomainOSTypeFromString(ostype)) < 0) {
18955             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18956                            _("unknown OS type '%s'"), ostype);
18957             return -1;
18958         }
18959     }
18960 
18961     /*
18962      * HACK: For xen driver we previously used bogus 'linux' as the
18963      * os type for paravirt, whereas capabilities declare it to
18964      * be 'xen'. So we accept the former and convert
18965      */
18966     if (def->os.type == VIR_DOMAIN_OSTYPE_LINUX &&
18967         def->virtType == VIR_DOMAIN_VIRT_XEN) {
18968         def->os.type = VIR_DOMAIN_OSTYPE_XEN;
18969     }
18970 
18971     if (arch && !(def->os.arch = virArchFromString(arch))) {
18972         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
18973                        _("Unknown architecture %s"), arch);
18974         return -1;
18975     }
18976 
18977     if (def->os.arch == VIR_ARCH_NONE) {
18978         if (xmlopt && xmlopt->config.defArch != VIR_ARCH_NONE)
18979             def->os.arch = xmlopt->config.defArch;
18980         else
18981             def->os.arch = virArchFromHost();
18982     }
18983 
18984     return 0;
18985 }
18986 
18987 
18988 static int
virDomainDefParseMemory(virDomainDef * def,xmlXPathContextPtr ctxt)18989 virDomainDefParseMemory(virDomainDef *def,
18990                         xmlXPathContextPtr ctxt)
18991 {
18992     g_autofree xmlNodePtr *nodes = NULL;
18993     g_autofree char *tmp = NULL;
18994     xmlNodePtr node = NULL;
18995     size_t i;
18996     int n;
18997 
18998     /* Extract domain memory */
18999     if (virDomainParseMemory("./memory[1]", NULL, ctxt,
19000                              &def->mem.total_memory, false, true) < 0)
19001         return -1;
19002 
19003     if (virDomainParseMemory("./currentMemory[1]", NULL, ctxt,
19004                              &def->mem.cur_balloon, false, true) < 0)
19005         return -1;
19006 
19007     if (virDomainParseMemory("./maxMemory[1]", NULL, ctxt,
19008                              &def->mem.max_memory, false, false) < 0)
19009         return -1;
19010 
19011     if (virXPathUInt("string(./maxMemory[1]/@slots)", ctxt, &def->mem.memory_slots) == -2) {
19012         virReportError(VIR_ERR_XML_ERROR, "%s",
19013                        _("Failed to parse memory slot count"));
19014         return -1;
19015     }
19016 
19017     /* and info about it */
19018     if ((tmp = virXPathString("string(./memory[1]/@dumpCore)", ctxt)) &&
19019         (def->mem.dump_core = virTristateSwitchTypeFromString(tmp)) <= 0) {
19020         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19021                        _("Invalid memory core dump attribute value '%s'"), tmp);
19022         return -1;
19023     }
19024     VIR_FREE(tmp);
19025 
19026     tmp = virXPathString("string(./memoryBacking/source/@type)", ctxt);
19027     if (tmp) {
19028         if ((def->mem.source = virDomainMemorySourceTypeFromString(tmp)) <= 0) {
19029             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19030                            _("unknown memoryBacking/source/type '%s'"), tmp);
19031             return -1;
19032         }
19033         VIR_FREE(tmp);
19034     }
19035 
19036     tmp = virXPathString("string(./memoryBacking/access/@mode)", ctxt);
19037     if (tmp) {
19038         if ((def->mem.access = virDomainMemoryAccessTypeFromString(tmp)) <= 0) {
19039             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19040                            _("unknown memoryBacking/access/mode '%s'"), tmp);
19041             return -1;
19042         }
19043         VIR_FREE(tmp);
19044     }
19045 
19046     tmp = virXPathString("string(./memoryBacking/allocation/@mode)", ctxt);
19047     if (tmp) {
19048         if ((def->mem.allocation = virDomainMemoryAllocationTypeFromString(tmp)) <= 0) {
19049             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19050                            _("unknown memoryBacking/allocation/mode '%s'"), tmp);
19051             return -1;
19052         }
19053         VIR_FREE(tmp);
19054     }
19055 
19056     if (virXPathNode("./memoryBacking/hugepages", ctxt)) {
19057         /* hugepages will be used */
19058         if ((n = virXPathNodeSet("./memoryBacking/hugepages/page", ctxt, &nodes)) < 0) {
19059             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19060                            _("cannot extract hugepages nodes"));
19061             return -1;
19062         }
19063 
19064         if (n) {
19065             def->mem.hugepages = g_new0(virDomainHugePage, n);
19066 
19067             for (i = 0; i < n; i++) {
19068                 if (virDomainHugepagesParseXML(nodes[i], ctxt,
19069                                                &def->mem.hugepages[i]) < 0)
19070                     return -1;
19071                 def->mem.nhugepages++;
19072             }
19073 
19074             VIR_FREE(nodes);
19075         } else {
19076             /* no hugepage pages */
19077             def->mem.hugepages = g_new0(virDomainHugePage, 1);
19078             def->mem.nhugepages = 1;
19079         }
19080     }
19081 
19082     if ((node = virXPathNode("./memoryBacking/nosharepages", ctxt)))
19083         def->mem.nosharepages = true;
19084 
19085     if (virXPathBoolean("boolean(./memoryBacking/locked)", ctxt))
19086         def->mem.locked = true;
19087 
19088     if (virXPathBoolean("boolean(./memoryBacking/discard)", ctxt))
19089         def->mem.discard = VIR_TRISTATE_BOOL_YES;
19090 
19091     return 0;
19092 }
19093 
19094 
19095 static int
virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt,xmlNodePtr node,virResctrlAlloc * alloc)19096 virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt,
19097                                   xmlNodePtr node,
19098                                   virResctrlAlloc *alloc)
19099 {
19100     VIR_XPATH_NODE_AUTORESTORE(ctxt)
19101     unsigned int id;
19102     unsigned int bandwidth;
19103 
19104     ctxt->node = node;
19105 
19106     if (virXMLPropUInt(node, "id", 10, VIR_XML_PROP_REQUIRED, &id) < 0)
19107         return -1;
19108 
19109     if (virXMLPropUInt(node, "bandwidth", 10, VIR_XML_PROP_REQUIRED,
19110                        &bandwidth) < 0)
19111         return -1;
19112 
19113     if (virResctrlAllocSetMemoryBandwidth(alloc, id, bandwidth) < 0)
19114         return -1;
19115 
19116     return 0;
19117 }
19118 
19119 
19120 static int
virDomainMemorytuneDefParse(virDomainDef * def,xmlXPathContextPtr ctxt,xmlNodePtr node,unsigned int flags)19121 virDomainMemorytuneDefParse(virDomainDef *def,
19122                             xmlXPathContextPtr ctxt,
19123                             xmlNodePtr node,
19124                             unsigned int flags)
19125 {
19126     VIR_XPATH_NODE_AUTORESTORE(ctxt)
19127     virDomainResctrlDef *resctrl = NULL;
19128     virDomainResctrlDef *newresctrl = NULL;
19129     g_autoptr(virBitmap) vcpus = NULL;
19130     g_autofree xmlNodePtr *nodes = NULL;
19131     g_autoptr(virResctrlAlloc) alloc = NULL;
19132     ssize_t i = 0;
19133     size_t nmons = 0;
19134     size_t ret = -1;
19135 
19136     int n;
19137 
19138     ctxt->node = node;
19139 
19140     if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0)
19141         return -1;
19142 
19143     if (virBitmapIsAllClear(vcpus))
19144         return 0;
19145 
19146     if ((n = virXPathNodeSet("./node", ctxt, &nodes)) < 0) {
19147         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19148                        _("Cannot extract memory nodes under memorytune"));
19149         return -1;
19150     }
19151 
19152     if (virDomainResctrlVcpuMatch(def, vcpus, &resctrl) < 0)
19153         return -1;
19154 
19155     if (resctrl) {
19156         alloc = virObjectRef(resctrl->alloc);
19157     } else {
19158         if (!(alloc = virResctrlAllocNew()))
19159             return -1;
19160     }
19161 
19162     /* First, parse <memorytune/node> element if any <node> element exists */
19163     for (i = 0; i < n; i++) {
19164         if (virDomainMemorytuneDefParseMemory(ctxt, nodes[i], alloc) < 0)
19165             return -1;
19166     }
19167 
19168     /*
19169      * If this is a new allocation, format ID and append to resctrl, otherwise
19170      * just update the existing alloc information, which is done in above
19171      * virDomainMemorytuneDefParseMemory */
19172     if (!resctrl) {
19173         if (!(newresctrl = virDomainResctrlNew(node, alloc, vcpus, flags)))
19174             return -1;
19175 
19176         resctrl = newresctrl;
19177     }
19178 
19179     /* Next, parse <memorytune/monitor> element */
19180     nmons = resctrl->nmonitors;
19181     if (virDomainResctrlMonDefParse(def, ctxt, node,
19182                                     VIR_RESCTRL_MONITOR_TYPE_MEMBW,
19183                                     resctrl) < 0)
19184         goto cleanup;
19185 
19186     nmons = resctrl->nmonitors - nmons;
19187     /* Now @nmons contains the new <monitor> element number found in current
19188      * <memorytune> element, and @n holds the number of new <node> element,
19189      * only append the new @newresctrl object to domain if any of them is
19190      * not zero. */
19191     if (newresctrl && (nmons || n)) {
19192         VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, newresctrl);
19193     }
19194 
19195     ret = 0;
19196  cleanup:
19197     virDomainResctrlDefFree(newresctrl);
19198     return ret;
19199 }
19200 
19201 
19202 static int
virDomainDefTunablesParse(virDomainDef * def,xmlXPathContextPtr ctxt,virDomainXMLOption * xmlopt,unsigned int flags)19203 virDomainDefTunablesParse(virDomainDef *def,
19204                           xmlXPathContextPtr ctxt,
19205                           virDomainXMLOption *xmlopt,
19206                           unsigned int flags)
19207 {
19208     g_autofree xmlNodePtr *nodes = NULL;
19209     size_t i;
19210     int n;
19211 
19212     /* Extract blkio cgroup tunables */
19213     if (virXPathUInt("string(./blkiotune/weight)", ctxt,
19214                      &def->blkio.weight) < 0)
19215         def->blkio.weight = 0;
19216 
19217     if ((n = virXPathNodeSet("./blkiotune/device", ctxt, &nodes)) < 0) {
19218         virReportError(VIR_ERR_INTERNAL_ERROR,
19219                        "%s", _("cannot extract blkiotune nodes"));
19220         return -1;
19221     }
19222     if (n)
19223         def->blkio.devices = g_new0(virBlkioDevice, n);
19224 
19225     for (i = 0; i < n; i++) {
19226         if (virDomainBlkioDeviceParseXML(nodes[i], ctxt,
19227                                          &def->blkio.devices[i]) < 0)
19228             return -1;
19229         def->blkio.ndevices++;
19230     }
19231     VIR_FREE(nodes);
19232 
19233     /* Extract other memory tunables */
19234     if (virDomainParseMemoryLimit("./memtune/hard_limit[1]", NULL, ctxt,
19235                                   &def->mem.hard_limit) < 0)
19236         return -1;
19237 
19238     if (virDomainParseMemoryLimit("./memtune/soft_limit[1]", NULL, ctxt,
19239                                   &def->mem.soft_limit) < 0)
19240         return -1;
19241 
19242     if (virDomainParseMemory("./memtune/min_guarantee[1]", NULL, ctxt,
19243                              &def->mem.min_guarantee, false, false) < 0)
19244         return -1;
19245 
19246     if (virDomainParseMemoryLimit("./memtune/swap_hard_limit[1]", NULL, ctxt,
19247                                   &def->mem.swap_hard_limit) < 0)
19248         return -1;
19249 
19250     if (virDomainVcpuParse(def, ctxt, xmlopt) < 0)
19251         return -1;
19252 
19253     if (virDomainDefParseIOThreads(def, ctxt) < 0)
19254         return -1;
19255 
19256     /* Extract cpu tunables. */
19257     if ((n = virXPathULongLong("string(./cputune/shares[1])", ctxt,
19258                                &def->cputune.shares)) < -1) {
19259         virReportError(VIR_ERR_XML_ERROR, "%s",
19260                        _("can't parse cputune shares value"));
19261         return -1;
19262     } else if (n == 0) {
19263         def->cputune.sharesSpecified = true;
19264     }
19265 
19266     if (virXPathULongLong("string(./cputune/period[1])", ctxt,
19267                           &def->cputune.period) < -1) {
19268         virReportError(VIR_ERR_XML_ERROR, "%s",
19269                        _("can't parse cputune period value"));
19270         return -1;
19271     }
19272 
19273     if (virXPathLongLong("string(./cputune/quota[1])", ctxt,
19274                          &def->cputune.quota) < -1) {
19275         virReportError(VIR_ERR_XML_ERROR, "%s",
19276                        _("can't parse cputune quota value"));
19277         return -1;
19278     }
19279 
19280     if (virXPathULongLong("string(./cputune/global_period[1])", ctxt,
19281                           &def->cputune.global_period) < -1) {
19282         virReportError(VIR_ERR_XML_ERROR, "%s",
19283                        _("can't parse cputune global period value"));
19284         return -1;
19285     }
19286 
19287     if (virXPathLongLong("string(./cputune/global_quota[1])", ctxt,
19288                          &def->cputune.global_quota) < -1) {
19289         virReportError(VIR_ERR_XML_ERROR, "%s",
19290                        _("can't parse cputune global quota value"));
19291         return -1;
19292     }
19293 
19294     if (virXPathULongLong("string(./cputune/emulator_period[1])", ctxt,
19295                           &def->cputune.emulator_period) < -1) {
19296         virReportError(VIR_ERR_XML_ERROR, "%s",
19297                        _("can't parse cputune emulator period value"));
19298         return -1;
19299     }
19300 
19301     if (virXPathLongLong("string(./cputune/emulator_quota[1])", ctxt,
19302                          &def->cputune.emulator_quota) < -1) {
19303         virReportError(VIR_ERR_XML_ERROR, "%s",
19304                        _("can't parse cputune emulator quota value"));
19305         return -1;
19306     }
19307 
19308 
19309     if (virXPathULongLong("string(./cputune/iothread_period[1])", ctxt,
19310                           &def->cputune.iothread_period) < -1) {
19311         virReportError(VIR_ERR_XML_ERROR, "%s",
19312                        _("can't parse cputune iothread period value"));
19313         return -1;
19314     }
19315 
19316     if (virXPathLongLong("string(./cputune/iothread_quota[1])", ctxt,
19317                          &def->cputune.iothread_quota) < -1) {
19318         virReportError(VIR_ERR_XML_ERROR, "%s",
19319                        _("can't parse cputune iothread quota value"));
19320         return -1;
19321     }
19322 
19323     if ((n = virXPathNodeSet("./cputune/vcpupin", ctxt, &nodes)) < 0)
19324         return -1;
19325 
19326     for (i = 0; i < n; i++) {
19327         if (virDomainVcpuPinDefParseXML(def, nodes[i]))
19328             return -1;
19329     }
19330     VIR_FREE(nodes);
19331 
19332     if ((n = virXPathNodeSet("./cputune/emulatorpin", ctxt, &nodes)) < 0) {
19333         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19334                        _("cannot extract emulatorpin nodes"));
19335         return -1;
19336     }
19337 
19338     if (n) {
19339         if (n > 1) {
19340             virReportError(VIR_ERR_XML_ERROR, "%s",
19341                            _("only one emulatorpin is supported"));
19342             return -1;
19343         }
19344 
19345         if (!(def->cputune.emulatorpin = virDomainEmulatorPinDefParseXML(nodes[0])))
19346             return -1;
19347     }
19348     VIR_FREE(nodes);
19349 
19350 
19351     if ((n = virXPathNodeSet("./cputune/iothreadpin", ctxt, &nodes)) < 0) {
19352         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19353                        _("cannot extract iothreadpin nodes"));
19354         return -1;
19355     }
19356 
19357     for (i = 0; i < n; i++) {
19358         if (virDomainIOThreadPinDefParseXML(nodes[i], def) < 0)
19359             return -1;
19360     }
19361     VIR_FREE(nodes);
19362 
19363     if ((n = virXPathNodeSet("./cputune/vcpusched", ctxt, &nodes)) < 0) {
19364         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19365                        _("cannot extract vcpusched nodes"));
19366         return -1;
19367     }
19368 
19369     for (i = 0; i < n; i++) {
19370         if (virDomainVcpuThreadSchedParse(nodes[i], def) < 0)
19371             return -1;
19372     }
19373     VIR_FREE(nodes);
19374 
19375     if ((n = virXPathNodeSet("./cputune/iothreadsched", ctxt, &nodes)) < 0) {
19376         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19377                        _("cannot extract iothreadsched nodes"));
19378         return -1;
19379     }
19380 
19381     for (i = 0; i < n; i++) {
19382         if (virDomainIOThreadSchedParse(nodes[i], def) < 0)
19383             return -1;
19384     }
19385     VIR_FREE(nodes);
19386 
19387     if ((n = virXPathNodeSet("./cputune/emulatorsched", ctxt, &nodes)) < 0) {
19388         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19389                        _("cannot extract emulatorsched nodes"));
19390         return -1;
19391     }
19392 
19393     if (n) {
19394         if (n > 1) {
19395             virReportError(VIR_ERR_XML_ERROR, "%s",
19396                            _("only one emulatorsched is supported"));
19397             return -1;
19398         }
19399 
19400         if (virDomainEmulatorSchedParse(nodes[0], def) < 0)
19401             return -1;
19402     }
19403     VIR_FREE(nodes);
19404 
19405     if ((n = virXPathNodeSet("./cputune/cachetune", ctxt, &nodes)) < 0) {
19406         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19407                        _("cannot extract cachetune nodes"));
19408         return -1;
19409     }
19410 
19411     for (i = 0; i < n; i++) {
19412         if (virDomainCachetuneDefParse(def, ctxt, nodes[i], flags) < 0)
19413             return -1;
19414     }
19415     VIR_FREE(nodes);
19416 
19417     if ((n = virXPathNodeSet("./cputune/memorytune", ctxt, &nodes)) < 0) {
19418         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19419                        _("cannot extract memorytune nodes"));
19420         return -1;
19421     }
19422 
19423     for (i = 0; i < n; i++) {
19424         if (virDomainMemorytuneDefParse(def, ctxt, nodes[i], flags) < 0)
19425             return -1;
19426     }
19427     VIR_FREE(nodes);
19428 
19429     return 0;
19430 }
19431 
19432 
19433 static int
virDomainDefLifecycleParse(virDomainDef * def,xmlXPathContextPtr ctxt)19434 virDomainDefLifecycleParse(virDomainDef *def,
19435                            xmlXPathContextPtr ctxt)
19436 {
19437     if (virDomainEventActionParseXML(ctxt, "on_reboot",
19438                                      "string(./on_reboot[1])",
19439                                      &def->onReboot,
19440                                      VIR_DOMAIN_LIFECYCLE_ACTION_RESTART,
19441                                      virDomainLifecycleActionTypeFromString) < 0)
19442         return -1;
19443 
19444     if (virDomainEventActionParseXML(ctxt, "on_poweroff",
19445                                      "string(./on_poweroff[1])",
19446                                      &def->onPoweroff,
19447                                      VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY,
19448                                      virDomainLifecycleActionTypeFromString) < 0)
19449         return -1;
19450 
19451     if (virDomainEventActionParseXML(ctxt, "on_crash",
19452                                      "string(./on_crash[1])",
19453                                      &def->onCrash,
19454                                      VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY,
19455                                      virDomainLifecycleActionTypeFromString) < 0)
19456         return -1;
19457 
19458     if (virDomainEventActionParseXML(ctxt, "on_lockfailure",
19459                                      "string(./on_lockfailure[1])",
19460                                      &def->onLockFailure,
19461                                      VIR_DOMAIN_LOCK_FAILURE_DEFAULT,
19462                                      virDomainLockFailureTypeFromString) < 0)
19463         return -1;
19464 
19465     if (virDomainPMStateParseXML(ctxt,
19466                                  "string(./pm/suspend-to-mem/@enabled)",
19467                                  &def->pm.s3) < 0)
19468         return -1;
19469 
19470     if (virDomainPMStateParseXML(ctxt,
19471                                  "string(./pm/suspend-to-disk/@enabled)",
19472                                  &def->pm.s4) < 0)
19473         return -1;
19474 
19475     return 0;
19476 }
19477 
19478 
19479 static int
virDomainDefClockParse(virDomainDef * def,xmlXPathContextPtr ctxt)19480 virDomainDefClockParse(virDomainDef *def,
19481                        xmlXPathContextPtr ctxt)
19482 {
19483     size_t i;
19484     int n;
19485     g_autofree xmlNodePtr *nodes = NULL;
19486     g_autofree char *tmp = NULL;
19487 
19488     if ((tmp = virXPathString("string(./clock/@offset)", ctxt)) &&
19489         (def->clock.offset = virDomainClockOffsetTypeFromString(tmp)) < 0) {
19490         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19491                        _("unknown clock offset '%s'"), tmp);
19492         return -1;
19493     }
19494     VIR_FREE(tmp);
19495 
19496     switch (def->clock.offset) {
19497     case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
19498     case VIR_DOMAIN_CLOCK_OFFSET_UTC:
19499         tmp = virXPathString("string(./clock/@adjustment)", ctxt);
19500         if (tmp) {
19501             if (STREQ(tmp, "reset")) {
19502                 def->clock.data.utc_reset = true;
19503             } else {
19504                 if (virStrToLong_ll(tmp, NULL, 10,
19505                                     &def->clock.data.variable.adjustment) < 0) {
19506                     virReportError(VIR_ERR_XML_ERROR,
19507                                    _("unknown clock adjustment '%s'"),
19508                                    tmp);
19509                     return -1;
19510                 }
19511                 switch (def->clock.offset) {
19512                 case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
19513                     def->clock.data.variable.basis = VIR_DOMAIN_CLOCK_BASIS_LOCALTIME;
19514                     break;
19515                 case VIR_DOMAIN_CLOCK_OFFSET_UTC:
19516                     def->clock.data.variable.basis = VIR_DOMAIN_CLOCK_BASIS_UTC;
19517                     break;
19518                 }
19519                 def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_VARIABLE;
19520             }
19521             VIR_FREE(tmp);
19522         } else {
19523             def->clock.data.utc_reset = false;
19524         }
19525         break;
19526 
19527     case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
19528         if (virXPathLongLong("number(./clock/@adjustment)", ctxt,
19529                              &def->clock.data.variable.adjustment) < 0)
19530             def->clock.data.variable.adjustment = 0;
19531         if (virXPathLongLong("number(./clock/@adjustment0)", ctxt,
19532                              &def->clock.data.variable.adjustment0) < 0)
19533             def->clock.data.variable.adjustment0 = 0;
19534         tmp = virXPathString("string(./clock/@basis)", ctxt);
19535         if (tmp) {
19536             if ((def->clock.data.variable.basis = virDomainClockBasisTypeFromString(tmp)) < 0) {
19537                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
19538                                _("unknown clock basis '%s'"), tmp);
19539                 return -1;
19540             }
19541             VIR_FREE(tmp);
19542         } else {
19543             def->clock.data.variable.basis = VIR_DOMAIN_CLOCK_BASIS_UTC;
19544         }
19545         break;
19546 
19547     case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
19548         def->clock.data.timezone = virXPathString("string(./clock/@timezone)", ctxt);
19549         if (!def->clock.data.timezone) {
19550             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19551                            _("missing 'timezone' attribute for clock with offset='timezone'"));
19552             return -1;
19553         }
19554         break;
19555     }
19556 
19557     if ((n = virXPathNodeSet("./clock/timer", ctxt, &nodes)) < 0)
19558         return -1;
19559 
19560     if (n)
19561         def->clock.timers = g_new0(virDomainTimerDef *, n);
19562 
19563     for (i = 0; i < n; i++) {
19564         virDomainTimerDef *timer = virDomainTimerDefParseXML(nodes[i], ctxt);
19565 
19566         if (!timer)
19567             return -1;
19568 
19569         def->clock.timers[def->clock.ntimers++] = timer;
19570     }
19571     VIR_FREE(nodes);
19572 
19573     return 0;
19574 }
19575 
19576 static int
virDomainDefControllersParse(virDomainDef * def,xmlXPathContextPtr ctxt,virDomainXMLOption * xmlopt,unsigned int flags,bool * usb_none)19577 virDomainDefControllersParse(virDomainDef *def,
19578                              xmlXPathContextPtr ctxt,
19579                              virDomainXMLOption *xmlopt,
19580                              unsigned int flags,
19581                              bool *usb_none)
19582 {
19583     g_autofree xmlNodePtr *nodes = NULL;
19584     bool usb_other = false;
19585     bool usb_master = false;
19586     size_t i;
19587     int n;
19588 
19589     if ((n = virXPathNodeSet("./devices/controller", ctxt, &nodes)) < 0)
19590         return -1;
19591 
19592     if (n)
19593         def->controllers = g_new0(virDomainControllerDef *, n);
19594 
19595     for (i = 0; i < n; i++) {
19596         g_autoptr(virDomainControllerDef) controller = NULL;
19597 
19598         controller = virDomainControllerDefParseXML(xmlopt, nodes[i],
19599                                                     ctxt, flags);
19600 
19601         if (!controller)
19602             return -1;
19603 
19604         /* sanitize handling of "none" usb controller */
19605         if (controller->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
19606             if (controller->model == VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE) {
19607                 if (usb_other || *usb_none) {
19608                     virReportError(VIR_ERR_XML_DETAIL, "%s",
19609                                    _("Can't add another USB controller: "
19610                                      "USB is disabled for this domain"));
19611                     return -1;
19612                 }
19613                 *usb_none = true;
19614             } else {
19615                 if (*usb_none) {
19616                     virReportError(VIR_ERR_XML_DETAIL, "%s",
19617                                    _("Can't add another USB controller: "
19618                                      "USB is disabled for this domain"));
19619                     return -1;
19620                 }
19621                 usb_other = true;
19622             }
19623 
19624             if (controller->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_NONE)
19625                 usb_master = true;
19626         }
19627 
19628         virDomainControllerInsertPreAlloced(def, g_steal_pointer(&controller));
19629     }
19630 
19631     if (usb_other && !usb_master) {
19632         virReportError(VIR_ERR_XML_DETAIL, "%s",
19633                        _("No master USB controller specified"));
19634         return -1;
19635     }
19636 
19637     return 0;
19638 }
19639 
19640 static virDomainDef *
virDomainDefParseXML(xmlXPathContextPtr ctxt,virDomainXMLOption * xmlopt,unsigned int flags)19641 virDomainDefParseXML(xmlXPathContextPtr ctxt,
19642                      virDomainXMLOption *xmlopt,
19643                      unsigned int flags)
19644 {
19645     xmlNodePtr node = NULL;
19646     size_t i, j;
19647     int n;
19648     bool uuid_generated = false;
19649     bool usb_none = false;
19650     g_autofree xmlNodePtr *nodes = NULL;
19651     g_autofree char *tmp = NULL;
19652     g_autoptr(virDomainDef) def = NULL;
19653 
19654     if (!(def = virDomainDefNew(xmlopt)))
19655         return NULL;
19656 
19657     if (virDomainDefParseIDs(def, ctxt, flags, &uuid_generated) < 0)
19658         return NULL;
19659 
19660     if (virDomainDefParseCaps(def, ctxt, xmlopt) < 0)
19661         return NULL;
19662 
19663     /* Extract short description of domain (title) */
19664     def->title = virXPathString("string(./title[1])", ctxt);
19665     if (def->title && strchr(def->title, '\n')) {
19666         virReportError(VIR_ERR_XML_ERROR, "%s",
19667                        _("Domain title can't contain newlines"));
19668         return NULL;
19669     }
19670 
19671     /* Extract documentation if present */
19672     def->description = virXPathString("string(./description[1])", ctxt);
19673 
19674     /* analysis of security label, done early even though we format it
19675      * late, so devices can refer to this for defaults */
19676     if (!(flags & VIR_DOMAIN_DEF_PARSE_SKIP_SECLABEL)) {
19677         if (virSecurityLabelDefsParseXML(def, ctxt, xmlopt, flags) == -1)
19678             return NULL;
19679     }
19680 
19681     if (virDomainDefParseMemory(def, ctxt) < 0)
19682         return NULL;
19683 
19684     if (virDomainDefTunablesParse(def, ctxt, xmlopt, flags) < 0)
19685         return NULL;
19686 
19687     if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu,
19688                           false) < 0)
19689         return NULL;
19690 
19691     if (virDomainNumaDefParseXML(def->numa, ctxt) < 0)
19692         return NULL;
19693 
19694     if (virDomainNumaGetCPUCountTotal(def->numa) > virDomainDefGetVcpusMax(def)) {
19695         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19696                        _("Number of CPUs in <numa> exceeds the"
19697                          " <vcpu> count"));
19698         return NULL;
19699     }
19700 
19701     if (virDomainNumaGetMaxCPUID(def->numa) >= virDomainDefGetVcpusMax(def)) {
19702         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
19703                        _("CPU IDs in <numa> exceed the <vcpu> count"));
19704         return NULL;
19705     }
19706 
19707     if (virDomainNumatuneParseXML(def->numa,
19708                                   def->placement_mode ==
19709                                   VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC,
19710                                   ctxt) < 0)
19711         return NULL;
19712 
19713     if (virDomainNumatuneHasPlacementAuto(def->numa) &&
19714         !def->cpumask && !virDomainDefHasVcpuPin(def) &&
19715         !def->cputune.emulatorpin &&
19716         !virDomainIOThreadIDArrayHasPin(def))
19717         def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO;
19718 
19719     if ((n = virXPathNodeSet("./resource", ctxt, &nodes)) < 0) {
19720         virReportError(VIR_ERR_INTERNAL_ERROR,
19721                        "%s", _("cannot extract resource nodes"));
19722         return NULL;
19723     }
19724 
19725     if (n > 1) {
19726         virReportError(VIR_ERR_XML_ERROR, "%s",
19727                        _("only one resource element is supported"));
19728         return NULL;
19729     }
19730 
19731     if (n &&
19732         !(def->resource = virDomainResourceDefParse(nodes[0], ctxt)))
19733         return NULL;
19734     VIR_FREE(nodes);
19735 
19736     if (virDomainFeaturesDefParse(def, ctxt) < 0)
19737         return NULL;
19738 
19739     if (virDomainDefLifecycleParse(def, ctxt) < 0)
19740         return NULL;
19741 
19742     if (virDomainPerfDefParseXML(def, ctxt) < 0)
19743         return NULL;
19744 
19745     if (virDomainDefClockParse(def, ctxt) < 0)
19746         return NULL;
19747 
19748     if (virDomainDefParseBootOptions(def, ctxt) < 0)
19749         return NULL;
19750 
19751     /* analysis of the disk devices */
19752     if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0)
19753         return NULL;
19754 
19755     for (i = 0; i < n; i++) {
19756         virDomainDiskDef *disk = virDomainDiskDefParseXML(xmlopt,
19757                                                           nodes[i],
19758                                                           ctxt,
19759                                                           flags);
19760         if (!disk)
19761             return NULL;
19762 
19763         virDomainDiskInsert(def, disk);
19764     }
19765     VIR_FREE(nodes);
19766 
19767     if (virDomainDefControllersParse(def, ctxt, xmlopt, flags, &usb_none) < 0)
19768         return NULL;
19769 
19770     /* analysis of the resource leases */
19771     if ((n = virXPathNodeSet("./devices/lease", ctxt, &nodes)) < 0) {
19772         virReportError(VIR_ERR_INTERNAL_ERROR,
19773                        "%s", _("cannot extract device leases"));
19774         return NULL;
19775     }
19776     if (n)
19777         def->leases = g_new0(virDomainLeaseDef *, n);
19778     for (i = 0; i < n; i++) {
19779         virDomainLeaseDef *lease = virDomainLeaseDefParseXML(nodes[i], ctxt);
19780         if (!lease)
19781             return NULL;
19782 
19783         def->leases[def->nleases++] = lease;
19784     }
19785     VIR_FREE(nodes);
19786 
19787     /* analysis of the filesystems */
19788     if ((n = virXPathNodeSet("./devices/filesystem", ctxt, &nodes)) < 0)
19789         return NULL;
19790     if (n)
19791         def->fss = g_new0(virDomainFSDef *, n);
19792     for (i = 0; i < n; i++) {
19793         virDomainFSDef *fs = virDomainFSDefParseXML(xmlopt,
19794                                                     nodes[i],
19795                                                     ctxt,
19796                                                     flags);
19797         if (!fs)
19798             return NULL;
19799 
19800         def->fss[def->nfss++] = fs;
19801     }
19802     VIR_FREE(nodes);
19803 
19804     /* analysis of the network devices */
19805     if ((n = virXPathNodeSet("./devices/interface", ctxt, &nodes)) < 0)
19806         return NULL;
19807     if (n)
19808         def->nets = g_new0(virDomainNetDef *, n);
19809     for (i = 0; i < n; i++) {
19810         virDomainNetDef *net = virDomainNetDefParseXML(xmlopt,
19811                                                        nodes[i],
19812                                                        ctxt,
19813                                                        flags);
19814         if (!net)
19815             return NULL;
19816 
19817         def->nets[def->nnets++] = net;
19818 
19819         /* <interface type='hostdev'> (and <interface type='net'>
19820          * where the actual network type is already known to be
19821          * hostdev) must also be in the hostdevs array.
19822          */
19823         if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
19824             virDomainHostdevInsert(def, virDomainNetGetActualHostdev(net)) < 0) {
19825             return NULL;
19826         }
19827     }
19828     VIR_FREE(nodes);
19829 
19830 
19831     /* analysis of the smartcard devices */
19832     if ((n = virXPathNodeSet("./devices/smartcard", ctxt, &nodes)) < 0)
19833         return NULL;
19834     if (n)
19835         def->smartcards = g_new0(virDomainSmartcardDef *, n);
19836 
19837     for (i = 0; i < n; i++) {
19838         virDomainSmartcardDef *card = virDomainSmartcardDefParseXML(xmlopt,
19839                                                                     nodes[i],
19840                                                                     ctxt,
19841                                                                     flags);
19842         if (!card)
19843             return NULL;
19844 
19845         def->smartcards[def->nsmartcards++] = card;
19846     }
19847     VIR_FREE(nodes);
19848 
19849 
19850     /* analysis of the character devices */
19851     if ((n = virXPathNodeSet("./devices/parallel", ctxt, &nodes)) < 0)
19852         return NULL;
19853     if (n)
19854         def->parallels = g_new0(virDomainChrDef *, n);
19855 
19856     for (i = 0; i < n; i++) {
19857         virDomainChrDef *chr = virDomainChrDefParseXML(xmlopt,
19858                                                        ctxt,
19859                                                        nodes[i],
19860                                                        flags);
19861         if (!chr)
19862             return NULL;
19863 
19864         if (chr->target.port == -1) {
19865             int maxport = -1;
19866             for (j = 0; j < i; j++) {
19867                 if (def->parallels[j]->target.port > maxport)
19868                     maxport = def->parallels[j]->target.port;
19869             }
19870             chr->target.port = maxport + 1;
19871         }
19872         def->parallels[def->nparallels++] = chr;
19873     }
19874     VIR_FREE(nodes);
19875 
19876     if ((n = virXPathNodeSet("./devices/serial", ctxt, &nodes)) < 0)
19877         return NULL;
19878 
19879     if (n)
19880         def->serials = g_new0(virDomainChrDef *, n);
19881 
19882     for (i = 0; i < n; i++) {
19883         virDomainChrDef *chr = virDomainChrDefParseXML(xmlopt,
19884                                                        ctxt,
19885                                                        nodes[i],
19886                                                        flags);
19887         if (!chr)
19888             return NULL;
19889 
19890         if (chr->target.port == -1) {
19891             int maxport = -1;
19892             for (j = 0; j < i; j++) {
19893                 if (def->serials[j]->target.port > maxport)
19894                     maxport = def->serials[j]->target.port;
19895             }
19896             chr->target.port = maxport + 1;
19897         }
19898         def->serials[def->nserials++] = chr;
19899     }
19900     VIR_FREE(nodes);
19901 
19902     if ((n = virXPathNodeSet("./devices/console", ctxt, &nodes)) < 0) {
19903         virReportError(VIR_ERR_INTERNAL_ERROR,
19904                        "%s", _("cannot extract console devices"));
19905         return NULL;
19906     }
19907     if (n)
19908         def->consoles = g_new0(virDomainChrDef *, n);
19909 
19910     for (i = 0; i < n; i++) {
19911         virDomainChrDef *chr = virDomainChrDefParseXML(xmlopt,
19912                                                        ctxt,
19913                                                        nodes[i],
19914                                                        flags);
19915         if (!chr)
19916             return NULL;
19917 
19918         chr->target.port = i;
19919         def->consoles[def->nconsoles++] = chr;
19920     }
19921     VIR_FREE(nodes);
19922 
19923     if ((n = virXPathNodeSet("./devices/channel", ctxt, &nodes)) < 0)
19924         return NULL;
19925     if (n)
19926         def->channels = g_new0(virDomainChrDef *, n);
19927 
19928     for (i = 0; i < n; i++) {
19929         virDomainChrDef *chr = virDomainChrDefParseXML(xmlopt,
19930                                                        ctxt,
19931                                                        nodes[i],
19932                                                        flags);
19933         if (!chr)
19934             return NULL;
19935 
19936         def->channels[def->nchannels++] = chr;
19937     }
19938     VIR_FREE(nodes);
19939 
19940 
19941     /* analysis of the input devices */
19942     if ((n = virXPathNodeSet("./devices/input", ctxt, &nodes)) < 0)
19943         return NULL;
19944     if (n)
19945         def->inputs = g_new0(virDomainInputDef *, n);
19946 
19947     for (i = 0; i < n; i++) {
19948         virDomainInputDef *input = virDomainInputDefParseXML(xmlopt,
19949                                                              def,
19950                                                              nodes[i],
19951                                                              ctxt,
19952                                                              flags);
19953         if (!input)
19954             return NULL;
19955 
19956         /* Check if USB bus is required */
19957         if (input->bus == VIR_DOMAIN_INPUT_BUS_USB && usb_none) {
19958             virDomainInputDefFree(input);
19959             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
19960                            _("Can't add USB input device. "
19961                              "USB bus is disabled"));
19962             return NULL;
19963         }
19964 
19965         def->inputs[def->ninputs++] = input;
19966     }
19967     VIR_FREE(nodes);
19968 
19969     /* analysis of the graphics devices */
19970     if ((n = virXPathNodeSet("./devices/graphics", ctxt, &nodes)) < 0)
19971         return NULL;
19972     if (n)
19973         def->graphics = g_new0(virDomainGraphicsDef *, n);
19974     for (i = 0; i < n; i++) {
19975         virDomainGraphicsDef *graphics = virDomainGraphicsDefParseXML(xmlopt,
19976                                                                       nodes[i],
19977                                                                       ctxt,
19978                                                                       flags);
19979         if (!graphics)
19980             return NULL;
19981 
19982         def->graphics[def->ngraphics++] = graphics;
19983     }
19984     VIR_FREE(nodes);
19985 
19986     /* analysis of the sound devices */
19987     if ((n = virXPathNodeSet("./devices/sound", ctxt, &nodes)) < 0)
19988         return NULL;
19989     if (n)
19990         def->sounds = g_new0(virDomainSoundDef *, n);
19991     for (i = 0; i < n; i++) {
19992         virDomainSoundDef *sound = virDomainSoundDefParseXML(xmlopt,
19993                                                              nodes[i],
19994                                                              ctxt,
19995                                                              flags);
19996         if (!sound)
19997             return NULL;
19998 
19999         def->sounds[def->nsounds++] = sound;
20000     }
20001     VIR_FREE(nodes);
20002 
20003     /* analysis of the audio devices */
20004     if ((n = virXPathNodeSet("./devices/audio", ctxt, &nodes)) < 0)
20005         return NULL;
20006     if (n)
20007         def->audios = g_new0(virDomainAudioDef *, n);
20008     for (i = 0; i < n; i++) {
20009         virDomainAudioDef *audio = virDomainAudioDefParseXML(xmlopt,
20010                                                              nodes[i],
20011                                                              ctxt);
20012         if (!audio)
20013             return NULL;
20014 
20015         def->audios[def->naudios++] = audio;
20016     }
20017     VIR_FREE(nodes);
20018 
20019     /* analysis of the video devices */
20020     if ((n = virXPathNodeSet("./devices/video", ctxt, &nodes)) < 0)
20021         return NULL;
20022     if (n)
20023         def->videos = g_new0(virDomainVideoDef *, n);
20024     for (i = 0; i < n; i++) {
20025         g_autoptr(virDomainVideoDef) video = NULL;
20026         ssize_t insertAt = -1;
20027 
20028         if (!(video = virDomainVideoDefParseXML(xmlopt, nodes[i],
20029                                                 ctxt, flags)))
20030             return NULL;
20031 
20032         if (video->primary) {
20033             insertAt = 0;
20034         }
20035 
20036         if (VIR_INSERT_ELEMENT_INPLACE(def->videos,
20037                                        insertAt,
20038                                        def->nvideos,
20039                                        video) < 0) {
20040             return NULL;
20041         }
20042     }
20043 
20044     VIR_FREE(nodes);
20045 
20046     /* analysis of the host devices */
20047     if ((n = virXPathNodeSet("./devices/hostdev", ctxt, &nodes)) < 0)
20048         return NULL;
20049     if (n > 0)
20050         VIR_REALLOC_N(def->hostdevs, def->nhostdevs + n);
20051 
20052     for (i = 0; i < n; i++) {
20053         virDomainHostdevDef *hostdev;
20054 
20055         hostdev = virDomainHostdevDefParseXML(xmlopt, nodes[i], ctxt,
20056                                               flags);
20057         if (!hostdev)
20058             return NULL;
20059 
20060         if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
20061             usb_none) {
20062             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20063                            _("Can't add host USB device: "
20064                              "USB is disabled in this host"));
20065             virDomainHostdevDefFree(hostdev);
20066             return NULL;
20067         }
20068 
20069         def->hostdevs[def->nhostdevs++] = hostdev;
20070 
20071         /* For a domain definition, we need to check if the controller
20072          * for this hostdev exists yet and if not add it. This cannot be
20073          * done during virDomainHostdevAssignAddress (as part of device
20074          * post processing) because that will result in the failure to
20075          * load the controller during hostdev hotplug.
20076          */
20077         if (virDomainDefMaybeAddHostdevSCSIcontroller(def) < 0)
20078             return NULL;
20079     }
20080     VIR_FREE(nodes);
20081 
20082     /* analysis of the watchdog devices */
20083     def->watchdog = NULL;
20084     if ((n = virXPathNodeSet("./devices/watchdog", ctxt, &nodes)) < 0)
20085         return NULL;
20086     if (n > 1) {
20087         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
20088                        _("only a single watchdog device is supported"));
20089         return NULL;
20090     }
20091     if (n > 0) {
20092         virDomainWatchdogDef *watchdog;
20093 
20094         watchdog = virDomainWatchdogDefParseXML(xmlopt, nodes[0], ctxt, flags);
20095         if (!watchdog)
20096             return NULL;
20097 
20098         def->watchdog = watchdog;
20099         VIR_FREE(nodes);
20100     }
20101 
20102     /* analysis of the memballoon devices */
20103     def->memballoon = NULL;
20104     if ((n = virXPathNodeSet("./devices/memballoon", ctxt, &nodes)) < 0)
20105         return NULL;
20106     if (n > 1) {
20107         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
20108                        _("only a single memory balloon device is supported"));
20109         return NULL;
20110     }
20111     if (n > 0) {
20112         virDomainMemballoonDef *memballoon;
20113 
20114         memballoon = virDomainMemballoonDefParseXML(xmlopt, nodes[0], ctxt, flags);
20115         if (!memballoon)
20116             return NULL;
20117 
20118         def->memballoon = memballoon;
20119         VIR_FREE(nodes);
20120     }
20121 
20122     /* Parse the RNG devices */
20123     if ((n = virXPathNodeSet("./devices/rng", ctxt, &nodes)) < 0)
20124         return NULL;
20125     if (n)
20126         def->rngs = g_new0(virDomainRNGDef *, n);
20127     for (i = 0; i < n; i++) {
20128         virDomainRNGDef *rng = virDomainRNGDefParseXML(xmlopt, nodes[i],
20129                                                        ctxt, flags);
20130         if (!rng)
20131             return NULL;
20132 
20133         def->rngs[def->nrngs++] = rng;
20134     }
20135     VIR_FREE(nodes);
20136 
20137     /* Parse the TPM devices */
20138     if ((n = virXPathNodeSet("./devices/tpm", ctxt, &nodes)) < 0)
20139         return NULL;
20140 
20141     if (n > 2) {
20142         virReportError(VIR_ERR_XML_ERROR, "%s",
20143                        _("a maximum of two TPM devices is supported, one of "
20144                          "them being a TPM Proxy device"));
20145         return NULL;
20146     }
20147 
20148     if (n)
20149         def->tpms = g_new0(virDomainTPMDef *, n);
20150 
20151     for (i = 0; i < n; i++) {
20152         virDomainTPMDef *tpm = virDomainTPMDefParseXML(xmlopt, nodes[i],
20153                                                        ctxt, flags);
20154         if (!tpm)
20155             return NULL;
20156 
20157         def->tpms[def->ntpms++] = tpm;
20158     }
20159     VIR_FREE(nodes);
20160 
20161     if ((n = virXPathNodeSet("./devices/nvram", ctxt, &nodes)) < 0)
20162         return NULL;
20163 
20164     if (n > 1) {
20165         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
20166                        _("only a single nvram device is supported"));
20167         return NULL;
20168     } else if (n == 1) {
20169         virDomainNVRAMDef *nvram =
20170             virDomainNVRAMDefParseXML(xmlopt, nodes[0], ctxt, flags);
20171         if (!nvram)
20172             return NULL;
20173         def->nvram = nvram;
20174         VIR_FREE(nodes);
20175     }
20176 
20177     /* analysis of the hub devices */
20178     if ((n = virXPathNodeSet("./devices/hub", ctxt, &nodes)) < 0)
20179         return NULL;
20180     if (n)
20181         def->hubs = g_new0(virDomainHubDef *, n);
20182     for (i = 0; i < n; i++) {
20183         virDomainHubDef *hub;
20184 
20185         hub = virDomainHubDefParseXML(xmlopt, nodes[i], ctxt, flags);
20186         if (!hub)
20187             return NULL;
20188 
20189         if (hub->type == VIR_DOMAIN_HUB_TYPE_USB && usb_none) {
20190             virDomainHubDefFree(hub);
20191             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20192                            _("Can't add USB hub: "
20193                              "USB is disabled for this domain"));
20194             return NULL;
20195         }
20196 
20197         def->hubs[def->nhubs++] = hub;
20198     }
20199     VIR_FREE(nodes);
20200 
20201     /* analysis of the redirected devices */
20202     if ((n = virXPathNodeSet("./devices/redirdev", ctxt, &nodes)) < 0)
20203         return NULL;
20204     if (n)
20205         def->redirdevs = g_new0(virDomainRedirdevDef *, n);
20206     for (i = 0; i < n; i++) {
20207         virDomainRedirdevDef *redirdev =
20208             virDomainRedirdevDefParseXML(xmlopt, nodes[i], ctxt, flags);
20209         if (!redirdev)
20210             return NULL;
20211 
20212         def->redirdevs[def->nredirdevs++] = redirdev;
20213     }
20214     VIR_FREE(nodes);
20215 
20216     /* analysis of the redirection filter rules */
20217     if ((n = virXPathNodeSet("./devices/redirfilter", ctxt, &nodes)) < 0)
20218         return NULL;
20219     if (n > 1) {
20220         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
20221                        _("only one set of redirection filter rule is supported"));
20222         return NULL;
20223     }
20224 
20225     if (n) {
20226         virDomainRedirFilterDef *redirfilter =
20227             virDomainRedirFilterDefParseXML(nodes[0], ctxt);
20228         if (!redirfilter)
20229             return NULL;
20230 
20231         def->redirfilter = redirfilter;
20232     }
20233     VIR_FREE(nodes);
20234 
20235     /* analysis of the panic devices */
20236     if ((n = virXPathNodeSet("./devices/panic", ctxt, &nodes)) < 0)
20237         return NULL;
20238     if (n)
20239         def->panics = g_new0(virDomainPanicDef *, n);
20240     for (i = 0; i < n; i++) {
20241         virDomainPanicDef *panic;
20242 
20243         panic = virDomainPanicDefParseXML(xmlopt, nodes[i], ctxt, flags);
20244         if (!panic)
20245             return NULL;
20246 
20247         def->panics[def->npanics++] = panic;
20248     }
20249     VIR_FREE(nodes);
20250 
20251     /* analysis of the shmem devices */
20252     if ((n = virXPathNodeSet("./devices/shmem", ctxt, &nodes)) < 0)
20253         return NULL;
20254     if (n)
20255         def->shmems = g_new0(virDomainShmemDef *, n);
20256 
20257     node = ctxt->node;
20258     for (i = 0; i < n; i++) {
20259         virDomainShmemDef *shmem;
20260         ctxt->node = nodes[i];
20261         shmem = virDomainShmemDefParseXML(xmlopt, nodes[i], ctxt, flags);
20262         if (!shmem)
20263             return NULL;
20264 
20265         def->shmems[def->nshmems++] = shmem;
20266     }
20267     ctxt->node = node;
20268     VIR_FREE(nodes);
20269 
20270     /* Check for launch security e.g. SEV feature */
20271     if ((node = virXPathNode("./launchSecurity", ctxt)) != NULL) {
20272         def->sec = virDomainSecDefParseXML(node, ctxt);
20273         if (!def->sec)
20274             return NULL;
20275     }
20276 
20277     /* analysis of memory devices */
20278     if ((n = virXPathNodeSet("./devices/memory", ctxt, &nodes)) < 0)
20279         return NULL;
20280     if (n)
20281         def->mems = g_new0(virDomainMemoryDef *, n);
20282 
20283     for (i = 0; i < n; i++) {
20284         virDomainMemoryDef *mem = virDomainMemoryDefParseXML(xmlopt,
20285                                                              nodes[i],
20286                                                              ctxt,
20287                                                              flags);
20288         if (!mem)
20289             return NULL;
20290 
20291         def->mems[def->nmems++] = mem;
20292     }
20293     VIR_FREE(nodes);
20294 
20295     if ((n = virXPathNodeSet("./devices/iommu", ctxt, &nodes)) < 0)
20296         return NULL;
20297 
20298     if (n > 1) {
20299         virReportError(VIR_ERR_XML_ERROR, "%s",
20300                        _("only a single IOMMU device is supported"));
20301         return NULL;
20302     }
20303 
20304     if (n > 0) {
20305         if (!(def->iommu = virDomainIOMMUDefParseXML(nodes[0], ctxt)))
20306             return NULL;
20307     }
20308     VIR_FREE(nodes);
20309 
20310     if ((n = virXPathNodeSet("./devices/vsock", ctxt, &nodes)) < 0)
20311         return NULL;
20312 
20313     if (n > 1) {
20314         virReportError(VIR_ERR_XML_ERROR, "%s",
20315                        _("only a single vsock device is supported"));
20316         return NULL;
20317     }
20318 
20319     if (n > 0) {
20320         if (!(def->vsock = virDomainVsockDefParseXML(xmlopt, nodes[0],
20321                                                      ctxt, flags)))
20322             return NULL;
20323     }
20324     VIR_FREE(nodes);
20325 
20326     /* analysis of the user namespace mapping */
20327     if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0)
20328         return NULL;
20329 
20330     if (n) {
20331         def->idmap.uidmap = virDomainIdmapDefParseXML(ctxt, nodes, n);
20332         if (!def->idmap.uidmap)
20333             return NULL;
20334 
20335         def->idmap.nuidmap = n;
20336     }
20337     VIR_FREE(nodes);
20338 
20339     if  ((n = virXPathNodeSet("./idmap/gid", ctxt, &nodes)) < 0)
20340         return NULL;
20341 
20342     if (n) {
20343         def->idmap.gidmap =  virDomainIdmapDefParseXML(ctxt, nodes, n);
20344         if (!def->idmap.gidmap)
20345             return NULL;
20346 
20347         def->idmap.ngidmap = n;
20348     }
20349     VIR_FREE(nodes);
20350 
20351     if ((n = virXPathNodeSet("./sysinfo", ctxt, &nodes)) < 0)
20352         return NULL;
20353 
20354     def->sysinfo = g_new0(virSysinfoDef *, n);
20355 
20356     for (i = 0; i < n; i++) {
20357         virSysinfoDef *sysinfo = virSysinfoParseXML(nodes[i], ctxt,
20358                                                     def->uuid, uuid_generated);
20359 
20360         if (!sysinfo)
20361             return NULL;
20362 
20363         def->sysinfo[def->nsysinfo++] = sysinfo;
20364     }
20365     VIR_FREE(nodes);
20366 
20367     if ((tmp = virXPathString("string(./os/smbios/@mode)", ctxt))) {
20368         int mode;
20369 
20370         if ((mode = virDomainSmbiosModeTypeFromString(tmp)) < 0) {
20371             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20372                            _("unknown smbios mode '%s'"), tmp);
20373             return NULL;
20374         }
20375         def->os.smbios_mode = mode;
20376     }
20377 
20378     if (virDomainKeyWrapDefParseXML(def, ctxt) < 0)
20379         return NULL;
20380 
20381     /* Extract custom metadata */
20382     if ((node = virXPathNode("./metadata[1]", ctxt)) != NULL)
20383         def->metadata = xmlCopyNode(node, 1);
20384 
20385     /* we have to make a copy of all of the callback pointers here since
20386      * we won't have the virCaps structure available during free
20387      */
20388     def->ns = xmlopt->ns;
20389 
20390     if (def->ns.parse) {
20391         if (virXMLNamespaceRegister(ctxt, &def->ns) < 0)
20392             return NULL;
20393         if ((def->ns.parse)(ctxt, &def->namespaceData) < 0)
20394             return NULL;
20395     }
20396 
20397     return g_steal_pointer(&def);
20398 }
20399 
20400 
20401 static virDomainObj *
virDomainObjParseXML(xmlXPathContextPtr ctxt,virDomainXMLOption * xmlopt,unsigned int flags)20402 virDomainObjParseXML(xmlXPathContextPtr ctxt,
20403                      virDomainXMLOption *xmlopt,
20404                      unsigned int flags)
20405 {
20406     long val;
20407     xmlNodePtr config;
20408     xmlNodePtr oldnode;
20409     g_autoptr(virDomainObj) obj = NULL;
20410     size_t i;
20411     int n;
20412     virDomainState state;
20413     int reason = 0;
20414     void *parseOpaque = NULL;
20415     g_autofree char *tmp = NULL;
20416     g_autofree xmlNodePtr *taintNodes = NULL;
20417     g_autofree xmlNodePtr *depNodes = NULL;
20418 
20419     if (!(obj = virDomainObjNew(xmlopt)))
20420         return NULL;
20421 
20422     if (!(config = virXPathNode("./domain", ctxt))) {
20423         virReportError(VIR_ERR_INTERNAL_ERROR,
20424                        "%s", _("no domain config"));
20425         return NULL;
20426     }
20427 
20428     oldnode = ctxt->node;
20429     ctxt->node = config;
20430     obj->def = virDomainDefParseXML(ctxt, xmlopt, flags);
20431     ctxt->node = oldnode;
20432     if (!obj->def)
20433         return NULL;
20434 
20435     if (virXMLPropEnum(ctxt->node, "state", virDomainStateTypeFromString,
20436                        VIR_XML_PROP_REQUIRED, &state) < 0)
20437         return NULL;
20438 
20439     if ((tmp = virXMLPropString(ctxt->node, "reason"))) {
20440         if ((reason = virDomainStateReasonFromString(state, tmp)) < 0) {
20441             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20442                            _("invalid domain state reason '%s'"), tmp);
20443             return NULL;
20444         }
20445     }
20446 
20447     virDomainObjSetState(obj, state, reason);
20448 
20449     if (virXPathLong("string(./@pid)", ctxt, &val) < 0) {
20450         virReportError(VIR_ERR_INTERNAL_ERROR,
20451                        "%s", _("invalid pid"));
20452         return NULL;
20453     }
20454     obj->pid = (pid_t)val;
20455 
20456     if ((n = virXPathNodeSet("./taint", ctxt, &taintNodes)) < 0)
20457         return NULL;
20458     for (i = 0; i < n; i++) {
20459         int rc;
20460         virDomainTaintFlags taint;
20461 
20462         if ((rc = virXMLPropEnum(taintNodes[i], "flag",
20463                                  virDomainTaintTypeFromString,
20464                                  VIR_XML_PROP_NONE, &taint)) < 0)
20465             return NULL;
20466 
20467         if (rc == 1)
20468             virDomainObjTaint(obj, taint);
20469     }
20470 
20471     if ((n = virXPathNodeSet("./deprecation", ctxt, &depNodes)) < 0)
20472         return NULL;
20473     for (i = 0; i < n; i++) {
20474         g_autofree char *str = virXMLNodeContentString(depNodes[i]);
20475         virDomainObjDeprecation(obj, str);
20476     }
20477 
20478     if (xmlopt->privateData.parse &&
20479         xmlopt->privateData.parse(ctxt, obj, &xmlopt->config) < 0)
20480         return NULL;
20481 
20482     if (xmlopt->privateData.getParseOpaque)
20483         parseOpaque = xmlopt->privateData.getParseOpaque(obj);
20484 
20485     /* callback to fill driver specific domain aspects */
20486     if (virDomainDefPostParse(obj->def, flags, xmlopt, parseOpaque) < 0)
20487         return NULL;
20488 
20489     /* validate configuration */
20490     if (virDomainDefValidate(obj->def, flags, xmlopt, parseOpaque) < 0)
20491         return NULL;
20492 
20493     return g_steal_pointer(&obj);
20494 }
20495 
20496 
20497 static virDomainDef *
virDomainDefParse(const char * xmlStr,const char * filename,virDomainXMLOption * xmlopt,void * parseOpaque,unsigned int flags)20498 virDomainDefParse(const char *xmlStr,
20499                   const char *filename,
20500                   virDomainXMLOption *xmlopt,
20501                   void *parseOpaque,
20502                   unsigned int flags)
20503 {
20504     g_autoptr(xmlDoc) xml = NULL;
20505     virDomainDef *def = NULL;
20506     int keepBlanksDefault = xmlKeepBlanksDefault(0);
20507     xmlNodePtr root;
20508     if (!(xml = virXMLParse(filename, xmlStr, _("(domain_definition)"), "domain.rng",
20509                             flags & VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA)))
20510         goto cleanup;
20511 
20512     root = xmlDocGetRootElement(xml);
20513     if (!virXMLNodeNameEqual(root, "domain")) {
20514         virReportError(VIR_ERR_XML_ERROR,
20515                        _("unexpected root element <%s>, "
20516                          "expecting <domain>"),
20517                        root->name);
20518         goto cleanup;
20519     }
20520 
20521     def = virDomainDefParseNode(xml, root, xmlopt, parseOpaque, flags);
20522 
20523  cleanup:
20524     xmlKeepBlanksDefault(keepBlanksDefault);
20525     return def;
20526 }
20527 
20528 virDomainDef *
virDomainDefParseString(const char * xmlStr,virDomainXMLOption * xmlopt,void * parseOpaque,unsigned int flags)20529 virDomainDefParseString(const char *xmlStr,
20530                         virDomainXMLOption *xmlopt,
20531                         void *parseOpaque,
20532                         unsigned int flags)
20533 {
20534     return virDomainDefParse(xmlStr, NULL, xmlopt, parseOpaque, flags);
20535 }
20536 
20537 virDomainDef *
virDomainDefParseFile(const char * filename,virDomainXMLOption * xmlopt,void * parseOpaque,unsigned int flags)20538 virDomainDefParseFile(const char *filename,
20539                       virDomainXMLOption *xmlopt,
20540                       void *parseOpaque,
20541                       unsigned int flags)
20542 {
20543     return virDomainDefParse(NULL, filename, xmlopt, parseOpaque, flags);
20544 }
20545 
20546 
20547 virDomainDef *
virDomainDefParseNode(xmlDocPtr xml,xmlNodePtr root,virDomainXMLOption * xmlopt,void * parseOpaque,unsigned int flags)20548 virDomainDefParseNode(xmlDocPtr xml,
20549                       xmlNodePtr root,
20550                       virDomainXMLOption *xmlopt,
20551                       void *parseOpaque,
20552                       unsigned int flags)
20553 {
20554     g_autoptr(xmlXPathContext) ctxt = NULL;
20555     g_autoptr(virDomainDef) def = NULL;
20556 
20557     if (!(ctxt = virXMLXPathContextNew(xml)))
20558         return NULL;
20559 
20560     ctxt->node = root;
20561 
20562     if (!(def = virDomainDefParseXML(ctxt, xmlopt, flags)))
20563         return NULL;
20564 
20565     /* callback to fill driver specific domain aspects */
20566     if (virDomainDefPostParse(def, flags, xmlopt, parseOpaque) < 0)
20567         return NULL;
20568 
20569     /* validate configuration */
20570     if (virDomainDefValidate(def, flags, xmlopt, parseOpaque) < 0)
20571         return NULL;
20572 
20573     return g_steal_pointer(&def);
20574 }
20575 
20576 
20577 virDomainObj *
virDomainObjParseNode(xmlDocPtr xml,xmlNodePtr root,virDomainXMLOption * xmlopt,unsigned int flags)20578 virDomainObjParseNode(xmlDocPtr xml,
20579                       xmlNodePtr root,
20580                       virDomainXMLOption *xmlopt,
20581                       unsigned int flags)
20582 {
20583     g_autoptr(xmlXPathContext) ctxt = NULL;
20584 
20585     if (!virXMLNodeNameEqual(root, "domstatus")) {
20586         virReportError(VIR_ERR_XML_ERROR,
20587                        _("unexpected root element <%s>, "
20588                          "expecting <domstatus>"),
20589                        root->name);
20590         return NULL;
20591     }
20592 
20593     if (!(ctxt = virXMLXPathContextNew(xml)))
20594         return NULL;
20595 
20596     ctxt->node = root;
20597     return virDomainObjParseXML(ctxt, xmlopt, flags);
20598 }
20599 
20600 
20601 virDomainObj *
virDomainObjParseFile(const char * filename,virDomainXMLOption * xmlopt,unsigned int flags)20602 virDomainObjParseFile(const char *filename,
20603                       virDomainXMLOption *xmlopt,
20604                       unsigned int flags)
20605 {
20606     g_autoptr(xmlDoc) xml = NULL;
20607     virDomainObj *obj = NULL;
20608     int keepBlanksDefault = xmlKeepBlanksDefault(0);
20609 
20610     if ((xml = virXMLParseFile(filename))) {
20611         obj = virDomainObjParseNode(xml, xmlDocGetRootElement(xml),
20612                                     xmlopt, flags);
20613     }
20614 
20615     xmlKeepBlanksDefault(keepBlanksDefault);
20616     return obj;
20617 }
20618 
20619 
20620 static bool
virDomainTimerDefCheckABIStability(virDomainTimerDef * src,virDomainTimerDef * dst)20621 virDomainTimerDefCheckABIStability(virDomainTimerDef *src,
20622                                    virDomainTimerDef *dst)
20623 {
20624     if (src->name != dst->name) {
20625         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20626                        _("Target timer %s does not match source %s"),
20627                        virDomainTimerNameTypeToString(dst->name),
20628                        virDomainTimerNameTypeToString(src->name));
20629         return false;
20630     }
20631 
20632     if (src->present != dst->present) {
20633         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20634                        _("Target timer presence %d does not match source %d"),
20635                        dst->present, src->present);
20636         return false;
20637     }
20638 
20639     if (src->name == VIR_DOMAIN_TIMER_NAME_TSC) {
20640         if (src->frequency != dst->frequency) {
20641             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20642                            _("Target TSC frequency %llu does not match source %llu"),
20643                            dst->frequency, src->frequency);
20644             return false;
20645         }
20646 
20647         if (src->mode != dst->mode) {
20648             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20649                            _("Target TSC mode %s does not match source %s"),
20650                            virDomainTimerModeTypeToString(dst->mode),
20651                            virDomainTimerModeTypeToString(src->mode));
20652             return false;
20653         }
20654     }
20655 
20656     return true;
20657 }
20658 
20659 
20660 static bool
virDomainDeviceInfoCheckABIStability(virDomainDeviceInfo * src,virDomainDeviceInfo * dst)20661 virDomainDeviceInfoCheckABIStability(virDomainDeviceInfo *src,
20662                                      virDomainDeviceInfo *dst)
20663 {
20664     if (src->type != dst->type) {
20665         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20666                        _("Target device address type %s does not match source %s"),
20667                        virDomainDeviceAddressTypeToString(dst->type),
20668                        virDomainDeviceAddressTypeToString(src->type));
20669         return false;
20670     }
20671 
20672     switch ((virDomainDeviceAddressType) src->type) {
20673     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
20674         if (src->addr.pci.domain != dst->addr.pci.domain ||
20675             src->addr.pci.bus != dst->addr.pci.bus ||
20676             src->addr.pci.slot != dst->addr.pci.slot ||
20677             src->addr.pci.function != dst->addr.pci.function) {
20678             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20679                            _("Target device PCI address " VIR_PCI_DEVICE_ADDRESS_FMT
20680                              "does not match source " VIR_PCI_DEVICE_ADDRESS_FMT),
20681                            dst->addr.pci.domain, dst->addr.pci.bus,
20682                            dst->addr.pci.slot, dst->addr.pci.function,
20683                            src->addr.pci.domain, src->addr.pci.bus,
20684                            src->addr.pci.slot, src->addr.pci.function);
20685             return false;
20686         }
20687         break;
20688 
20689     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
20690         if (src->addr.drive.controller != dst->addr.drive.controller ||
20691             src->addr.drive.bus != dst->addr.drive.bus ||
20692             src->addr.drive.unit != dst->addr.drive.unit) {
20693             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20694                            _("Target device drive address %d:%d:%d "
20695                              "does not match source %d:%d:%d"),
20696                            dst->addr.drive.controller, dst->addr.drive.bus,
20697                            dst->addr.drive.unit,
20698                            src->addr.drive.controller, src->addr.drive.bus,
20699                            src->addr.drive.unit);
20700             return false;
20701         }
20702         break;
20703 
20704     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL:
20705         if (src->addr.vioserial.controller != dst->addr.vioserial.controller ||
20706             src->addr.vioserial.bus != dst->addr.vioserial.bus ||
20707             src->addr.vioserial.port != dst->addr.vioserial.port) {
20708             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20709                            _("Target device virtio serial address %d:%d:%d "
20710                              "does not match source %d:%d:%d"),
20711                            dst->addr.vioserial.controller, dst->addr.vioserial.bus,
20712                            dst->addr.vioserial.port,
20713                            src->addr.vioserial.controller, src->addr.vioserial.bus,
20714                            src->addr.vioserial.port);
20715             return false;
20716         }
20717         break;
20718 
20719     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
20720         if (src->addr.ccid.controller != dst->addr.ccid.controller ||
20721             src->addr.ccid.slot != dst->addr.ccid.slot) {
20722             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20723                            _("Target device ccid address %d:%d "
20724                              "does not match source %d:%d"),
20725                            dst->addr.ccid.controller,
20726                            dst->addr.ccid.slot,
20727                            src->addr.ccid.controller,
20728                            src->addr.ccid.slot);
20729             return false;
20730         }
20731         break;
20732 
20733     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
20734         if (src->addr.isa.iobase != dst->addr.isa.iobase ||
20735             src->addr.isa.irq != dst->addr.isa.irq) {
20736             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20737                            _("Target device isa address %d:%d "
20738                              "does not match source %d:%d"),
20739                            dst->addr.isa.iobase,
20740                            dst->addr.isa.irq,
20741                            src->addr.isa.iobase,
20742                            src->addr.isa.irq);
20743             return false;
20744         }
20745         break;
20746 
20747     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
20748         if (src->addr.dimm.slot != dst->addr.dimm.slot) {
20749             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20750                            _("Target device dimm slot %u does not match "
20751                              "source %u"),
20752                            dst->addr.dimm.slot,
20753                            src->addr.dimm.slot);
20754             return false;
20755         }
20756 
20757         if (src->addr.dimm.base != dst->addr.dimm.base) {
20758             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20759                            _("Target device dimm base address '%llx' does "
20760                              "not match source '%llx'"),
20761                            dst->addr.dimm.base,
20762                            src->addr.dimm.base);
20763             return false;
20764         }
20765         break;
20766 
20767     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
20768     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
20769     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390:
20770     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
20771     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_MMIO:
20772     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE:
20773     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED:
20774     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST:
20775         break;
20776     }
20777 
20778     if (src->acpiIndex != dst->acpiIndex) {
20779         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20780                        _("Target ACPI index '%u' does not match source '%u'"),
20781                        dst->acpiIndex, src->acpiIndex);
20782         return false;
20783     }
20784 
20785     return true;
20786 }
20787 
20788 
20789 static bool
virDomainVirtioOptionsCheckABIStability(virDomainVirtioOptions * src,virDomainVirtioOptions * dst)20790 virDomainVirtioOptionsCheckABIStability(virDomainVirtioOptions *src,
20791                                         virDomainVirtioOptions *dst)
20792 {
20793     if (!src && !dst)
20794         return true;
20795 
20796     if (!src || !dst) {
20797         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20798                        _("Target device virtio options don't match the source"));
20799         return false;
20800     }
20801 
20802     if (src->iommu != dst->iommu) {
20803         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20804                        _("Target device iommu option '%s' does not "
20805                          "match source '%s'"),
20806                        virTristateSwitchTypeToString(dst->iommu),
20807                        virTristateSwitchTypeToString(src->iommu));
20808         return false;
20809     }
20810     if (src->ats != dst->ats) {
20811         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20812                        _("Target device ats option '%s' does not "
20813                          "match source '%s'"),
20814                        virTristateSwitchTypeToString(dst->ats),
20815                        virTristateSwitchTypeToString(src->ats));
20816         return false;
20817     }
20818     if (src->packed != dst->packed) {
20819         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20820                        _("Target device packed option '%s' does not "
20821                          "match source '%s'"),
20822                        virTristateSwitchTypeToString(dst->packed),
20823                        virTristateSwitchTypeToString(src->packed));
20824         return false;
20825     }
20826     if (src->page_per_vq != dst->page_per_vq) {
20827         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20828                        _("Target device page_per_vq option '%s' does not "
20829                          "match source '%s'"),
20830                        virTristateSwitchTypeToString(dst->page_per_vq),
20831                        virTristateSwitchTypeToString(src->page_per_vq));
20832         return false;
20833     }
20834     return true;
20835 }
20836 
20837 
20838 static bool
virDomainDiskDefCheckABIStability(virDomainDiskDef * src,virDomainDiskDef * dst)20839 virDomainDiskDefCheckABIStability(virDomainDiskDef *src,
20840                                   virDomainDiskDef *dst)
20841 {
20842     if (src->device != dst->device) {
20843         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20844                        _("Target disk device %s does not match source %s"),
20845                        virDomainDiskDeviceTypeToString(dst->device),
20846                        virDomainDiskDeviceTypeToString(src->device));
20847         return false;
20848     }
20849 
20850     if (src->bus != dst->bus) {
20851         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20852                        _("Target disk bus %s does not match source %s"),
20853                        virDomainDiskBusTypeToString(dst->bus),
20854                        virDomainDiskBusTypeToString(src->bus));
20855         return false;
20856     }
20857 
20858     if (STRNEQ(src->dst, dst->dst)) {
20859         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20860                        _("Target disk %s does not match source %s"),
20861                        dst->dst, src->dst);
20862         return false;
20863     }
20864 
20865     if (STRNEQ_NULLABLE(src->serial, dst->serial)) {
20866         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20867                        _("Target disk serial %s does not match source %s"),
20868                        NULLSTR(dst->serial), NULLSTR(src->serial));
20869         return false;
20870     }
20871 
20872     if (STRNEQ_NULLABLE(src->wwn, dst->wwn)) {
20873         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20874                        _("Target disk wwn '%s' does not match source '%s'"),
20875                        NULLSTR(dst->wwn), NULLSTR(src->wwn));
20876         return false;
20877 
20878     }
20879 
20880     if (src->src->readonly != dst->src->readonly) {
20881         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20882                        _("Target disk access mode does not match source"));
20883         return false;
20884     }
20885 
20886     if (src->model != dst->model) {
20887         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20888                        _("Target disk model %s does not match source %s"),
20889                        virDomainDiskModelTypeToString(dst->model),
20890                        virDomainDiskModelTypeToString(src->model));
20891         return false;
20892     }
20893 
20894     if (src->rotation_rate != dst->rotation_rate) {
20895         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20896                        _("Target disk rotation rate %u RPM does not match source %u RPM"),
20897                        dst->rotation_rate, src->rotation_rate);
20898         return false;
20899     }
20900 
20901     if (src->queues != dst->queues) {
20902         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20903                        _("Target disk queue count %u does not match source %u"),
20904                        dst->queues, src->queues);
20905         return false;
20906     }
20907 
20908     if (src->queue_size != dst->queue_size) {
20909         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20910                        _("Target disk queue size %u does not match source %u"),
20911                        dst->queues, src->queues);
20912         return false;
20913     }
20914 
20915     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
20916         return false;
20917 
20918     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
20919         return false;
20920 
20921     return true;
20922 }
20923 
20924 
20925 static bool
virDomainControllerDefCheckABIStability(virDomainControllerDef * src,virDomainControllerDef * dst)20926 virDomainControllerDefCheckABIStability(virDomainControllerDef *src,
20927                                         virDomainControllerDef *dst)
20928 {
20929     if (src->type != dst->type) {
20930         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20931                        _("Target controller type %s does not match source %s"),
20932                        virDomainControllerTypeToString(dst->type),
20933                        virDomainControllerTypeToString(src->type));
20934         return false;
20935     }
20936 
20937     if (src->idx != dst->idx) {
20938         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20939                        _("Target controller index %d does not match source %d"),
20940                        dst->idx, src->idx);
20941         return false;
20942     }
20943 
20944     if (src->model != dst->model) {
20945         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20946                        _("Target controller model %d does not match source %d"),
20947                        dst->model, src->model);
20948         return false;
20949     }
20950 
20951     if (src->type == VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) {
20952         if (src->opts.vioserial.ports != dst->opts.vioserial.ports) {
20953             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20954                            _("Target controller ports %d does not match source %d"),
20955                            dst->opts.vioserial.ports, src->opts.vioserial.ports);
20956             return false;
20957         }
20958 
20959         if (src->opts.vioserial.vectors != dst->opts.vioserial.vectors) {
20960             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20961                            _("Target controller vectors %d does not match source %d"),
20962                            dst->opts.vioserial.vectors, src->opts.vioserial.vectors);
20963             return false;
20964         }
20965     } else if (src->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
20966         if (src->opts.usbopts.ports != dst->opts.usbopts.ports) {
20967             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20968                            _("Target controller ports %d does not match source %d"),
20969                            dst->opts.usbopts.ports, src->opts.usbopts.ports);
20970             return false;
20971         }
20972     }
20973 
20974     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
20975         return false;
20976 
20977     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
20978         return false;
20979 
20980     return true;
20981 }
20982 
20983 
20984 static bool
virDomainFsDefCheckABIStability(virDomainFSDef * src,virDomainFSDef * dst)20985 virDomainFsDefCheckABIStability(virDomainFSDef *src,
20986                                 virDomainFSDef *dst)
20987 {
20988     if (STRNEQ_NULLABLE(src->dst, dst->dst)) {
20989         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
20990                        _("Target filesystem guest target %s does not match source %s"),
20991                        dst->dst, src->dst);
20992         return false;
20993     }
20994 
20995     if (src->readonly != dst->readonly) {
20996         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
20997                        _("Target filesystem access mode does not match source"));
20998         return false;
20999     }
21000 
21001     if (src->model != dst->model) {
21002         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21003                        _("Target filesystem model does not match source"));
21004         return false;
21005     }
21006 
21007     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
21008         return false;
21009 
21010     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21011         return false;
21012 
21013     return true;
21014 }
21015 
21016 
21017 static bool
virDomainNetDefCheckABIStability(virDomainNetDef * src,virDomainNetDef * dst)21018 virDomainNetDefCheckABIStability(virDomainNetDef *src,
21019                                  virDomainNetDef *dst)
21020 {
21021     char srcmac[VIR_MAC_STRING_BUFLEN];
21022     char dstmac[VIR_MAC_STRING_BUFLEN];
21023 
21024     if (virMacAddrCmp(&src->mac, &dst->mac) != 0) {
21025         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21026                        _("Target network card mac %s"
21027                          " does not match source %s"),
21028                        virMacAddrFormat(&dst->mac, dstmac),
21029                        virMacAddrFormat(&src->mac, srcmac));
21030         return false;
21031     }
21032 
21033     if (STRNEQ_NULLABLE(src->modelstr, dst->modelstr)) {
21034         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21035                        _("Target network card model %s does not match source %s"),
21036                        NULLSTR(dst->modelstr), NULLSTR(src->modelstr));
21037         return false;
21038     }
21039 
21040     if (src->model != dst->model) {
21041         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21042                        _("Target network card model %s does not match source %s"),
21043                        virDomainNetModelTypeToString(dst->model),
21044                        virDomainNetModelTypeToString(src->model));
21045         return false;
21046     }
21047 
21048     if (src->mtu != dst->mtu) {
21049         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21050                        _("Target network card MTU %d does not match source %d"),
21051                        dst->mtu, src->mtu);
21052         return false;
21053     }
21054 
21055     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
21056         return false;
21057 
21058     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21059         return false;
21060 
21061     return true;
21062 }
21063 
21064 
21065 static bool
virDomainInputDefCheckABIStability(virDomainInputDef * src,virDomainInputDef * dst)21066 virDomainInputDefCheckABIStability(virDomainInputDef *src,
21067                                    virDomainInputDef *dst)
21068 {
21069     if (src->type != dst->type) {
21070         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21071                        _("Target input device type %s does not match source %s"),
21072                        virDomainInputTypeToString(dst->type),
21073                        virDomainInputTypeToString(src->type));
21074         return false;
21075     }
21076 
21077     if (src->bus != dst->bus) {
21078         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21079                        _("Target input device bus %s does not match source %s"),
21080                        virDomainInputBusTypeToString(dst->bus),
21081                        virDomainInputBusTypeToString(src->bus));
21082         return false;
21083     }
21084 
21085     if (src->model != dst->model) {
21086         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21087                        _("Target input model %s does not match source %s"),
21088                        virDomainInputBusTypeToString(dst->model),
21089                        virDomainInputBusTypeToString(src->model));
21090         return false;
21091     }
21092 
21093     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
21094         return false;
21095 
21096     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21097         return false;
21098 
21099     return true;
21100 }
21101 
21102 
21103 static bool
virDomainSoundDefCheckABIStability(virDomainSoundDef * src,virDomainSoundDef * dst)21104 virDomainSoundDefCheckABIStability(virDomainSoundDef *src,
21105                                    virDomainSoundDef *dst)
21106 {
21107     if (src->model != dst->model) {
21108         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21109                        _("Target sound card model %s does not match source %s"),
21110                        virDomainSoundModelTypeToString(dst->model),
21111                        virDomainSoundModelTypeToString(src->model));
21112         return false;
21113     }
21114 
21115     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21116         return false;
21117 
21118     return true;
21119 }
21120 
21121 
21122 static bool
virDomainVideoDefCheckABIStability(virDomainVideoDef * src,virDomainVideoDef * dst)21123 virDomainVideoDefCheckABIStability(virDomainVideoDef *src,
21124                                    virDomainVideoDef *dst)
21125 {
21126     if (src->type != dst->type) {
21127         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21128                        _("Target video card model %s does not match source %s"),
21129                        virDomainVideoTypeToString(dst->type),
21130                        virDomainVideoTypeToString(src->type));
21131         return false;
21132     }
21133 
21134     if (src->ram != dst->ram) {
21135         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21136                        _("Target video card ram %u does not match source %u"),
21137                        dst->ram, src->ram);
21138         return false;
21139     }
21140 
21141     if (src->vram != dst->vram) {
21142         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21143                        _("Target video card vram %u does not match source %u"),
21144                        dst->vram, src->vram);
21145         return false;
21146     }
21147 
21148     if (src->vram64 != dst->vram64) {
21149         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21150                        _("Target video card vram64 %u does not match source %u"),
21151                        dst->vram64, src->vram64);
21152         return false;
21153     }
21154 
21155     if (src->vgamem != dst->vgamem) {
21156         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21157                        _("Target video card vgamem %u does not match source %u"),
21158                        dst->vgamem, src->vgamem);
21159         return false;
21160     }
21161 
21162     if (src->heads != dst->heads) {
21163         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21164                        _("Target video card heads %u does not match source %u"),
21165                        dst->heads, src->heads);
21166         return false;
21167     }
21168 
21169     if ((src->accel && !dst->accel) ||
21170         (!src->accel && dst->accel)) {
21171         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21172                        _("Target video card acceleration does not match source"));
21173         return false;
21174     }
21175 
21176     if (src->accel) {
21177         if (src->accel->accel2d != dst->accel->accel2d) {
21178             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21179                            _("Target video card 2d accel %u does not match source %u"),
21180                            dst->accel->accel2d, src->accel->accel2d);
21181             return false;
21182         }
21183 
21184         if (src->accel->accel3d != dst->accel->accel3d) {
21185             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21186                            _("Target video card 3d accel %u does not match source %u"),
21187                            dst->accel->accel3d, src->accel->accel3d);
21188             return false;
21189         }
21190     }
21191 
21192     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
21193         return false;
21194 
21195     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21196         return false;
21197 
21198     return true;
21199 }
21200 
21201 
21202 static bool
virDomainHostdevDefCheckABIStability(virDomainHostdevDef * src,virDomainHostdevDef * dst)21203 virDomainHostdevDefCheckABIStability(virDomainHostdevDef *src,
21204                                      virDomainHostdevDef *dst)
21205 {
21206     if (src->mode != dst->mode) {
21207         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21208                        _("Target host device mode %s does not match source %s"),
21209                        virDomainHostdevModeTypeToString(dst->mode),
21210                        virDomainHostdevModeTypeToString(src->mode));
21211         return false;
21212     }
21213 
21214     if (src->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
21215         src->source.subsys.type != dst->source.subsys.type) {
21216         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21217                        _("Target host device subsystem %s does not match source %s"),
21218                        virDomainHostdevSubsysTypeToString(dst->source.subsys.type),
21219                        virDomainHostdevSubsysTypeToString(src->source.subsys.type));
21220         return false;
21221     }
21222 
21223     if (!virDomainDeviceInfoCheckABIStability(src->info, dst->info))
21224         return false;
21225 
21226     return true;
21227 }
21228 
21229 
21230 static bool
virDomainSmartcardDefCheckABIStability(virDomainSmartcardDef * src,virDomainSmartcardDef * dst)21231 virDomainSmartcardDefCheckABIStability(virDomainSmartcardDef *src,
21232                                        virDomainSmartcardDef *dst)
21233 {
21234     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21235         return false;
21236 
21237     return true;
21238 }
21239 
21240 
21241 static bool
virDomainSerialDefCheckABIStability(virDomainChrDef * src,virDomainChrDef * dst)21242 virDomainSerialDefCheckABIStability(virDomainChrDef *src,
21243                                     virDomainChrDef *dst)
21244 {
21245     if (src->targetType != dst->targetType) {
21246         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21247                        _("Target serial type %s does not match source %s"),
21248                        virDomainChrSerialTargetTypeToString(dst->targetType),
21249                        virDomainChrSerialTargetTypeToString(src->targetType));
21250         return false;
21251     }
21252 
21253     if (src->target.port != dst->target.port) {
21254         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21255                        _("Target serial port %d does not match source %d"),
21256                        dst->target.port, src->target.port);
21257         return false;
21258     }
21259 
21260     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21261         return false;
21262 
21263     return true;
21264 }
21265 
21266 
21267 static bool
virDomainParallelDefCheckABIStability(virDomainChrDef * src,virDomainChrDef * dst)21268 virDomainParallelDefCheckABIStability(virDomainChrDef *src,
21269                                       virDomainChrDef *dst)
21270 {
21271     if (src->target.port != dst->target.port) {
21272         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21273                        _("Target parallel port %d does not match source %d"),
21274                        dst->target.port, src->target.port);
21275         return false;
21276     }
21277 
21278     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21279         return false;
21280 
21281     return true;
21282 }
21283 
21284 
21285 static bool
virDomainChannelDefCheckABIStability(virDomainChrDef * src,virDomainChrDef * dst)21286 virDomainChannelDefCheckABIStability(virDomainChrDef *src,
21287                                      virDomainChrDef *dst)
21288 {
21289     if (src->targetType != dst->targetType) {
21290         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21291                        _("Target channel type %s does not match source %s"),
21292                        virDomainChrChannelTargetTypeToString(dst->targetType),
21293                        virDomainChrChannelTargetTypeToString(src->targetType));
21294         return false;
21295     }
21296 
21297     switch (src->targetType) {
21298 
21299     case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
21300     case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
21301         if (STRNEQ_NULLABLE(src->target.name, dst->target.name)) {
21302             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21303                            _("Target channel name %s does not match source %s"),
21304                            NULLSTR(dst->target.name), NULLSTR(src->target.name));
21305             return false;
21306         }
21307         if (src->source->type != dst->source->type &&
21308             (src->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC ||
21309              dst->source->type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) &&
21310             !src->target.name) {
21311             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21312                            _("Changing device type to/from spicevmc would"
21313                              " change default target channel name"));
21314             return false;
21315         }
21316         break;
21317     case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
21318         if (memcmp(src->target.addr, dst->target.addr,
21319                    sizeof(*src->target.addr)) != 0) {
21320             g_autofree char *saddr = virSocketAddrFormatFull(src->target.addr, true, ":");
21321             g_autofree char *daddr = virSocketAddrFormatFull(dst->target.addr, true, ":");
21322             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21323                            _("Target channel addr %s does not match source %s"),
21324                            NULLSTR(daddr), NULLSTR(saddr));
21325             return false;
21326         }
21327         break;
21328     }
21329 
21330     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21331         return false;
21332 
21333     return true;
21334 }
21335 
21336 
21337 static bool
virDomainConsoleDefCheckABIStability(virDomainChrDef * src,virDomainChrDef * dst)21338 virDomainConsoleDefCheckABIStability(virDomainChrDef *src,
21339                                      virDomainChrDef *dst)
21340 {
21341     if (src->targetType != dst->targetType) {
21342         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21343                        _("Target console type %s does not match source %s"),
21344                        virDomainChrConsoleTargetTypeToString(dst->targetType),
21345                        virDomainChrConsoleTargetTypeToString(src->targetType));
21346         return false;
21347     }
21348 
21349     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21350         return false;
21351 
21352     return true;
21353 }
21354 
21355 
21356 static bool
virDomainWatchdogDefCheckABIStability(virDomainWatchdogDef * src,virDomainWatchdogDef * dst)21357 virDomainWatchdogDefCheckABIStability(virDomainWatchdogDef *src,
21358                                       virDomainWatchdogDef *dst)
21359 {
21360     if (src->model != dst->model) {
21361         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21362                        _("Target watchdog model %s does not match source %s"),
21363                        virDomainWatchdogModelTypeToString(dst->model),
21364                        virDomainWatchdogModelTypeToString(src->model));
21365         return false;
21366     }
21367 
21368     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21369         return false;
21370 
21371     return true;
21372 }
21373 
21374 
21375 static bool
virDomainMemballoonDefCheckABIStability(virDomainMemballoonDef * src,virDomainMemballoonDef * dst)21376 virDomainMemballoonDefCheckABIStability(virDomainMemballoonDef *src,
21377                                         virDomainMemballoonDef *dst)
21378 {
21379     if (src->model != dst->model) {
21380         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21381                        _("Target balloon model %s does not match source %s"),
21382                        virDomainMemballoonModelTypeToString(dst->model),
21383                        virDomainMemballoonModelTypeToString(src->model));
21384         return false;
21385     }
21386 
21387     if (src->autodeflate != dst->autodeflate) {
21388         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21389                        _("Target balloon autodeflate attribute value "
21390                          "'%s' does not match source '%s'"),
21391                        virTristateSwitchTypeToString(dst->autodeflate),
21392                        virTristateSwitchTypeToString(src->autodeflate));
21393         return false;
21394     }
21395 
21396     if (src->free_page_reporting != dst->free_page_reporting) {
21397         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21398                        _("Target balloon freePageReporting attribute value "
21399                          "'%s' does not match source '%s'"),
21400                        virTristateSwitchTypeToString(dst->free_page_reporting),
21401                        virTristateSwitchTypeToString(src->free_page_reporting));
21402         return false;
21403     }
21404 
21405     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
21406         return false;
21407 
21408     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21409         return false;
21410 
21411     return true;
21412 }
21413 
21414 
21415 static bool
virDomainRNGDefCheckABIStability(virDomainRNGDef * src,virDomainRNGDef * dst)21416 virDomainRNGDefCheckABIStability(virDomainRNGDef *src,
21417                                  virDomainRNGDef *dst)
21418 {
21419     if (src->model != dst->model) {
21420         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21421                        _("Target RNG model '%s' does not match source '%s'"),
21422                        virDomainRNGModelTypeToString(dst->model),
21423                        virDomainRNGModelTypeToString(src->model));
21424         return false;
21425     }
21426 
21427     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
21428         return false;
21429 
21430     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21431         return false;
21432 
21433     return true;
21434 }
21435 
21436 
21437 static bool
virDomainHubDefCheckABIStability(virDomainHubDef * src,virDomainHubDef * dst)21438 virDomainHubDefCheckABIStability(virDomainHubDef *src,
21439                                  virDomainHubDef *dst)
21440 {
21441     if (src->type != dst->type) {
21442         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21443                        _("Target hub device type %s does not match source %s"),
21444                        virDomainHubTypeToString(dst->type),
21445                        virDomainHubTypeToString(src->type));
21446         return false;
21447     }
21448 
21449     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21450         return false;
21451 
21452     return true;
21453 }
21454 
21455 
21456 static bool
virDomainRedirdevDefCheckABIStability(virDomainRedirdevDef * src,virDomainRedirdevDef * dst)21457 virDomainRedirdevDefCheckABIStability(virDomainRedirdevDef *src,
21458                                       virDomainRedirdevDef *dst)
21459 {
21460     if (src->bus != dst->bus) {
21461         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21462                        _("Target redirected device bus %s does not match "
21463                          "source %s"),
21464                        virDomainRedirdevBusTypeToString(dst->bus),
21465                        virDomainRedirdevBusTypeToString(src->bus));
21466         return false;
21467     }
21468 
21469     switch ((virDomainRedirdevBus) src->bus) {
21470     case VIR_DOMAIN_REDIRDEV_BUS_USB:
21471         if (src->source->type != dst->source->type) {
21472             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21473                            _("Target redirected device source type %s does "
21474                              "not match source device source type %s"),
21475                            virDomainChrTypeToString(dst->source->type),
21476                            virDomainChrTypeToString(src->source->type));
21477             return false;
21478         }
21479         break;
21480     case VIR_DOMAIN_REDIRDEV_BUS_LAST:
21481         break;
21482     }
21483 
21484     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
21485         return false;
21486 
21487     return true;
21488 }
21489 
21490 
21491 static bool
virDomainRedirFilterDefCheckABIStability(virDomainRedirFilterDef * src,virDomainRedirFilterDef * dst)21492 virDomainRedirFilterDefCheckABIStability(virDomainRedirFilterDef *src,
21493                                          virDomainRedirFilterDef *dst)
21494 {
21495     size_t i;
21496 
21497     if (src->nusbdevs != dst->nusbdevs) {
21498         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21499                        _("Target USB redirection filter rule "
21500                          "count %zu does not match source %zu"),
21501                          dst->nusbdevs, src->nusbdevs);
21502         return false;
21503     }
21504 
21505     for (i = 0; i < src->nusbdevs; i++) {
21506         virDomainRedirFilterUSBDevDef *srcUSBDev = src->usbdevs[i];
21507         virDomainRedirFilterUSBDevDef *dstUSBDev = dst->usbdevs[i];
21508         if (srcUSBDev->usbClass != dstUSBDev->usbClass) {
21509             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21510                            "%s", _("Target USB Class code does not match source"));
21511             return false;
21512         }
21513 
21514         if (srcUSBDev->vendor != dstUSBDev->vendor) {
21515             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21516                            "%s", _("Target USB vendor ID does not match source"));
21517             return false;
21518         }
21519 
21520         if (srcUSBDev->product != dstUSBDev->product) {
21521             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21522                            "%s", _("Target USB product ID does not match source"));
21523             return false;
21524         }
21525 
21526         if (srcUSBDev->version != dstUSBDev->version) {
21527             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21528                            "%s", _("Target USB version does not match source"));
21529             return false;
21530         }
21531 
21532         if (srcUSBDev->allow != dstUSBDev->allow) {
21533             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21534                            _("Target USB allow '%s' does not match source '%s'"),
21535                              dstUSBDev->allow ? "yes" : "no",
21536                              srcUSBDev->allow ? "yes" : "no");
21537             return false;
21538         }
21539     }
21540 
21541     return true;
21542 }
21543 
21544 
21545 static bool
virDomainDefFeaturesCheckABIStability(virDomainDef * src,virDomainDef * dst)21546 virDomainDefFeaturesCheckABIStability(virDomainDef *src,
21547                                       virDomainDef *dst)
21548 {
21549     size_t i;
21550 
21551     for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
21552         const char *featureName = virDomainFeatureTypeToString(i);
21553 
21554         switch ((virDomainFeature) i) {
21555         case VIR_DOMAIN_FEATURE_ACPI:
21556         case VIR_DOMAIN_FEATURE_PAE:
21557         case VIR_DOMAIN_FEATURE_HAP:
21558         case VIR_DOMAIN_FEATURE_VIRIDIAN:
21559         case VIR_DOMAIN_FEATURE_PRIVNET:
21560         case VIR_DOMAIN_FEATURE_HYPERV:
21561         case VIR_DOMAIN_FEATURE_KVM:
21562         case VIR_DOMAIN_FEATURE_XEN:
21563         case VIR_DOMAIN_FEATURE_PVSPINLOCK:
21564         case VIR_DOMAIN_FEATURE_PMU:
21565         case VIR_DOMAIN_FEATURE_VMPORT:
21566         case VIR_DOMAIN_FEATURE_SMM:
21567         case VIR_DOMAIN_FEATURE_VMCOREINFO:
21568         case VIR_DOMAIN_FEATURE_HTM:
21569         case VIR_DOMAIN_FEATURE_NESTED_HV:
21570         case VIR_DOMAIN_FEATURE_CCF_ASSIST:
21571             if (src->features[i] != dst->features[i]) {
21572                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21573                                _("State of feature '%s' differs: "
21574                                  "source: '%s', destination: '%s'"),
21575                                featureName,
21576                                virTristateSwitchTypeToString(src->features[i]),
21577                                virTristateSwitchTypeToString(dst->features[i]));
21578                 return false;
21579             }
21580             break;
21581 
21582         case VIR_DOMAIN_FEATURE_CAPABILITIES:
21583             if (src->features[i] != dst->features[i]) {
21584                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21585                                _("State of feature '%s' differs: "
21586                                  "source: '%s=%s', destination: '%s=%s'"),
21587                                featureName,
21588                                "policy",
21589                                virDomainCapabilitiesPolicyTypeToString(src->features[i]),
21590                                "policy",
21591                                virDomainCapabilitiesPolicyTypeToString(dst->features[i]));
21592                 return false;
21593             }
21594             break;
21595 
21596         case VIR_DOMAIN_FEATURE_GIC:
21597             if (src->features[i] != dst->features[i] ||
21598                 src->gic_version != dst->gic_version) {
21599                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21600                                _("State of feature '%s' differs: "
21601                                  "source: '%s,%s=%s', destination: '%s,%s=%s'"),
21602                                featureName,
21603                                virTristateSwitchTypeToString(src->features[i]),
21604                                "version", virGICVersionTypeToString(src->gic_version),
21605                                virTristateSwitchTypeToString(dst->features[i]),
21606                                "version", virGICVersionTypeToString(dst->gic_version));
21607                 return false;
21608             }
21609             break;
21610 
21611         case VIR_DOMAIN_FEATURE_HPT:
21612             if (src->features[i] != dst->features[i] ||
21613                 src->hpt_resizing != dst->hpt_resizing ||
21614                 src->hpt_maxpagesize != dst->hpt_maxpagesize) {
21615                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21616                                _("State of feature '%s' differs: "
21617                                  "source: '%s,%s=%s,%s=%llu', destination: '%s,%s=%s,%s=%llu'"),
21618                                featureName,
21619                                virTristateSwitchTypeToString(src->features[i]),
21620                                "resizing", virDomainHPTResizingTypeToString(src->hpt_resizing),
21621                                "maxpagesize", src->hpt_maxpagesize,
21622                                virTristateSwitchTypeToString(dst->features[i]),
21623                                "resizing", virDomainHPTResizingTypeToString(dst->hpt_resizing),
21624                                "maxpagesize", dst->hpt_maxpagesize);
21625                 return false;
21626             }
21627             break;
21628 
21629         case VIR_DOMAIN_FEATURE_APIC:
21630             if (src->features[i] != dst->features[i] ||
21631                 src->apic_eoi != dst->apic_eoi) {
21632                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21633                                _("State of feature '%s' differs: "
21634                                  "source: '%s,%s=%s', destination: '%s,%s=%s'"),
21635                                featureName,
21636                                virTristateSwitchTypeToString(src->features[i]),
21637                                "eoi", virTristateSwitchTypeToString(src->apic_eoi),
21638                                virTristateSwitchTypeToString(dst->features[i]),
21639                                "eoi", virTristateSwitchTypeToString(dst->apic_eoi));
21640                 return false;
21641             }
21642             break;
21643 
21644         case VIR_DOMAIN_FEATURE_IOAPIC:
21645             if (src->features[i] != dst->features[i]) {
21646                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21647                                _("State of feature '%s' differs: "
21648                                  "source: '%s=%s', destination: '%s=%s'"),
21649                                featureName,
21650                                "driver", virDomainIOAPICTypeToString(src->features[i]),
21651                                "driver", virDomainIOAPICTypeToString(dst->features[i]));
21652                 return false;
21653             }
21654             break;
21655 
21656         case VIR_DOMAIN_FEATURE_CFPC:
21657             if (src->features[i] != dst->features[i]) {
21658                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21659                                _("State of feature '%s' differs: "
21660                                  "source: '%s=%s', destination: '%s=%s'"),
21661                                featureName,
21662                                "value", virDomainCFPCTypeToString(src->features[i]),
21663                                "value", virDomainCFPCTypeToString(dst->features[i]));
21664                 return false;
21665             }
21666             break;
21667 
21668         case VIR_DOMAIN_FEATURE_SBBC:
21669             if (src->features[i] != dst->features[i]) {
21670                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21671                                _("State of feature '%s' differs: "
21672                                  "source: '%s=%s', destination: '%s=%s'"),
21673                                featureName,
21674                                "value", virDomainSBBCTypeToString(src->features[i]),
21675                                "value", virDomainSBBCTypeToString(dst->features[i]));
21676                 return false;
21677             }
21678             break;
21679 
21680         case VIR_DOMAIN_FEATURE_IBS:
21681             if (src->features[i] != dst->features[i]) {
21682                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21683                                _("State of feature '%s' differs: "
21684                                  "source: '%s=%s', destination: '%s=%s'"),
21685                                featureName,
21686                                "value", virDomainIBSTypeToString(src->features[i]),
21687                                "value", virDomainIBSTypeToString(dst->features[i]));
21688                 return false;
21689             }
21690             break;
21691 
21692         case VIR_DOMAIN_FEATURE_MSRS:
21693             break;
21694 
21695         case VIR_DOMAIN_FEATURE_LAST:
21696             break;
21697         }
21698     }
21699 
21700     /* hyperv */
21701     if (src->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_TRISTATE_SWITCH_ON) {
21702         for (i = 0; i < VIR_DOMAIN_HYPERV_LAST; i++) {
21703             switch ((virDomainHyperv) i) {
21704             case VIR_DOMAIN_HYPERV_RELAXED:
21705             case VIR_DOMAIN_HYPERV_VAPIC:
21706             case VIR_DOMAIN_HYPERV_VPINDEX:
21707             case VIR_DOMAIN_HYPERV_RUNTIME:
21708             case VIR_DOMAIN_HYPERV_SYNIC:
21709             case VIR_DOMAIN_HYPERV_STIMER:
21710             case VIR_DOMAIN_HYPERV_RESET:
21711             case VIR_DOMAIN_HYPERV_FREQUENCIES:
21712             case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
21713             case VIR_DOMAIN_HYPERV_TLBFLUSH:
21714             case VIR_DOMAIN_HYPERV_IPI:
21715             case VIR_DOMAIN_HYPERV_EVMCS:
21716                 if (src->hyperv_features[i] != dst->hyperv_features[i]) {
21717                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21718                                    _("State of HyperV enlightenment "
21719                                      "feature '%s' differs: "
21720                                      "source: '%s', destination: '%s'"),
21721                                    virDomainHypervTypeToString(i),
21722                                    virTristateSwitchTypeToString(src->hyperv_features[i]),
21723                                    virTristateSwitchTypeToString(dst->hyperv_features[i]));
21724                     return false;
21725                 }
21726 
21727                 break;
21728 
21729             case VIR_DOMAIN_HYPERV_SPINLOCKS:
21730                 /* spinlock count matters! */
21731                 if (src->hyperv_spinlocks != dst->hyperv_spinlocks) {
21732                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21733                                    _("HyperV spinlock retry count differs: "
21734                                      "source: '%u', destination: '%u'"),
21735                                    src->hyperv_spinlocks,
21736                                    dst->hyperv_spinlocks);
21737                     return false;
21738                 }
21739                 break;
21740 
21741             case VIR_DOMAIN_HYPERV_VENDOR_ID:
21742                 if (STRNEQ_NULLABLE(src->hyperv_vendor_id, dst->hyperv_vendor_id)) {
21743                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21744                                    _("HyperV vendor_id differs: "
21745                                      "source: '%s', destination: '%s'"),
21746                                    src->hyperv_vendor_id,
21747                                    dst->hyperv_vendor_id);
21748                     return false;
21749                 }
21750                 break;
21751 
21752             case VIR_DOMAIN_HYPERV_LAST:
21753                 break;
21754             }
21755         }
21756     }
21757 
21758     if (src->hyperv_features[VIR_DOMAIN_HYPERV_STIMER] == VIR_TRISTATE_SWITCH_ON) {
21759         if (src->hyperv_stimer_direct != dst->hyperv_stimer_direct) {
21760             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21761                            _("State of HyperV stimer direct feature differs: "
21762                              "source: '%s', destination: '%s'"),
21763                            virTristateSwitchTypeToString(src->hyperv_stimer_direct),
21764                            virTristateSwitchTypeToString(dst->hyperv_stimer_direct));
21765             return false;
21766         }
21767     }
21768 
21769     /* xen */
21770     if (src->features[VIR_DOMAIN_FEATURE_XEN] == VIR_TRISTATE_SWITCH_ON) {
21771         for (i = 0; i < VIR_DOMAIN_XEN_LAST; i++) {
21772             if (src->xen_features[i] != dst->xen_features[i]) {
21773                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21774                                _("State of Xen feature '%s' differs: "
21775                                  "source: '%s', destination: '%s'"),
21776                                virDomainXenTypeToString(i),
21777                                virTristateSwitchTypeToString(src->xen_features[i]),
21778                                virTristateSwitchTypeToString(dst->xen_features[i]));
21779                 return false;
21780             }
21781             switch ((virDomainXen) i) {
21782             case VIR_DOMAIN_XEN_E820_HOST:
21783                 break;
21784 
21785             case VIR_DOMAIN_XEN_PASSTHROUGH:
21786                 if (src->xen_passthrough_mode != dst->xen_passthrough_mode) {
21787                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21788                                    _("'mode' of Xen passthrough feature differs: "
21789                                      "source: '%s', destination: '%s'"),
21790                                    virDomainXenPassthroughModeTypeToString(src->xen_passthrough_mode),
21791                                    virDomainXenPassthroughModeTypeToString(dst->xen_passthrough_mode));
21792                     return false;
21793                 }
21794                 break;
21795 
21796             case VIR_DOMAIN_XEN_LAST:
21797                 break;
21798             }
21799         }
21800     }
21801 
21802     /* kvm */
21803     if (src->features[VIR_DOMAIN_FEATURE_KVM] == VIR_TRISTATE_SWITCH_ON) {
21804         for (i = 0; i < VIR_DOMAIN_KVM_LAST; i++) {
21805             switch ((virDomainKVM) i) {
21806             case VIR_DOMAIN_KVM_HIDDEN:
21807             case VIR_DOMAIN_KVM_DEDICATED:
21808             case VIR_DOMAIN_KVM_POLLCONTROL:
21809             case VIR_DOMAIN_KVM_PVIPI:
21810                 if (src->kvm_features[i] != dst->kvm_features[i]) {
21811                     virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21812                                    _("State of KVM feature '%s' differs: "
21813                                      "source: '%s', destination: '%s'"),
21814                                    virDomainKVMTypeToString(i),
21815                                    virTristateSwitchTypeToString(src->kvm_features[i]),
21816                                    virTristateSwitchTypeToString(dst->kvm_features[i]));
21817                     return false;
21818                 }
21819 
21820                 break;
21821 
21822             case VIR_DOMAIN_KVM_LAST:
21823                 break;
21824             }
21825         }
21826     }
21827 
21828     /* smm */
21829     if (src->features[VIR_DOMAIN_FEATURE_SMM] == VIR_TRISTATE_SWITCH_ON) {
21830         if (src->tseg_specified != dst->tseg_specified) {
21831             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21832                            _("SMM TSEG differs: source: %s, destination: '%s'"),
21833                            src->tseg_specified ? _("specified") : _("not specified"),
21834                            dst->tseg_specified ? _("specified") : _("not specified"));
21835             return false;
21836         }
21837 
21838         if (src->tseg_specified &&
21839             src->tseg_size != dst->tseg_size) {
21840             const char *unit_src, *unit_dst;
21841             unsigned long long short_size_src = virFormatIntPretty(src->tseg_size,
21842                                                                    &unit_src);
21843             unsigned long long short_size_dst = virFormatIntPretty(dst->tseg_size,
21844                                                                    &unit_dst);
21845 
21846             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21847                            _("Size of SMM TSEG size differs: "
21848                              "source: '%llu %s', destination: '%llu %s'"),
21849                            short_size_src, unit_src,
21850                            short_size_dst, unit_dst);
21851             return false;
21852         }
21853     }
21854 
21855     return true;
21856 }
21857 
21858 static bool
virDomainPanicDefCheckABIStability(virDomainPanicDef * src,virDomainPanicDef * dst)21859 virDomainPanicDefCheckABIStability(virDomainPanicDef *src,
21860                                    virDomainPanicDef *dst)
21861 {
21862     if (src->model != dst->model) {
21863         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21864                        _("Target panic model '%s' does not match source '%s'"),
21865                        virDomainPanicModelTypeToString(dst->model),
21866                        virDomainPanicModelTypeToString(src->model));
21867         return false;
21868     }
21869 
21870     return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
21871 }
21872 
21873 
21874 static bool
virDomainShmemDefCheckABIStability(virDomainShmemDef * src,virDomainShmemDef * dst)21875 virDomainShmemDefCheckABIStability(virDomainShmemDef *src,
21876                                    virDomainShmemDef *dst)
21877 {
21878     if (src->role != dst->role) {
21879         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21880                        _("Target shared memory role '%s' does not match "
21881                          "source role '%s'"),
21882                        virDomainShmemRoleTypeToString(dst->role),
21883                        virDomainShmemRoleTypeToString(src->role));
21884         return false;
21885     }
21886 
21887     if (src->model != dst->model) {
21888         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21889                        _("Target shared memory model '%s' does not match "
21890                          "source model '%s'"),
21891                        virDomainShmemModelTypeToString(dst->model),
21892                        virDomainShmemModelTypeToString(src->model));
21893         return false;
21894     }
21895 
21896     if (src->size != dst->size) {
21897         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21898                        _("Target shared memory size '%llu' does not match "
21899                          "source size '%llu'"), dst->size, src->size);
21900         return false;
21901     }
21902 
21903     if (src->server.enabled != dst->server.enabled) {
21904         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21905                        _("Target shared memory server usage doesn't match "
21906                          "source"));
21907         return false;
21908     }
21909 
21910     if (src->msi.vectors != dst->msi.vectors ||
21911         src->msi.enabled != dst->msi.enabled ||
21912         src->msi.ioeventfd != dst->msi.ioeventfd) {
21913         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21914                        _("Target shared memory MSI configuration doesn't match "
21915                          "source"));
21916         return false;
21917     }
21918 
21919     return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
21920 }
21921 
21922 
21923 static bool
virDomainTPMDefCheckABIStability(virDomainTPMDef * src,virDomainTPMDef * dst)21924 virDomainTPMDefCheckABIStability(virDomainTPMDef *src,
21925                                  virDomainTPMDef *dst)
21926 {
21927     if (src->type != dst->type) {
21928         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21929                        _("Target TPM device type doesn't match source"));
21930         return false;
21931     }
21932 
21933     if (src->model != dst->model) {
21934         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21935                        _("Target TPM device model doesn't match source"));
21936         return false;
21937     }
21938 
21939     if (src->version != dst->version) {
21940         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
21941                        _("Target TPM version doesn't match source"));
21942         return false;
21943     }
21944 
21945     return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
21946 }
21947 
21948 
21949 static bool
virDomainMemtuneCheckABIStability(const virDomainDef * src,const virDomainDef * dst,unsigned int flags)21950 virDomainMemtuneCheckABIStability(const virDomainDef *src,
21951                                   const virDomainDef *dst,
21952                                   unsigned int flags)
21953 {
21954     if (virDomainDefGetMemoryInitial(src) != virDomainDefGetMemoryInitial(dst)) {
21955         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21956                        _("Target domain max memory %lld "
21957                          "does not match source %lld"),
21958                        virDomainDefGetMemoryInitial(dst),
21959                        virDomainDefGetMemoryInitial(src));
21960         return false;
21961     }
21962 
21963     if (!(flags & VIR_DOMAIN_DEF_ABI_CHECK_SKIP_VOLATILE) &&
21964         src->mem.cur_balloon != dst->mem.cur_balloon) {
21965         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21966                        _("Target domain current memory %lld "
21967                          "does not match source %lld"),
21968                        dst->mem.cur_balloon,
21969                        src->mem.cur_balloon);
21970         return false;
21971     }
21972 
21973     if (src->mem.max_memory != dst->mem.max_memory) {
21974         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21975                        _("Target maximum memory size '%llu' "
21976                          "doesn't match source '%llu'"),
21977                        dst->mem.max_memory,
21978                        src->mem.max_memory);
21979         return false;
21980     }
21981 
21982     if (src->mem.memory_slots != dst->mem.memory_slots) {
21983         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
21984                        _("Target domain memory slots "
21985                          "count '%u' doesn't match source '%u'"),
21986                        dst->mem.memory_slots,
21987                        src->mem.memory_slots);
21988         return false;
21989     }
21990 
21991     return true;
21992 }
21993 
21994 
21995 static bool
virDomainMemoryDefCheckABIStability(virDomainMemoryDef * src,virDomainMemoryDef * dst)21996 virDomainMemoryDefCheckABIStability(virDomainMemoryDef *src,
21997                                     virDomainMemoryDef *dst)
21998 {
21999     if (src->model != dst->model) {
22000         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22001                        _("Target memory device model '%s' "
22002                          "doesn't match source model '%s'"),
22003                        virDomainMemoryModelTypeToString(dst->model),
22004                        virDomainMemoryModelTypeToString(src->model));
22005         return false;
22006     }
22007 
22008     if (src->targetNode != dst->targetNode) {
22009         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22010                        _("Target memory device targetNode '%d' "
22011                          "doesn't match source targetNode '%d'"),
22012                        dst->targetNode, src->targetNode);
22013         return false;
22014     }
22015 
22016     if (src->size != dst->size) {
22017         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22018                        _("Target memory device size '%llu' doesn't match "
22019                          "source memory device size '%llu'"),
22020                        dst->size, src->size);
22021         return false;
22022     }
22023 
22024     if (src->blocksize != dst->blocksize) {
22025         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22026                        _("Target memory device block size '%llu' doesn't match "
22027                          "source memory device block size '%llu'"),
22028                        dst->blocksize, src->blocksize);
22029         return false;
22030     }
22031 
22032     if (src->requestedsize != dst->requestedsize) {
22033         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22034                        _("Target memory device requested size '%llu' doesn't match "
22035                          "source memory device requested size '%llu'"),
22036                        dst->requestedsize, src->requestedsize);
22037         return false;
22038     }
22039 
22040     if (src->model == VIR_DOMAIN_MEMORY_MODEL_NVDIMM) {
22041         if (src->labelsize != dst->labelsize) {
22042             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22043                            _("Target NVDIMM label size '%llu' doesn't match "
22044                              "source NVDIMM label size '%llu'"),
22045                            src->labelsize, dst->labelsize);
22046             return false;
22047         }
22048 
22049         if (src->alignsize != dst->alignsize) {
22050             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22051                            _("Target NVDIMM alignment '%llu' doesn't match "
22052                              "source NVDIMM alignment '%llu'"),
22053                            src->alignsize, dst->alignsize);
22054             return false;
22055         }
22056 
22057         if (src->nvdimmPmem != dst->nvdimmPmem) {
22058             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22059                            _("Target NVDIMM pmem flag doesn't match "
22060                              "source NVDIMM pmem flag"));
22061             return false;
22062         }
22063 
22064         if (src->readonly != dst->readonly) {
22065             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22066                            _("Target NVDIMM readonly flag doesn't match "
22067                              "source NVDIMM readonly flag"));
22068             return false;
22069         }
22070 
22071         if ((src->uuid || dst->uuid) &&
22072             !(src->uuid && dst->uuid &&
22073               memcmp(src->uuid, dst->uuid, VIR_UUID_BUFLEN) == 0)) {
22074             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22075                            _("Target NVDIMM UUID doesn't match source NVDIMM"));
22076             return false;
22077         }
22078     }
22079 
22080     return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
22081 }
22082 
22083 
22084 static bool
virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef * src,virDomainIOMMUDef * dst)22085 virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src,
22086                                    virDomainIOMMUDef *dst)
22087 {
22088     if (src->model != dst->model) {
22089         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22090                        _("Target domain IOMMU device model '%s' "
22091                          "does not match source '%s'"),
22092                        virDomainIOMMUModelTypeToString(dst->model),
22093                        virDomainIOMMUModelTypeToString(src->model));
22094         return false;
22095     }
22096     if (src->intremap != dst->intremap) {
22097         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22098                        _("Target domain IOMMU device intremap value '%s' "
22099                          "does not match source '%s'"),
22100                        virTristateSwitchTypeToString(dst->intremap),
22101                        virTristateSwitchTypeToString(src->intremap));
22102         return false;
22103     }
22104     if (src->caching_mode != dst->caching_mode) {
22105         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22106                        _("Target domain IOMMU device caching mode '%s' "
22107                          "does not match source '%s'"),
22108                        virTristateSwitchTypeToString(dst->caching_mode),
22109                        virTristateSwitchTypeToString(src->caching_mode));
22110         return false;
22111     }
22112     if (src->eim != dst->eim) {
22113         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22114                        _("Target domain IOMMU device eim value '%s' "
22115                          "does not match source '%s'"),
22116                        virTristateSwitchTypeToString(dst->eim),
22117                        virTristateSwitchTypeToString(src->eim));
22118         return false;
22119     }
22120     if (src->iotlb != dst->iotlb) {
22121         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22122                        _("Target domain IOMMU device iotlb value '%s' "
22123                          "does not match source '%s'"),
22124                        virTristateSwitchTypeToString(dst->iotlb),
22125                        virTristateSwitchTypeToString(src->iotlb));
22126         return false;
22127     }
22128     if (src->aw_bits != dst->aw_bits) {
22129         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22130                        _("Target domain IOMMU device aw_bits value '%d' "
22131                          "does not match source '%d'"),
22132                        dst->aw_bits, src->aw_bits);
22133         return false;
22134     }
22135 
22136     return true;
22137 }
22138 
22139 
22140 static bool
virDomainVsockDefCheckABIStability(virDomainVsockDef * src,virDomainVsockDef * dst)22141 virDomainVsockDefCheckABIStability(virDomainVsockDef *src,
22142                                    virDomainVsockDef *dst)
22143 {
22144     if (src->model != dst->model) {
22145         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22146                        _("Target domain vsock device model '%s' "
22147                          "does not match source '%s'"),
22148                        virDomainVsockModelTypeToString(dst->model),
22149                        virDomainVsockModelTypeToString(src->model));
22150         return false;
22151     }
22152 
22153     if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
22154         return false;
22155 
22156     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
22157         return false;
22158 
22159     return true;
22160 }
22161 
22162 
22163 static bool
virDomainDefVcpuCheckAbiStability(virDomainDef * src,virDomainDef * dst)22164 virDomainDefVcpuCheckAbiStability(virDomainDef *src,
22165                                   virDomainDef *dst)
22166 {
22167     size_t i;
22168 
22169     if (src->maxvcpus != dst->maxvcpus) {
22170         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22171                        _("Target domain vCPU max %zu does not match source %zu"),
22172                        dst->maxvcpus, src->maxvcpus);
22173         return false;
22174     }
22175 
22176     for (i = 0; i < src->maxvcpus; i++) {
22177         virDomainVcpuDef *svcpu = src->vcpus[i];
22178         virDomainVcpuDef *dvcpu = dst->vcpus[i];
22179 
22180         if (svcpu->online != dvcpu->online) {
22181             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22182                            _("State of vCPU '%zu' differs between source and "
22183                              "destination definitions"), i);
22184             return false;
22185         }
22186 
22187         if (svcpu->order != dvcpu->order) {
22188             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22189                            _("vcpu enable order of vCPU '%zu' differs between "
22190                              "source and destination definitions"), i);
22191             return false;
22192         }
22193     }
22194 
22195     return true;
22196 }
22197 
22198 
22199 /* This compares two configurations and looks for any differences
22200  * which will affect the guest ABI. This is primarily to allow
22201  * validation of custom XML config passed in during migration
22202  */
22203 bool
virDomainDefCheckABIStabilityFlags(virDomainDef * src,virDomainDef * dst,virDomainXMLOption * xmlopt,unsigned int flags)22204 virDomainDefCheckABIStabilityFlags(virDomainDef *src,
22205                                    virDomainDef *dst,
22206                                    virDomainXMLOption *xmlopt,
22207                                    unsigned int flags)
22208 {
22209     size_t i;
22210     virErrorPtr err;
22211     g_autofree char *strSrc = NULL;
22212     g_autofree char *strDst = NULL;
22213 
22214     if (src->virtType != dst->virtType) {
22215         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22216                        _("Target domain virt type %s does not match source %s"),
22217                        virDomainVirtTypeToString(dst->virtType),
22218                        virDomainVirtTypeToString(src->virtType));
22219         goto error;
22220     }
22221 
22222     if (memcmp(src->uuid, dst->uuid, VIR_UUID_BUFLEN) != 0) {
22223         char uuidsrc[VIR_UUID_STRING_BUFLEN];
22224         char uuiddst[VIR_UUID_STRING_BUFLEN];
22225         virUUIDFormat(src->uuid, uuidsrc);
22226         virUUIDFormat(dst->uuid, uuiddst);
22227         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22228                        _("Target domain uuid %s does not match source %s"),
22229                        uuiddst, uuidsrc);
22230         goto error;
22231     }
22232 
22233     if (src->genidRequested != dst->genidRequested) {
22234         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22235                        _("Target domain requested genid does not match source"));
22236         goto error;
22237     }
22238 
22239     if (src->genidRequested &&
22240         memcmp(src->genid, dst->genid, VIR_UUID_BUFLEN) != 0) {
22241         char guidsrc[VIR_UUID_STRING_BUFLEN];
22242         char guiddst[VIR_UUID_STRING_BUFLEN];
22243 
22244         virUUIDFormat(src->genid, guidsrc);
22245         virUUIDFormat(dst->genid, guiddst);
22246         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22247                        _("Target domain genid %s does not match source %s"),
22248                        guiddst, guidsrc);
22249         goto error;
22250     }
22251 
22252     /* Not strictly ABI related, but we want to make sure domains
22253      * don't get silently re-named through the backdoor when passing
22254      * custom XML into various APIs, since this would create havoc
22255      */
22256     if (STRNEQ_NULLABLE(src->name, dst->name)) {
22257         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22258                        _("Target domain name '%s' does not match source '%s'"),
22259                        dst->name, src->name);
22260         goto error;
22261     }
22262 
22263     if (!virDomainMemtuneCheckABIStability(src, dst, flags))
22264         goto error;
22265 
22266     if (!virDomainNumaCheckABIStability(src->numa, dst->numa))
22267         goto error;
22268 
22269     if (!virDomainDefVcpuCheckAbiStability(src, dst))
22270         goto error;
22271 
22272     if (src->os.type != dst->os.type) {
22273         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22274                        _("Target domain OS type %s does not match source %s"),
22275                        virDomainOSTypeToString(dst->os.type),
22276                        virDomainOSTypeToString(src->os.type));
22277         goto error;
22278     }
22279     if (src->os.arch != dst->os.arch) {
22280         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22281                        _("Target domain architecture %s does not match source %s"),
22282                        virArchToString(dst->os.arch),
22283                        virArchToString(src->os.arch));
22284         goto error;
22285     }
22286     if (STRNEQ_NULLABLE(src->os.machine, dst->os.machine)) {
22287         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22288                     _("Target domain machine type %s does not match source %s"),
22289                     dst->os.machine, src->os.machine);
22290         goto error;
22291     }
22292 
22293     if (src->os.smbios_mode != dst->os.smbios_mode) {
22294         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22295                        _("Target domain SMBIOS mode %s does not match source %s"),
22296                        virDomainSmbiosModeTypeToString(dst->os.smbios_mode),
22297                        virDomainSmbiosModeTypeToString(src->os.smbios_mode));
22298         goto error;
22299     }
22300 
22301     if (!virDomainDefFeaturesCheckABIStability(src, dst))
22302         goto error;
22303 
22304     if (src->clock.ntimers != dst->clock.ntimers) {
22305         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22306                        _("Target domain timers do not match source"));
22307         goto error;
22308     }
22309 
22310     for (i = 0; i < src->clock.ntimers; i++) {
22311         if (!virDomainTimerDefCheckABIStability(src->clock.timers[i],
22312                                                 dst->clock.timers[i]))
22313             goto error;
22314     }
22315 
22316     if (!virCPUDefIsEqual(src->cpu, dst->cpu, true))
22317         goto error;
22318 
22319     if (src->nsysinfo != dst->nsysinfo) {
22320         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22321                        _("Target domain count of sysinfo does not match source"));
22322             goto error;
22323     }
22324 
22325     for (i = 0; i < src->nsysinfo; i++) {
22326         if (!virSysinfoIsEqual(src->sysinfo[i], dst->sysinfo[i]))
22327             goto error;
22328     }
22329 
22330     if (src->ndisks != dst->ndisks) {
22331         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22332                        _("Target domain disk count %zu does not match source %zu"),
22333                        dst->ndisks, src->ndisks);
22334         goto error;
22335     }
22336 
22337     for (i = 0; i < src->ndisks; i++)
22338         if (!virDomainDiskDefCheckABIStability(src->disks[i], dst->disks[i]))
22339             goto error;
22340 
22341     if (src->ncontrollers != dst->ncontrollers) {
22342         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22343                        _("Target domain controller count %zu "
22344                          "does not match source %zu"),
22345                        dst->ncontrollers, src->ncontrollers);
22346         goto error;
22347     }
22348 
22349     for (i = 0; i < src->ncontrollers; i++)
22350         if (!virDomainControllerDefCheckABIStability(src->controllers[i],
22351                                                      dst->controllers[i]))
22352             goto error;
22353 
22354     if (src->nfss != dst->nfss) {
22355         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22356                        _("Target domain filesystem count %zu "
22357                          "does not match source %zu"),
22358                        dst->nfss, src->nfss);
22359         goto error;
22360     }
22361 
22362     for (i = 0; i < src->nfss; i++)
22363         if (!virDomainFsDefCheckABIStability(src->fss[i], dst->fss[i]))
22364             goto error;
22365 
22366     if (src->nnets != dst->nnets) {
22367         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22368                        _("Target domain net card count %zu "
22369                          "does not match source %zu"),
22370                        dst->nnets, src->nnets);
22371         goto error;
22372     }
22373 
22374     for (i = 0; i < src->nnets; i++)
22375         if (!virDomainNetDefCheckABIStability(src->nets[i], dst->nets[i]))
22376             goto error;
22377 
22378     if (src->ninputs != dst->ninputs) {
22379         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22380                        _("Target domain input device count %zu "
22381                          "does not match source %zu"),
22382                        dst->ninputs, src->ninputs);
22383         goto error;
22384     }
22385 
22386     for (i = 0; i < src->ninputs; i++)
22387         if (!virDomainInputDefCheckABIStability(src->inputs[i], dst->inputs[i]))
22388             goto error;
22389 
22390     if (src->nsounds != dst->nsounds) {
22391         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22392                        _("Target domain sound card count %zu "
22393                          "does not match source %zu"),
22394                        dst->nsounds, src->nsounds);
22395         goto error;
22396     }
22397 
22398     for (i = 0; i < src->nsounds; i++)
22399         if (!virDomainSoundDefCheckABIStability(src->sounds[i], dst->sounds[i]))
22400             goto error;
22401 
22402     if (src->nvideos != dst->nvideos) {
22403         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22404                        _("Target domain video card count %zu "
22405                          "does not match source %zu"),
22406                        dst->nvideos, src->nvideos);
22407         goto error;
22408     }
22409 
22410     for (i = 0; i < src->nvideos; i++)
22411         if (!virDomainVideoDefCheckABIStability(src->videos[i], dst->videos[i]))
22412             goto error;
22413 
22414     if (src->nhostdevs != dst->nhostdevs) {
22415         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22416                        _("Target domain host device count %zu "
22417                          "does not match source %zu"),
22418                        dst->nhostdevs, src->nhostdevs);
22419         goto error;
22420     }
22421 
22422     for (i = 0; i < src->nhostdevs; i++)
22423         if (!virDomainHostdevDefCheckABIStability(src->hostdevs[i],
22424                                                   dst->hostdevs[i]))
22425             goto error;
22426 
22427     if (src->nsmartcards != dst->nsmartcards) {
22428         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22429                        _("Target domain smartcard count %zu "
22430                          "does not match source %zu"),
22431                        dst->nsmartcards, src->nsmartcards);
22432         goto error;
22433     }
22434 
22435     for (i = 0; i < src->nsmartcards; i++)
22436         if (!virDomainSmartcardDefCheckABIStability(src->smartcards[i],
22437                                                     dst->smartcards[i]))
22438             goto error;
22439 
22440     if (src->nserials != dst->nserials) {
22441         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22442                        _("Target domain serial port count %zu "
22443                          "does not match source %zu"),
22444                        dst->nserials, src->nserials);
22445         goto error;
22446     }
22447 
22448     for (i = 0; i < src->nserials; i++)
22449         if (!virDomainSerialDefCheckABIStability(src->serials[i],
22450                                                  dst->serials[i]))
22451             goto error;
22452 
22453     if (src->nparallels != dst->nparallels) {
22454         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22455                        _("Target domain parallel port count %zu "
22456                          "does not match source %zu"),
22457                        dst->nparallels, src->nparallels);
22458         goto error;
22459     }
22460 
22461     for (i = 0; i < src->nparallels; i++)
22462         if (!virDomainParallelDefCheckABIStability(src->parallels[i],
22463                                                    dst->parallels[i]))
22464             goto error;
22465 
22466     if (src->nchannels != dst->nchannels) {
22467         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22468                        _("Target domain channel count %zu "
22469                          "does not match source %zu"),
22470                        dst->nchannels, src->nchannels);
22471         goto error;
22472     }
22473 
22474     for (i = 0; i < src->nchannels; i++)
22475         if (!virDomainChannelDefCheckABIStability(src->channels[i],
22476                                                   dst->channels[i]))
22477             goto error;
22478 
22479     if (src->nconsoles != dst->nconsoles) {
22480         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22481                        _("Target domain console count %zu "
22482                          "does not match source %zu"),
22483                        dst->nconsoles, src->nconsoles);
22484         goto error;
22485     }
22486 
22487     for (i = 0; i < src->nconsoles; i++)
22488         if (!virDomainConsoleDefCheckABIStability(src->consoles[i],
22489                                                   dst->consoles[i]))
22490             goto error;
22491 
22492     if (src->nhubs != dst->nhubs) {
22493         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22494                        _("Target domain hub device count %zu "
22495                          "does not match source %zu"),
22496                        dst->nhubs, src->nhubs);
22497         goto error;
22498     }
22499 
22500     for (i = 0; i < src->nhubs; i++)
22501         if (!virDomainHubDefCheckABIStability(src->hubs[i], dst->hubs[i]))
22502             goto error;
22503 
22504     if (src->nredirdevs != dst->nredirdevs) {
22505         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22506                        _("Target domain redirected devices count %zu "
22507                          "does not match source %zu"),
22508                        dst->nredirdevs, src->nredirdevs);
22509         goto error;
22510     }
22511 
22512     for (i = 0; i < src->nredirdevs; i++) {
22513         if (!virDomainRedirdevDefCheckABIStability(src->redirdevs[i],
22514                                                    dst->redirdevs[i]))
22515             goto error;
22516     }
22517 
22518     if ((!src->redirfilter && dst->redirfilter) ||
22519         (src->redirfilter && !dst->redirfilter)) {
22520         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22521                        _("Target domain USB redirection filter count %d "
22522                          "does not match source %d"),
22523                        dst->redirfilter ? 1 : 0, src->redirfilter ? 1 : 0);
22524         goto error;
22525     }
22526 
22527     if (src->redirfilter &&
22528         !virDomainRedirFilterDefCheckABIStability(src->redirfilter,
22529                                                   dst->redirfilter))
22530         goto error;
22531 
22532     if ((!src->watchdog && dst->watchdog) ||
22533         (src->watchdog && !dst->watchdog)) {
22534         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22535                        _("Target domain watchdog count %d "
22536                          "does not match source %d"),
22537                        dst->watchdog ? 1 : 0, src->watchdog ? 1 : 0);
22538         goto error;
22539     }
22540 
22541     if (src->watchdog &&
22542         !virDomainWatchdogDefCheckABIStability(src->watchdog, dst->watchdog))
22543         goto error;
22544 
22545     if ((!src->memballoon && dst->memballoon) ||
22546         (src->memballoon && !dst->memballoon)) {
22547         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22548                        _("Target domain memory balloon count %d "
22549                          "does not match source %d"),
22550                        dst->memballoon ? 1 : 0, src->memballoon ? 1 : 0);
22551         goto error;
22552     }
22553 
22554     if (src->memballoon &&
22555         !virDomainMemballoonDefCheckABIStability(src->memballoon,
22556                                                  dst->memballoon))
22557         goto error;
22558 
22559     if (src->nrngs != dst->nrngs) {
22560         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22561                        _("Target domain RNG device count %zu "
22562                          "does not match source %zu"), dst->nrngs, src->nrngs);
22563         goto error;
22564     }
22565 
22566     for (i = 0; i < src->nrngs; i++)
22567         if (!virDomainRNGDefCheckABIStability(src->rngs[i], dst->rngs[i]))
22568             goto error;
22569 
22570     if (src->npanics != dst->npanics) {
22571         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22572                        _("Target domain panic device count %zu "
22573                          "does not match source %zu"), dst->npanics, src->npanics);
22574         goto error;
22575     }
22576 
22577     for (i = 0; i < src->npanics; i++) {
22578         if (!virDomainPanicDefCheckABIStability(src->panics[i], dst->panics[i]))
22579             goto error;
22580     }
22581 
22582     if (src->nshmems != dst->nshmems) {
22583         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22584                        _("Target domain shared memory device count %zu "
22585                          "does not match source %zu"), dst->nshmems, src->nshmems);
22586         goto error;
22587     }
22588 
22589     for (i = 0; i < src->nshmems; i++) {
22590         if (!virDomainShmemDefCheckABIStability(src->shmems[i], dst->shmems[i]))
22591             goto error;
22592     }
22593 
22594     if (src->ntpms != dst->ntpms) {
22595         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22596                        _("Target domain TPM device count %zu "
22597                          "does not match source %zu"),
22598                        dst->ntpms, src->ntpms);
22599         goto error;
22600     }
22601 
22602     for (i = 0; i < src->ntpms; i++) {
22603         if (!virDomainTPMDefCheckABIStability(src->tpms[i], dst->tpms[i]))
22604             goto error;
22605     }
22606 
22607     if (src->nmems != dst->nmems) {
22608         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
22609                        _("Target domain memory device count %zu "
22610                          "does not match source %zu"), dst->nmems, src->nmems);
22611         goto error;
22612     }
22613 
22614     for (i = 0; i < src->nmems; i++) {
22615         if (!virDomainMemoryDefCheckABIStability(src->mems[i], dst->mems[i]))
22616             goto error;
22617     }
22618 
22619     if (!!src->iommu != !!dst->iommu) {
22620         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22621                        _("Target domain IOMMU device count "
22622                          "does not match source"));
22623         goto error;
22624     }
22625 
22626     if (src->iommu &&
22627         !virDomainIOMMUDefCheckABIStability(src->iommu, dst->iommu))
22628         goto error;
22629 
22630     if (!!src->vsock != !!dst->vsock) {
22631         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
22632                        _("Target domain vsock device count "
22633                          "does not match source"));
22634         goto error;
22635     }
22636 
22637     if (src->vsock &&
22638         !virDomainVsockDefCheckABIStability(src->vsock, dst->vsock))
22639         goto error;
22640 
22641     if (xmlopt && xmlopt->abi.domain &&
22642         !xmlopt->abi.domain(src, dst))
22643         goto error;
22644 
22645     /* Coverity is not very happy with this - all dead_error_condition */
22646 #if !STATIC_ANALYSIS
22647     /* This switch statement is here to trigger compiler warning when adding
22648      * a new device type. When you are adding a new field to the switch you
22649      * also have to add an check above. Otherwise the switch statement has no
22650      * real function here and should be optimized out by the compiler. */
22651     i = VIR_DOMAIN_DEVICE_LAST;
22652     switch ((virDomainDeviceType) i) {
22653     case VIR_DOMAIN_DEVICE_DISK:
22654     case VIR_DOMAIN_DEVICE_LEASE:
22655     case VIR_DOMAIN_DEVICE_FS:
22656     case VIR_DOMAIN_DEVICE_NET:
22657     case VIR_DOMAIN_DEVICE_INPUT:
22658     case VIR_DOMAIN_DEVICE_SOUND:
22659     case VIR_DOMAIN_DEVICE_VIDEO:
22660     case VIR_DOMAIN_DEVICE_HOSTDEV:
22661     case VIR_DOMAIN_DEVICE_WATCHDOG:
22662     case VIR_DOMAIN_DEVICE_CONTROLLER:
22663     case VIR_DOMAIN_DEVICE_GRAPHICS:
22664     case VIR_DOMAIN_DEVICE_HUB:
22665     case VIR_DOMAIN_DEVICE_REDIRDEV:
22666     case VIR_DOMAIN_DEVICE_NONE:
22667     case VIR_DOMAIN_DEVICE_SMARTCARD:
22668     case VIR_DOMAIN_DEVICE_CHR:
22669     case VIR_DOMAIN_DEVICE_MEMBALLOON:
22670     case VIR_DOMAIN_DEVICE_NVRAM:
22671     case VIR_DOMAIN_DEVICE_LAST:
22672     case VIR_DOMAIN_DEVICE_RNG:
22673     case VIR_DOMAIN_DEVICE_TPM:
22674     case VIR_DOMAIN_DEVICE_PANIC:
22675     case VIR_DOMAIN_DEVICE_SHMEM:
22676     case VIR_DOMAIN_DEVICE_MEMORY:
22677     case VIR_DOMAIN_DEVICE_IOMMU:
22678     case VIR_DOMAIN_DEVICE_VSOCK:
22679     case VIR_DOMAIN_DEVICE_AUDIO:
22680         break;
22681     }
22682 #endif
22683 
22684     return true;
22685 
22686  error:
22687     virErrorPreserveLast(&err);
22688 
22689     strSrc = virDomainDefFormat(src, xmlopt, 0);
22690     strDst = virDomainDefFormat(dst, xmlopt, 0);
22691     VIR_DEBUG("XMLs that failed stability check were: src=\"%s\", dst=\"%s\"",
22692               NULLSTR(strSrc), NULLSTR(strDst));
22693 
22694     virErrorRestore(&err);
22695     return false;
22696 }
22697 
22698 
22699 bool
virDomainDefCheckABIStability(virDomainDef * src,virDomainDef * dst,virDomainXMLOption * xmlopt)22700 virDomainDefCheckABIStability(virDomainDef *src,
22701                               virDomainDef *dst,
22702                               virDomainXMLOption *xmlopt)
22703 {
22704     return virDomainDefCheckABIStabilityFlags(src, dst, xmlopt, 0);
22705 }
22706 
22707 
22708 static int
virDomainDefAddDiskControllersForType(virDomainDef * def,int controllerType,int diskBus)22709 virDomainDefAddDiskControllersForType(virDomainDef *def,
22710                                       int controllerType,
22711                                       int diskBus)
22712 {
22713     size_t i;
22714     int maxController = -1;
22715 
22716     for (i = 0; i < def->ndisks; i++) {
22717         if (def->disks[i]->bus != diskBus)
22718             continue;
22719 
22720         if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
22721             continue;
22722 
22723         if ((int)def->disks[i]->info.addr.drive.controller > maxController)
22724             maxController = def->disks[i]->info.addr.drive.controller;
22725     }
22726 
22727     if (maxController == -1)
22728         return 0;
22729 
22730     for (i = 0; i <= maxController; i++) {
22731         if (virDomainDefMaybeAddController(def, controllerType, i, -1) < 0)
22732             return -1;
22733     }
22734 
22735     return 0;
22736 }
22737 
22738 
22739 static int
virDomainDefMaybeAddVirtioSerialController(virDomainDef * def)22740 virDomainDefMaybeAddVirtioSerialController(virDomainDef *def)
22741 {
22742     /* Look for any virtio serial or virtio console devs */
22743     size_t i;
22744 
22745     for (i = 0; i < def->nchannels; i++) {
22746         virDomainChrDef *channel = def->channels[i];
22747 
22748         if (channel->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
22749             int idx = 0;
22750             if (channel->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL)
22751                 idx = channel->info.addr.vioserial.controller;
22752 
22753             if (virDomainDefMaybeAddController(def,
22754                 VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, idx, -1) < 0)
22755                 return -1;
22756         }
22757     }
22758 
22759     for (i = 0; i < def->nconsoles; i++) {
22760         virDomainChrDef *console = def->consoles[i];
22761 
22762         if (console->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) {
22763             int idx = 0;
22764             if (console->info.type ==
22765                 VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL)
22766                 idx = console->info.addr.vioserial.controller;
22767 
22768             if (virDomainDefMaybeAddController(def,
22769                 VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, idx, -1) < 0)
22770                 return -1;
22771         }
22772     }
22773 
22774     return 0;
22775 }
22776 
22777 
22778 static int
virDomainDefMaybeAddSmartcardController(virDomainDef * def)22779 virDomainDefMaybeAddSmartcardController(virDomainDef *def)
22780 {
22781     /* Look for any smartcard devs */
22782     size_t i;
22783 
22784     for (i = 0; i < def->nsmartcards; i++) {
22785         virDomainSmartcardDef *smartcard = def->smartcards[i];
22786         int idx = 0;
22787 
22788         if (smartcard->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID) {
22789             idx = smartcard->info.addr.ccid.controller;
22790         } else if (smartcard->info.type
22791                    == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
22792             size_t j;
22793             int max = -1;
22794 
22795             for (j = 0; j < def->nsmartcards; j++) {
22796                 virDomainDeviceInfo *info = &def->smartcards[j]->info;
22797                 if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID &&
22798                     info->addr.ccid.controller == 0 &&
22799                     (int) info->addr.ccid.slot > max)
22800                     max = info->addr.ccid.slot;
22801             }
22802             smartcard->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID;
22803             smartcard->info.addr.ccid.controller = 0;
22804             smartcard->info.addr.ccid.slot = max + 1;
22805         }
22806 
22807         if (virDomainDefMaybeAddController(def,
22808                                            VIR_DOMAIN_CONTROLLER_TYPE_CCID,
22809                                            idx, -1) < 0)
22810             return -1;
22811     }
22812 
22813     return 0;
22814 }
22815 
22816 /*
22817  * Based on the declared <address/> info for any devices,
22818  * add necessary drive controllers which are not already present
22819  * in the XML. This is for compat with existing apps which will
22820  * not know/care about <controller> info in the XML
22821  */
22822 static int
virDomainDefAddImplicitControllers(virDomainDef * def)22823 virDomainDefAddImplicitControllers(virDomainDef *def)
22824 {
22825     if (virDomainDefAddDiskControllersForType(def,
22826                                               VIR_DOMAIN_CONTROLLER_TYPE_SCSI,
22827                                               VIR_DOMAIN_DISK_BUS_SCSI) < 0)
22828         return -1;
22829 
22830     if (virDomainDefAddDiskControllersForType(def,
22831                                               VIR_DOMAIN_CONTROLLER_TYPE_FDC,
22832                                               VIR_DOMAIN_DISK_BUS_FDC) < 0)
22833         return -1;
22834 
22835     if (virDomainDefAddDiskControllersForType(def,
22836                                               VIR_DOMAIN_CONTROLLER_TYPE_IDE,
22837                                               VIR_DOMAIN_DISK_BUS_IDE) < 0)
22838         return -1;
22839 
22840     if (virDomainDefAddDiskControllersForType(def,
22841                                               VIR_DOMAIN_CONTROLLER_TYPE_SATA,
22842                                               VIR_DOMAIN_DISK_BUS_SATA) < 0)
22843         return -1;
22844 
22845     if (virDomainDefMaybeAddVirtioSerialController(def) < 0)
22846         return -1;
22847 
22848     if (virDomainDefMaybeAddSmartcardController(def) < 0)
22849         return -1;
22850 
22851     if (virDomainDefMaybeAddHostdevSCSIcontroller(def) < 0)
22852         return -1;
22853 
22854     return 0;
22855 }
22856 
22857 static int
virDomainDefAddImplicitVideo(virDomainDef * def,virDomainXMLOption * xmlopt)22858 virDomainDefAddImplicitVideo(virDomainDef *def, virDomainXMLOption *xmlopt)
22859 {
22860     g_autoptr(virDomainVideoDef) video = NULL;
22861 
22862     /* For backwards compatibility, if no <video> tag is set but there
22863      * is a <graphics> tag, then we add a single video tag */
22864     if (def->ngraphics == 0 || def->nvideos > 0)
22865         return 0;
22866 
22867     if (!(video = virDomainVideoDefNew(xmlopt)))
22868         return -1;
22869     video->type = VIR_DOMAIN_VIDEO_TYPE_DEFAULT;
22870     VIR_APPEND_ELEMENT(def->videos, def->nvideos, video);
22871 
22872     return 0;
22873 }
22874 
22875 int
virDomainDefAddImplicitDevices(virDomainDef * def,virDomainXMLOption * xmlopt)22876 virDomainDefAddImplicitDevices(virDomainDef *def, virDomainXMLOption *xmlopt)
22877 {
22878     if (virDomainDefAddConsoleCompat(def) < 0)
22879         return -1;
22880 
22881     if (virDomainDefAddImplicitControllers(def) < 0)
22882         return -1;
22883 
22884     if (virDomainDefAddImplicitVideo(def, xmlopt) < 0)
22885         return -1;
22886 
22887     return 0;
22888 }
22889 
22890 virDomainIOThreadIDDef *
virDomainIOThreadIDFind(const virDomainDef * def,unsigned int iothread_id)22891 virDomainIOThreadIDFind(const virDomainDef *def,
22892                         unsigned int iothread_id)
22893 {
22894     size_t i;
22895 
22896     if (!def->iothreadids || !def->niothreadids)
22897         return NULL;
22898 
22899     for (i = 0; i < def->niothreadids; i++) {
22900         if (iothread_id == def->iothreadids[i]->iothread_id)
22901             return def->iothreadids[i];
22902     }
22903 
22904     return NULL;
22905 }
22906 
22907 virDomainIOThreadIDDef *
virDomainIOThreadIDAdd(virDomainDef * def,unsigned int iothread_id)22908 virDomainIOThreadIDAdd(virDomainDef *def,
22909                        unsigned int iothread_id)
22910 {
22911     virDomainIOThreadIDDef *iothrid = NULL;
22912 
22913     iothrid = g_new0(virDomainIOThreadIDDef, 1);
22914 
22915     iothrid->iothread_id = iothread_id;
22916 
22917     VIR_APPEND_ELEMENT_COPY(def->iothreadids, def->niothreadids, iothrid);
22918 
22919     return iothrid;
22920 }
22921 
22922 
22923 void
virDomainIOThreadIDDel(virDomainDef * def,unsigned int iothread_id)22924 virDomainIOThreadIDDel(virDomainDef *def,
22925                        unsigned int iothread_id)
22926 {
22927     size_t i, j;
22928 
22929     for (i = 0; i < def->niothreadids; i++) {
22930         if (def->iothreadids[i]->iothread_id == iothread_id) {
22931             /* If we were sequential and removed a threadid in the
22932              * beginning or middle of the list, then unconditionally
22933              * clear the autofill flag so we don't lose these
22934              * definitions for XML formatting.
22935              */
22936             for (j = i + 1; j < def->niothreadids; j++)
22937                 def->iothreadids[j]->autofill = false;
22938 
22939             virDomainIOThreadIDDefFree(def->iothreadids[i]);
22940             VIR_DELETE_ELEMENT(def->iothreadids, i, def->niothreadids);
22941 
22942             return;
22943         }
22944     }
22945 }
22946 
22947 
22948 static int
virDomainEventActionDefFormat(virBuffer * buf,int type,const char * name,virEventActionToStringFunc convFunc)22949 virDomainEventActionDefFormat(virBuffer *buf,
22950                               int type,
22951                               const char *name,
22952                               virEventActionToStringFunc convFunc)
22953 {
22954     const char *typeStr = convFunc(type);
22955     if (!typeStr) {
22956         virReportError(VIR_ERR_INTERNAL_ERROR,
22957                        _("unexpected %s action: %d"), name, type);
22958         return -1;
22959     }
22960 
22961     virBufferAsprintf(buf, "<%s>%s</%s>\n", name, typeStr, name);
22962 
22963     return 0;
22964 }
22965 
22966 
22967 static void
virSecurityLabelDefFormat(virBuffer * buf,virSecurityLabelDef * def,unsigned int flags)22968 virSecurityLabelDefFormat(virBuffer *buf,
22969                           virSecurityLabelDef *def,
22970                           unsigned int flags)
22971 {
22972     const char *sectype = virDomainSeclabelTypeToString(def->type);
22973 
22974     if (!sectype)
22975         return;
22976 
22977     if (def->type == VIR_DOMAIN_SECLABEL_DEFAULT)
22978         return;
22979 
22980     /* libvirt versions prior to 0.10.0 support just a single seclabel element
22981      * in the XML, and that would typically be filled with type=selinux.
22982      * Don't format it in the MIGRATABLE case, for backwards compatibility
22983      */
22984     if ((STREQ_NULLABLE(def->model, "dac") ||
22985          STREQ_NULLABLE(def->model, "none")) && def->implicit &&
22986          (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE))
22987         return;
22988 
22989     virBufferAsprintf(buf, "<seclabel type='%s'",
22990                       sectype);
22991 
22992     virBufferEscapeString(buf, " model='%s'", def->model);
22993 
22994     if (def->type == VIR_DOMAIN_SECLABEL_NONE) {
22995         virBufferAddLit(buf, "/>\n");
22996         return;
22997     }
22998 
22999     virBufferAsprintf(buf, " relabel='%s'",
23000                       def->relabel ? "yes" : "no");
23001 
23002     if (def->label || def->imagelabel || def->baselabel) {
23003         virBufferAddLit(buf, ">\n");
23004         virBufferAdjustIndent(buf, 2);
23005         virBufferEscapeString(buf, "<label>%s</label>\n",
23006                               def->label);
23007         if (def->relabel)
23008             virBufferEscapeString(buf, "<imagelabel>%s</imagelabel>\n",
23009                                   def->imagelabel);
23010         if (def->type == VIR_DOMAIN_SECLABEL_DYNAMIC)
23011             virBufferEscapeString(buf, "<baselabel>%s</baselabel>\n",
23012                                   def->baselabel);
23013         virBufferAdjustIndent(buf, -2);
23014         virBufferAddLit(buf, "</seclabel>\n");
23015     } else {
23016         virBufferAddLit(buf, "/>\n");
23017     }
23018 }
23019 
23020 
23021 static void
virSecurityDeviceLabelDefFormat(virBuffer * buf,virSecurityDeviceLabelDef * def,unsigned int flags)23022 virSecurityDeviceLabelDefFormat(virBuffer *buf,
23023                                 virSecurityDeviceLabelDef *def,
23024                                 unsigned int flags)
23025 {
23026     /* For offline output, skip elements that allow labels but have no
23027      * label specified (possible if labelskip was ignored on input).  */
23028     if ((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) && !def->label && def->relabel)
23029         return;
23030 
23031     virBufferAddLit(buf, "<seclabel");
23032 
23033     if (def->model)
23034         virBufferEscapeString(buf, " model='%s'", def->model);
23035 
23036     if (def->labelskip)
23037         virBufferAddLit(buf, " labelskip='yes'");
23038     else
23039         virBufferAsprintf(buf, " relabel='%s'", def->relabel ? "yes" : "no");
23040 
23041     if (def->label) {
23042         virBufferAddLit(buf, ">\n");
23043         virBufferAdjustIndent(buf, 2);
23044         virBufferEscapeString(buf, "<label>%s</label>\n",
23045                               def->label);
23046         virBufferAdjustIndent(buf, -2);
23047         virBufferAddLit(buf, "</seclabel>\n");
23048     } else {
23049         virBufferAddLit(buf, "/>\n");
23050     }
23051 }
23052 
23053 
23054 static void
virDomainLeaseDefFormat(virBuffer * buf,virDomainLeaseDef * def)23055 virDomainLeaseDefFormat(virBuffer *buf,
23056                         virDomainLeaseDef *def)
23057 {
23058     virBufferAddLit(buf, "<lease>\n");
23059     virBufferAdjustIndent(buf, 2);
23060     virBufferEscapeString(buf, "<lockspace>%s</lockspace>\n", def->lockspace);
23061     virBufferEscapeString(buf, "<key>%s</key>\n", def->key);
23062     virBufferEscapeString(buf, "<target path='%s'", def->path);
23063     if (def->offset)
23064         virBufferAsprintf(buf, " offset='%llu'", def->offset);
23065     virBufferAddLit(buf, "/>\n");
23066     virBufferAdjustIndent(buf, -2);
23067     virBufferAddLit(buf, "</lease>\n");
23068 }
23069 
23070 static void
virDomainDiskGeometryDefFormat(virBuffer * buf,virDomainDiskDef * def)23071 virDomainDiskGeometryDefFormat(virBuffer *buf,
23072                                virDomainDiskDef *def)
23073 {
23074     const char *trans =
23075         virDomainDiskGeometryTransTypeToString(def->geometry.trans);
23076 
23077     if (def->geometry.cylinders > 0 &&
23078         def->geometry.heads > 0 &&
23079         def->geometry.sectors > 0) {
23080         virBufferAsprintf(buf,
23081                           "<geometry cyls='%u' heads='%u' secs='%u'",
23082                           def->geometry.cylinders,
23083                           def->geometry.heads,
23084                           def->geometry.sectors);
23085 
23086         if (def->geometry.trans != VIR_DOMAIN_DISK_TRANS_DEFAULT)
23087             virBufferEscapeString(buf, " trans='%s'", trans);
23088 
23089         virBufferAddLit(buf, "/>\n");
23090     }
23091 }
23092 
23093 static void
virDomainDiskBlockIoDefFormat(virBuffer * buf,virDomainDiskDef * def)23094 virDomainDiskBlockIoDefFormat(virBuffer *buf,
23095                               virDomainDiskDef *def)
23096 {
23097     if (def->blockio.logical_block_size > 0 ||
23098         def->blockio.physical_block_size > 0) {
23099         virBufferAddLit(buf, "<blockio");
23100         if (def->blockio.logical_block_size > 0) {
23101             virBufferAsprintf(buf,
23102                               " logical_block_size='%u'",
23103                               def->blockio.logical_block_size);
23104         }
23105         if (def->blockio.physical_block_size > 0) {
23106             virBufferAsprintf(buf,
23107                               " physical_block_size='%u'",
23108                               def->blockio.physical_block_size);
23109         }
23110         virBufferAddLit(buf, "/>\n");
23111     }
23112 }
23113 
23114 
23115 static void
virDomainSourceDefFormatSeclabel(virBuffer * buf,size_t nseclabels,virSecurityDeviceLabelDef ** seclabels,unsigned int flags)23116 virDomainSourceDefFormatSeclabel(virBuffer *buf,
23117                                  size_t nseclabels,
23118                                  virSecurityDeviceLabelDef **seclabels,
23119                                  unsigned int flags)
23120 {
23121     size_t n;
23122 
23123     for (n = 0; n < nseclabels; n++)
23124         virSecurityDeviceLabelDefFormat(buf, seclabels[n], flags);
23125 }
23126 
23127 
23128 static void
virDomainDiskSourceFormatNetworkCookies(virBuffer * buf,virStorageSource * src,unsigned int flags)23129 virDomainDiskSourceFormatNetworkCookies(virBuffer *buf,
23130                                         virStorageSource *src,
23131                                         unsigned int flags)
23132 {
23133     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23134     size_t i;
23135 
23136     if (!(flags & VIR_DOMAIN_DEF_FORMAT_SECURE))
23137         return;
23138 
23139     for (i = 0; i < src->ncookies; i++) {
23140         virBufferEscapeString(&childBuf, "<cookie name='%s'>", src->cookies[i]->name);
23141         virBufferEscapeString(&childBuf, "%s</cookie>\n", src->cookies[i]->value);
23142     }
23143 
23144     virXMLFormatElement(buf, "cookies", NULL, &childBuf);
23145 }
23146 
23147 
23148 static void
virDomainDiskSourceFormatNetwork(virBuffer * attrBuf,virBuffer * childBuf,virStorageSource * src,unsigned int flags)23149 virDomainDiskSourceFormatNetwork(virBuffer *attrBuf,
23150                                  virBuffer *childBuf,
23151                                  virStorageSource *src,
23152                                  unsigned int flags)
23153 {
23154     size_t n;
23155     g_autofree char *path = NULL;
23156 
23157     virBufferAsprintf(attrBuf, " protocol='%s'",
23158                       virStorageNetProtocolTypeToString(src->protocol));
23159 
23160     if (src->volume)
23161         path = g_strdup_printf("%s/%s", src->volume, src->path);
23162 
23163     virBufferEscapeString(attrBuf, " name='%s'", path ? path : src->path);
23164     virBufferEscapeString(attrBuf, " query='%s'", src->query);
23165 
23166     if (src->haveTLS != VIR_TRISTATE_BOOL_ABSENT &&
23167         !(flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE &&
23168           src->tlsFromConfig))
23169         virBufferAsprintf(attrBuf, " tls='%s'",
23170                           virTristateBoolTypeToString(src->haveTLS));
23171     if (flags & VIR_DOMAIN_DEF_FORMAT_STATUS)
23172         virBufferAsprintf(attrBuf, " tlsFromConfig='%d'", src->tlsFromConfig);
23173 
23174     for (n = 0; n < src->nhosts; n++) {
23175         virBufferAddLit(childBuf, "<host");
23176         virBufferEscapeString(childBuf, " name='%s'", src->hosts[n].name);
23177 
23178         if (src->hosts[n].port)
23179             virBufferAsprintf(childBuf, " port='%u'", src->hosts[n].port);
23180 
23181         if (src->hosts[n].transport)
23182             virBufferAsprintf(childBuf, " transport='%s'",
23183                               virStorageNetHostTransportTypeToString(src->hosts[n].transport));
23184 
23185         virBufferEscapeString(childBuf, " socket='%s'", src->hosts[n].socket);
23186         virBufferAddLit(childBuf, "/>\n");
23187     }
23188 
23189     if (src->protocol == VIR_STORAGE_NET_PROTOCOL_NFS &&
23190         (src->nfs_user || src->nfs_group)) {
23191         virBufferAddLit(childBuf, "<identity");
23192 
23193         virBufferEscapeString(childBuf, " user='%s'", src->nfs_user);
23194         virBufferEscapeString(childBuf, " group='%s'", src->nfs_group);
23195 
23196         virBufferAddLit(childBuf, "/>\n");
23197     }
23198 
23199 
23200     virBufferEscapeString(childBuf, "<snapshot name='%s'/>\n", src->snapshot);
23201     virBufferEscapeString(childBuf, "<config file='%s'/>\n", src->configFile);
23202 
23203     virStorageSourceInitiatorFormatXML(&src->initiator, childBuf);
23204 
23205     if (src->sslverify != VIR_TRISTATE_BOOL_ABSENT) {
23206         virBufferAsprintf(childBuf, "<ssl verify='%s'/>\n",
23207                           virTristateBoolTypeToString(src->sslverify));
23208     }
23209 
23210     virDomainDiskSourceFormatNetworkCookies(childBuf, src, flags);
23211 
23212     if (src->readahead)
23213         virBufferAsprintf(childBuf, "<readahead size='%llu'/>\n", src->readahead);
23214 
23215     if (src->timeout)
23216         virBufferAsprintf(childBuf, "<timeout seconds='%llu'/>\n", src->timeout);
23217 }
23218 
23219 
23220 static void
virDomainDiskSourceNVMeFormat(virBuffer * attrBuf,virBuffer * childBuf,const virStorageSourceNVMeDef * nvme)23221 virDomainDiskSourceNVMeFormat(virBuffer *attrBuf,
23222                               virBuffer *childBuf,
23223                               const virStorageSourceNVMeDef *nvme)
23224 {
23225     virBufferAddLit(attrBuf, " type='pci'");
23226     if (nvme->managed != VIR_TRISTATE_BOOL_ABSENT)
23227         virBufferAsprintf(attrBuf, " managed='%s'",
23228                           virTristateBoolTypeToString(nvme->managed));
23229     virBufferAsprintf(attrBuf, " namespace='%llu'", nvme->namespc);
23230     virPCIDeviceAddressFormat(childBuf, nvme->pciAddr, false);
23231 }
23232 
23233 
23234 static void
23235 virDomainChrSourceReconnectDefFormat(virBuffer *buf,
23236                                      virDomainChrSourceReconnectDef *def);
23237 
23238 
23239 static void
virDomainDiskSourceVhostuserFormat(virBuffer * attrBuf,virBuffer * childBuf,virDomainChrSourceDef * vhostuser)23240 virDomainDiskSourceVhostuserFormat(virBuffer *attrBuf,
23241                                    virBuffer *childBuf,
23242                                    virDomainChrSourceDef *vhostuser)
23243 {
23244     virBufferAddLit(attrBuf, " type='unix'");
23245     virBufferAsprintf(attrBuf, " path='%s'", vhostuser->data.nix.path);
23246 
23247     virDomainChrSourceReconnectDefFormat(childBuf, &vhostuser->data.nix.reconnect);
23248 }
23249 
23250 
23251 static int
virDomainDiskSourceFormatPrivateData(virBuffer * buf,virStorageSource * src,unsigned int flags,virDomainXMLOption * xmlopt)23252 virDomainDiskSourceFormatPrivateData(virBuffer *buf,
23253                                      virStorageSource *src,
23254                                      unsigned int flags,
23255                                      virDomainXMLOption *xmlopt)
23256 {
23257     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23258 
23259     if (!(flags & VIR_DOMAIN_DEF_FORMAT_STATUS) ||
23260         !xmlopt || !xmlopt->privateData.storageFormat)
23261         return 0;
23262 
23263     if (xmlopt->privateData.storageFormat(src, &childBuf) < 0)
23264         return -1;
23265 
23266     virXMLFormatElement(buf, "privateData", NULL, &childBuf);
23267     return 0;
23268 }
23269 
23270 
23271 static void
virDomainDiskSourceFormatSlice(virBuffer * buf,const char * slicetype,virStorageSourceSlice * slice)23272 virDomainDiskSourceFormatSlice(virBuffer *buf,
23273                                const char *slicetype,
23274                                virStorageSourceSlice *slice)
23275 {
23276     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
23277 
23278     if (!slice)
23279         return;
23280 
23281     virBufferAsprintf(&attrBuf, " type='%s'", slicetype);
23282     virBufferAsprintf(&attrBuf, " offset='%llu'", slice->offset);
23283     virBufferAsprintf(&attrBuf, " size='%llu'", slice->size);
23284 
23285     virXMLFormatElement(buf, "slice", &attrBuf, NULL);
23286 }
23287 
23288 
23289 static void
virDomainDiskSourceFormatSlices(virBuffer * buf,virStorageSource * src)23290 virDomainDiskSourceFormatSlices(virBuffer *buf,
23291                                 virStorageSource *src)
23292 {
23293     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23294 
23295     virDomainDiskSourceFormatSlice(&childBuf, "storage", src->sliceStorage);
23296 
23297     virXMLFormatElement(buf, "slices", NULL, &childBuf);
23298 }
23299 
23300 
23301 /**
23302  * virDomainDiskSourceFormat:
23303  * @buf: output buffer
23304  * @src: storage source definition to format
23305  * @element: name to use for the top-level element (often "source")
23306  * @policy: startup policy attribute value, if necessary
23307  * @attrIndex: the 'index' attribute of <source> is formatted if true
23308  * @flags: XML formatter flags
23309  * @skipAuth: Skip formatting of <auth>
23310  * @skipEnc: Skip formatting of <encryption>
23311  *                 regardless of the original definition state
23312  * @xmlopt: XML formatter callbacks
23313  *
23314  * Formats @src into a <source> element. Note that this doesn't format the
23315  * 'type' and 'format' properties of @src.
23316  */
23317 int
virDomainDiskSourceFormat(virBuffer * buf,virStorageSource * src,const char * element,int policy,bool attrIndex,unsigned int flags,bool skipAuth,bool skipEnc,virDomainXMLOption * xmlopt)23318 virDomainDiskSourceFormat(virBuffer *buf,
23319                           virStorageSource *src,
23320                           const char *element,
23321                           int policy,
23322                           bool attrIndex,
23323                           unsigned int flags,
23324                           bool skipAuth,
23325                           bool skipEnc,
23326                           virDomainXMLOption *xmlopt)
23327 {
23328     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
23329     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23330 
23331     switch ((virStorageType)src->type) {
23332     case VIR_STORAGE_TYPE_FILE:
23333         virBufferEscapeString(&attrBuf, " file='%s'", src->path);
23334         break;
23335 
23336     case VIR_STORAGE_TYPE_BLOCK:
23337         virBufferEscapeString(&attrBuf, " dev='%s'", src->path);
23338         break;
23339 
23340     case VIR_STORAGE_TYPE_DIR:
23341         virBufferEscapeString(&attrBuf, " dir='%s'", src->path);
23342         break;
23343 
23344     case VIR_STORAGE_TYPE_NETWORK:
23345         virDomainDiskSourceFormatNetwork(&attrBuf, &childBuf, src, flags);
23346         break;
23347 
23348     case VIR_STORAGE_TYPE_VOLUME:
23349         if (src->srcpool) {
23350             virBufferEscapeString(&attrBuf, " pool='%s'", src->srcpool->pool);
23351             virBufferEscapeString(&attrBuf, " volume='%s'",
23352                                   src->srcpool->volume);
23353             if (src->srcpool->mode)
23354                 virBufferAsprintf(&attrBuf, " mode='%s'",
23355                                   virStorageSourcePoolModeTypeToString(src->srcpool->mode));
23356         }
23357 
23358         break;
23359 
23360     case VIR_STORAGE_TYPE_NVME:
23361         virDomainDiskSourceNVMeFormat(&attrBuf, &childBuf, src->nvme);
23362         break;
23363 
23364     case VIR_STORAGE_TYPE_VHOST_USER:
23365         virDomainDiskSourceVhostuserFormat(&attrBuf, &childBuf, src->vhostuser);
23366         break;
23367 
23368     case VIR_STORAGE_TYPE_NONE:
23369     case VIR_STORAGE_TYPE_LAST:
23370         virReportError(VIR_ERR_INTERNAL_ERROR,
23371                        _("unexpected disk type %d"), src->type);
23372         return -1;
23373     }
23374 
23375     virDomainDiskSourceFormatSlices(&childBuf, src);
23376 
23377     if (src->type != VIR_STORAGE_TYPE_NETWORK)
23378         virDomainSourceDefFormatSeclabel(&childBuf, src->nseclabels,
23379                                          src->seclabels, flags);
23380 
23381     /* Storage Source formatting will not carry through the blunder
23382      * that disk source formatting had at one time to format the
23383      * <auth> for a volume source type. The <auth> information is
23384      * kept in the storage pool and would be overwritten anyway.
23385      * So avoid formatting it for volumes. */
23386     if (src->auth && !skipAuth && src->type != VIR_STORAGE_TYPE_VOLUME)
23387         virStorageAuthDefFormat(&childBuf, src->auth);
23388 
23389     if (src->encryption && !skipEnc &&
23390         virStorageEncryptionFormat(&childBuf, src->encryption) < 0)
23391         return -1;
23392 
23393     if (src->pr)
23394         virStoragePRDefFormat(&childBuf, src->pr,
23395                               flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE);
23396     if (policy && src->type != VIR_STORAGE_TYPE_NETWORK)
23397         virBufferEscapeString(&attrBuf, " startupPolicy='%s'",
23398                               virDomainStartupPolicyTypeToString(policy));
23399 
23400     if (attrIndex && src->id != 0)
23401         virBufferAsprintf(&attrBuf, " index='%u'", src->id);
23402 
23403     if (virDomainDiskSourceFormatPrivateData(&childBuf, src, flags, xmlopt) < 0)
23404         return -1;
23405 
23406     virXMLFormatElement(buf, element, &attrBuf, &childBuf);
23407 
23408     return 0;
23409 }
23410 
23411 
23412 int
virDomainDiskBackingStoreFormat(virBuffer * buf,virStorageSource * src,virDomainXMLOption * xmlopt,unsigned int flags)23413 virDomainDiskBackingStoreFormat(virBuffer *buf,
23414                                 virStorageSource *src,
23415                                 virDomainXMLOption *xmlopt,
23416                                 unsigned int flags)
23417 {
23418     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
23419     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23420     g_auto(virBuffer) formatAttrBuf = VIR_BUFFER_INITIALIZER;
23421     g_auto(virBuffer) formatChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
23422     bool inactive = flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE;
23423     virStorageSource *backingStore = src->backingStore;
23424 
23425     if (!backingStore)
23426         return 0;
23427 
23428     /* don't write detected backing chain members to inactive xml */
23429     if (inactive && backingStore->detected)
23430         return 0;
23431 
23432     if (backingStore->type == VIR_STORAGE_TYPE_NONE) {
23433         virBufferAddLit(buf, "<backingStore/>\n");
23434         return 0;
23435     }
23436 
23437     if (backingStore->format <= 0 || backingStore->format >= VIR_STORAGE_FILE_LAST) {
23438         virReportError(VIR_ERR_INTERNAL_ERROR,
23439                        _("unexpected disk backing store format %d"),
23440                        backingStore->format);
23441         return -1;
23442     }
23443 
23444     virBufferAsprintf(&attrBuf, " type='%s'",
23445                       virStorageTypeToString(backingStore->type));
23446     if (backingStore->id != 0)
23447         virBufferAsprintf(&attrBuf, " index='%u'", backingStore->id);
23448 
23449     virBufferAsprintf(&formatAttrBuf, " type='%s'",
23450                       virStorageFileFormatTypeToString(backingStore->format));
23451 
23452     if (backingStore->metadataCacheMaxSize > 0) {
23453         g_auto(virBuffer) metadataCacheChildBuf = VIR_BUFFER_INIT_CHILD(&formatChildBuf);
23454 
23455         virBufferAsprintf(&metadataCacheChildBuf,
23456                           "<max_size unit='bytes'>%llu</max_size>\n",
23457                           backingStore->metadataCacheMaxSize);
23458 
23459         virXMLFormatElement(&formatChildBuf, "metadata_cache", NULL, &metadataCacheChildBuf);
23460     }
23461 
23462     virXMLFormatElement(&childBuf, "format", &formatAttrBuf, &formatChildBuf);
23463 
23464 
23465     if (virDomainDiskSourceFormat(&childBuf, backingStore, "source", 0, false,
23466                                   flags, false, false, xmlopt) < 0)
23467         return -1;
23468 
23469     if (virDomainDiskBackingStoreFormat(&childBuf, backingStore, xmlopt, flags) < 0)
23470         return -1;
23471 
23472     virXMLFormatElement(buf, "backingStore", &attrBuf, &childBuf);
23473 
23474     return 0;
23475 }
23476 
23477 
23478 #define FORMAT_IOTUNE(val) \
23479         if (disk->blkdeviotune.val) { \
23480             virBufferAsprintf(&childBuf, "<" #val ">%llu</" #val ">\n", \
23481                               disk->blkdeviotune.val); \
23482         }
23483 
23484 static void
virDomainDiskDefFormatIotune(virBuffer * buf,virDomainDiskDef * disk)23485 virDomainDiskDefFormatIotune(virBuffer *buf,
23486                              virDomainDiskDef *disk)
23487 {
23488     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23489 
23490     FORMAT_IOTUNE(total_bytes_sec);
23491     FORMAT_IOTUNE(read_bytes_sec);
23492     FORMAT_IOTUNE(write_bytes_sec);
23493     FORMAT_IOTUNE(total_iops_sec);
23494     FORMAT_IOTUNE(read_iops_sec);
23495     FORMAT_IOTUNE(write_iops_sec);
23496 
23497     FORMAT_IOTUNE(total_bytes_sec_max);
23498     FORMAT_IOTUNE(read_bytes_sec_max);
23499     FORMAT_IOTUNE(write_bytes_sec_max);
23500     FORMAT_IOTUNE(total_iops_sec_max);
23501     FORMAT_IOTUNE(read_iops_sec_max);
23502     FORMAT_IOTUNE(write_iops_sec_max);
23503 
23504     if (disk->blkdeviotune.size_iops_sec) {
23505         virBufferAsprintf(&childBuf, "<size_iops_sec>%llu</size_iops_sec>\n",
23506                           disk->blkdeviotune.size_iops_sec);
23507     }
23508 
23509     if (disk->blkdeviotune.group_name) {
23510         virBufferEscapeString(&childBuf, "<group_name>%s</group_name>\n",
23511                               disk->blkdeviotune.group_name);
23512     }
23513 
23514     FORMAT_IOTUNE(total_bytes_sec_max_length);
23515     FORMAT_IOTUNE(read_bytes_sec_max_length);
23516     FORMAT_IOTUNE(write_bytes_sec_max_length);
23517     FORMAT_IOTUNE(total_iops_sec_max_length);
23518     FORMAT_IOTUNE(read_iops_sec_max_length);
23519     FORMAT_IOTUNE(write_iops_sec_max_length);
23520 
23521     virXMLFormatElement(buf, "iotune", NULL, &childBuf);
23522 }
23523 
23524 #undef FORMAT_IOTUNE
23525 
23526 
23527 static void
virDomainDiskDefFormatDriver(virBuffer * buf,virDomainDiskDef * disk)23528 virDomainDiskDefFormatDriver(virBuffer *buf,
23529                              virDomainDiskDef *disk)
23530 {
23531     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
23532     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23533 
23534     virBufferEscapeString(&attrBuf, " name='%s'", virDomainDiskGetDriver(disk));
23535 
23536     if (disk->src->format > 0)
23537         virBufferAsprintf(&attrBuf, " type='%s'",
23538                           virStorageFileFormatTypeToString(disk->src->format));
23539 
23540     if (disk->cachemode)
23541         virBufferAsprintf(&attrBuf, " cache='%s'",
23542                           virDomainDiskCacheTypeToString(disk->cachemode));
23543 
23544     if (disk->error_policy)
23545         virBufferAsprintf(&attrBuf, " error_policy='%s'",
23546                           virDomainDiskErrorPolicyTypeToString(disk->error_policy));
23547 
23548     if (disk->rerror_policy)
23549         virBufferAsprintf(&attrBuf, " rerror_policy='%s'",
23550                           virDomainDiskErrorPolicyTypeToString(disk->rerror_policy));
23551 
23552     if (disk->iomode)
23553         virBufferAsprintf(&attrBuf, " io='%s'",
23554                           virDomainDiskIoTypeToString(disk->iomode));
23555 
23556     if (disk->ioeventfd)
23557         virBufferAsprintf(&attrBuf, " ioeventfd='%s'",
23558                           virTristateSwitchTypeToString(disk->ioeventfd));
23559 
23560     if (disk->event_idx)
23561         virBufferAsprintf(&attrBuf, " event_idx='%s'",
23562                           virTristateSwitchTypeToString(disk->event_idx));
23563 
23564     if (disk->copy_on_read)
23565         virBufferAsprintf(&attrBuf, " copy_on_read='%s'",
23566                           virTristateSwitchTypeToString(disk->copy_on_read));
23567 
23568     if (disk->discard)
23569         virBufferAsprintf(&attrBuf, " discard='%s'",
23570                           virDomainDiskDiscardTypeToString(disk->discard));
23571 
23572     if (disk->iothread)
23573         virBufferAsprintf(&attrBuf, " iothread='%u'", disk->iothread);
23574 
23575     if (disk->detect_zeroes)
23576         virBufferAsprintf(&attrBuf, " detect_zeroes='%s'",
23577                           virDomainDiskDetectZeroesTypeToString(disk->detect_zeroes));
23578 
23579     if (disk->queues)
23580         virBufferAsprintf(&attrBuf, " queues='%u'", disk->queues);
23581 
23582     if (disk->queue_size)
23583         virBufferAsprintf(&attrBuf, " queue_size='%u'", disk->queue_size);
23584 
23585     virDomainVirtioOptionsFormat(&attrBuf, disk->virtio);
23586 
23587     if (disk->src->metadataCacheMaxSize > 0) {
23588         g_auto(virBuffer) metadataCacheChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
23589 
23590         virBufferAsprintf(&metadataCacheChildBuf,
23591                           "<max_size unit='bytes'>%llu</max_size>\n",
23592                           disk->src->metadataCacheMaxSize);
23593 
23594         virXMLFormatElement(&childBuf, "metadata_cache", NULL, &metadataCacheChildBuf);
23595     }
23596 
23597     virXMLFormatElement(buf, "driver", &attrBuf, &childBuf);
23598 }
23599 
23600 
23601 static int
virDomainDiskDefFormatMirror(virBuffer * buf,virDomainDiskDef * disk,unsigned int flags,virDomainXMLOption * xmlopt)23602 virDomainDiskDefFormatMirror(virBuffer *buf,
23603                              virDomainDiskDef *disk,
23604                              unsigned int flags,
23605                              virDomainXMLOption *xmlopt)
23606 {
23607     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
23608     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23609     g_auto(virBuffer) formatAttrBuf = VIR_BUFFER_INITIALIZER;
23610     g_auto(virBuffer) formatChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
23611     const char *formatStr = NULL;
23612 
23613     /* For now, mirroring is currently output-only: we only output it
23614      * for live domains, therefore we ignore it on input except for
23615      * the internal parse on libvirtd restart.  We prefer to output
23616      * the new style similar to backingStore, but for back-compat on
23617      * blockcopy files we also have to output old style attributes.
23618      * The parser accepts either style across libvirtd upgrades. */
23619 
23620     if (!disk->mirror ||
23621         (flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
23622         return 0;
23623 
23624     if (disk->mirror->format)
23625         formatStr = virStorageFileFormatTypeToString(disk->mirror->format);
23626     virBufferAsprintf(&attrBuf, " type='%s'",
23627                       virStorageTypeToString(disk->mirror->type));
23628     if (disk->mirror->type == VIR_STORAGE_TYPE_FILE &&
23629         disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_COPY) {
23630         virBufferEscapeString(&attrBuf, " file='%s'", disk->mirror->path);
23631         virBufferEscapeString(&attrBuf, " format='%s'", formatStr);
23632     }
23633     virBufferEscapeString(&attrBuf, " job='%s'",
23634                           virDomainBlockJobTypeToString(disk->mirrorJob));
23635     if (disk->mirrorState)
23636         virBufferEscapeString(&attrBuf, " ready='%s'",
23637                               virDomainDiskMirrorStateTypeToString(disk->mirrorState));
23638 
23639     virBufferEscapeString(&formatAttrBuf, " type='%s'", formatStr);
23640     if (disk->mirror->metadataCacheMaxSize > 0) {
23641         g_auto(virBuffer) metadataCacheChildBuf = VIR_BUFFER_INIT_CHILD(&formatChildBuf);
23642 
23643         virBufferAsprintf(&metadataCacheChildBuf,
23644                           "<max_size unit='bytes'>%llu</max_size>\n",
23645                           disk->mirror->metadataCacheMaxSize);
23646 
23647         virXMLFormatElement(&formatChildBuf, "metadata_cache", NULL, &metadataCacheChildBuf);
23648     }
23649 
23650     virXMLFormatElement(&childBuf, "format", &formatAttrBuf, &formatChildBuf);
23651 
23652     if (virDomainDiskSourceFormat(&childBuf, disk->mirror, "source", 0, true,
23653                                   flags, false, false, xmlopt) < 0)
23654         return -1;
23655 
23656     if (virDomainDiskBackingStoreFormat(&childBuf, disk->mirror, xmlopt, flags) < 0)
23657         return -1;
23658 
23659     virXMLFormatElement(buf, "mirror", &attrBuf, &childBuf);
23660 
23661     return 0;
23662 }
23663 
23664 
23665 static int
virDomainDiskDefFormatPrivateData(virBuffer * buf,virDomainDiskDef * disk,unsigned int flags,virDomainXMLOption * xmlopt)23666 virDomainDiskDefFormatPrivateData(virBuffer *buf,
23667                                   virDomainDiskDef *disk,
23668                                   unsigned int flags,
23669                                   virDomainXMLOption *xmlopt)
23670 {
23671     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23672 
23673     if (!(flags & VIR_DOMAIN_DEF_FORMAT_STATUS) ||
23674         !xmlopt ||
23675         !xmlopt->privateData.diskFormat)
23676         return 0;
23677 
23678     if (xmlopt->privateData.diskFormat(disk, &childBuf) < 0)
23679         return -1;
23680 
23681     virXMLFormatElement(buf, "privateData", NULL, &childBuf);
23682     return 0;
23683 }
23684 
23685 
23686 static int
virDomainDiskDefFormat(virBuffer * buf,virDomainDiskDef * def,unsigned int flags,virDomainXMLOption * xmlopt)23687 virDomainDiskDefFormat(virBuffer *buf,
23688                        virDomainDiskDef *def,
23689                        unsigned int flags,
23690                        virDomainXMLOption *xmlopt)
23691 {
23692     const char *type = virStorageTypeToString(def->src->type);
23693     const char *device = virDomainDiskDeviceTypeToString(def->device);
23694     const char *bus = virDomainDiskBusTypeToString(def->bus);
23695     const char *sgio = virDomainDeviceSGIOTypeToString(def->sgio);
23696 
23697     if (!type || !def->src->type) {
23698         virReportError(VIR_ERR_INTERNAL_ERROR,
23699                        _("unexpected disk type %d"), def->src->type);
23700         return -1;
23701     }
23702     if (!device) {
23703         virReportError(VIR_ERR_INTERNAL_ERROR,
23704                        _("unexpected disk device %d"), def->device);
23705         return -1;
23706     }
23707     if (!bus) {
23708         virReportError(VIR_ERR_INTERNAL_ERROR,
23709                        _("unexpected disk bus %d"), def->bus);
23710         return -1;
23711     }
23712     if (!sgio) {
23713         virReportError(VIR_ERR_INTERNAL_ERROR,
23714                        _("Unexpected disk sgio mode '%d'"), def->sgio);
23715         return -1;
23716     }
23717 
23718     virBufferAsprintf(buf,
23719                       "<disk type='%s' device='%s'",
23720                       type, device);
23721 
23722     if (def->model) {
23723         virBufferAsprintf(buf, " model='%s'",
23724                           virDomainDiskModelTypeToString(def->model));
23725     }
23726 
23727     if (def->rawio) {
23728         virBufferAsprintf(buf, " rawio='%s'",
23729                           virTristateBoolTypeToString(def->rawio));
23730     }
23731 
23732     if (def->sgio)
23733         virBufferAsprintf(buf, " sgio='%s'", sgio);
23734 
23735     if (def->snapshot &&
23736         !(def->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE &&
23737           def->src->readonly))
23738         virBufferAsprintf(buf, " snapshot='%s'",
23739                           virDomainSnapshotLocationTypeToString(def->snapshot));
23740     virBufferAddLit(buf, ">\n");
23741     virBufferAdjustIndent(buf, 2);
23742 
23743     virDomainDiskDefFormatDriver(buf, def);
23744 
23745     /* Format as child of <disk> if defined there; otherwise,
23746      * if defined as child of <source>, then format later */
23747     if (def->src->auth && def->diskElementAuth)
23748         virStorageAuthDefFormat(buf, def->src->auth);
23749 
23750     if (virDomainDiskSourceFormat(buf, def->src, "source", def->startupPolicy,
23751                                   true, flags,
23752                                   def->diskElementAuth, def->diskElementEnc,
23753                                   xmlopt) < 0)
23754         return -1;
23755 
23756     /* Don't format backingStore to inactive XMLs until the code for
23757      * persistent storage of backing chains is ready. */
23758     if (virDomainDiskBackingStoreFormat(buf, def->src, xmlopt, flags) < 0)
23759         return -1;
23760 
23761     virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name);
23762 
23763     virDomainDiskGeometryDefFormat(buf, def);
23764     virDomainDiskBlockIoDefFormat(buf, def);
23765 
23766     if (virDomainDiskDefFormatMirror(buf, def, flags, xmlopt) < 0)
23767         return -1;
23768 
23769     virBufferAsprintf(buf, "<target dev='%s' bus='%s'",
23770                       def->dst, bus);
23771     if ((def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY ||
23772          def->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
23773         def->tray_status != VIR_DOMAIN_DISK_TRAY_CLOSED)
23774         virBufferAsprintf(buf, " tray='%s'",
23775                           virDomainDiskTrayTypeToString(def->tray_status));
23776     if (def->bus == VIR_DOMAIN_DISK_BUS_USB &&
23777         def->removable != VIR_TRISTATE_SWITCH_ABSENT) {
23778         virBufferAsprintf(buf, " removable='%s'",
23779                           virTristateSwitchTypeToString(def->removable));
23780     }
23781     if (def->rotation_rate)
23782         virBufferAsprintf(buf, " rotation_rate='%u'", def->rotation_rate);
23783     virBufferAddLit(buf, "/>\n");
23784 
23785     virDomainDiskDefFormatIotune(buf, def);
23786 
23787     if (def->src->readonly)
23788         virBufferAddLit(buf, "<readonly/>\n");
23789     if (def->src->shared)
23790         virBufferAddLit(buf, "<shareable/>\n");
23791     if (def->transient) {
23792         virBufferAddLit(buf, "<transient");
23793         if (def->transientShareBacking == VIR_TRISTATE_BOOL_YES)
23794             virBufferAddLit(buf, " shareBacking='yes'");
23795         virBufferAddLit(buf, "/>\n");
23796     }
23797     virBufferEscapeString(buf, "<serial>%s</serial>\n", def->serial);
23798     virBufferEscapeString(buf, "<wwn>%s</wwn>\n", def->wwn);
23799     virBufferEscapeString(buf, "<vendor>%s</vendor>\n", def->vendor);
23800     virBufferEscapeString(buf, "<product>%s</product>\n", def->product);
23801 
23802     /* If originally found as a child of <disk>, then format thusly;
23803      * otherwise, will be formatted as child of <source> */
23804     if (def->src->encryption && def->diskElementEnc &&
23805         virStorageEncryptionFormat(buf, def->src->encryption) < 0)
23806         return -1;
23807     virDomainDeviceInfoFormat(buf, &def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT);
23808 
23809     if (virDomainDiskDefFormatPrivateData(buf, def, flags, xmlopt) < 0)
23810         return -1;
23811 
23812     /* format diskElementAuth and diskElementEnc into status XML to preserve
23813      * formatting */
23814     if (flags & VIR_DOMAIN_DEF_FORMAT_STATUS) {
23815         g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
23816 
23817         if (def->diskElementAuth)
23818             virBufferAddLit(&attrBuf, " auth='true'");
23819         if (def->diskElementEnc)
23820             virBufferAddLit(&attrBuf, " enc='true'");
23821 
23822         virXMLFormatElement(buf, "diskSecretsPlacement", &attrBuf, NULL);
23823     }
23824 
23825     virBufferAdjustIndent(buf, -2);
23826     virBufferAddLit(buf, "</disk>\n");
23827     return 0;
23828 }
23829 
23830 
23831 static void
virDomainControllerDriverFormat(virBuffer * buf,virDomainControllerDef * def)23832 virDomainControllerDriverFormat(virBuffer *buf,
23833                                 virDomainControllerDef *def)
23834 {
23835     g_auto(virBuffer) driverBuf = VIR_BUFFER_INITIALIZER;
23836 
23837     if (def->queues)
23838         virBufferAsprintf(&driverBuf, " queues='%u'", def->queues);
23839 
23840     if (def->cmd_per_lun)
23841         virBufferAsprintf(&driverBuf, " cmd_per_lun='%u'", def->cmd_per_lun);
23842 
23843     if (def->max_sectors)
23844         virBufferAsprintf(&driverBuf, " max_sectors='%u'", def->max_sectors);
23845 
23846     if (def->ioeventfd) {
23847         virBufferAsprintf(&driverBuf, " ioeventfd='%s'",
23848                           virTristateSwitchTypeToString(def->ioeventfd));
23849     }
23850 
23851     if (def->iothread)
23852         virBufferAsprintf(&driverBuf, " iothread='%u'", def->iothread);
23853 
23854     virDomainVirtioOptionsFormat(&driverBuf, def->virtio);
23855 
23856     virXMLFormatElement(buf, "driver", &driverBuf, NULL);
23857 }
23858 
23859 
23860 static int
virDomainControllerDefFormat(virBuffer * buf,virDomainControllerDef * def,unsigned int flags)23861 virDomainControllerDefFormat(virBuffer *buf,
23862                              virDomainControllerDef *def,
23863                              unsigned int flags)
23864 {
23865     const char *type = virDomainControllerTypeToString(def->type);
23866     const char *model = NULL;
23867     const char *modelName = NULL;
23868     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
23869     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
23870 
23871     if (!type) {
23872         virReportError(VIR_ERR_INTERNAL_ERROR,
23873                        _("unexpected controller type %d"), def->type);
23874         return -1;
23875     }
23876 
23877     if (def->model != -1) {
23878         model = virDomainControllerModelTypeToString(def, def->model);
23879 
23880         if (!model) {
23881             virReportError(VIR_ERR_INTERNAL_ERROR,
23882                            _("unexpected model type %d"), def->model);
23883             return -1;
23884         }
23885     }
23886 
23887     virBufferAsprintf(&attrBuf,
23888                       " type='%s' index='%d'",
23889                       type, def->idx);
23890 
23891     if (model)
23892         virBufferEscapeString(&attrBuf, " model='%s'", model);
23893 
23894     switch (def->type) {
23895     case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
23896         if (def->opts.vioserial.ports != -1) {
23897             virBufferAsprintf(&attrBuf, " ports='%d'",
23898                               def->opts.vioserial.ports);
23899         }
23900         if (def->opts.vioserial.vectors != -1) {
23901             virBufferAsprintf(&attrBuf, " vectors='%d'",
23902                               def->opts.vioserial.vectors);
23903         }
23904         break;
23905 
23906     case VIR_DOMAIN_CONTROLLER_TYPE_USB:
23907         if (def->opts.usbopts.ports != -1) {
23908             virBufferAsprintf(&attrBuf, " ports='%d'",
23909                               def->opts.usbopts.ports);
23910         }
23911         break;
23912 
23913     case VIR_DOMAIN_CONTROLLER_TYPE_XENBUS:
23914         if (def->opts.xenbusopts.maxGrantFrames != -1) {
23915             virBufferAsprintf(&attrBuf, " maxGrantFrames='%d'",
23916                               def->opts.xenbusopts.maxGrantFrames);
23917         }
23918         if (def->opts.xenbusopts.maxEventChannels != -1) {
23919             virBufferAsprintf(&attrBuf, " maxEventChannels='%d'",
23920                               def->opts.xenbusopts.maxEventChannels);
23921         }
23922         break;
23923 
23924     default:
23925         break;
23926     }
23927 
23928     if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
23929         bool formatModelName = true;
23930 
23931         if (def->opts.pciopts.modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_NONE)
23932             formatModelName = false;
23933 
23934         /* Historically, libvirt didn't support specifying a model name for
23935          * pci-root controllers; starting from 3.6.0, however, pSeries guests
23936          * use pci-root controllers with model name spapr-pci-host-bridge to
23937          * represent all PHBs, including the default one.
23938          *
23939          * In order to allow migration of pSeries guests from older libvirt
23940          * versions and back, we don't format the model name in the migratable
23941          * XML if it's spapr-pci-host-bridge, thus making "no model name" and
23942          * "spapr-pci-host-bridge model name" basically equivalent.
23943          *
23944          * The spapr-pci-host-bridge device is specific to pSeries.
23945          */
23946         if (def->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT &&
23947             def->opts.pciopts.modelName == VIR_DOMAIN_CONTROLLER_PCI_MODEL_NAME_SPAPR_PCI_HOST_BRIDGE &&
23948             flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE) {
23949             formatModelName = false;
23950         }
23951 
23952         if (formatModelName) {
23953             modelName = virDomainControllerPCIModelNameTypeToString(def->opts.pciopts.modelName);
23954             if (!modelName) {
23955                 virReportError(VIR_ERR_INTERNAL_ERROR,
23956                                _("unexpected model name value %d"),
23957                                def->opts.pciopts.modelName);
23958                 return -1;
23959             }
23960             virBufferAsprintf(&childBuf, "<model name='%s'/>\n", modelName);
23961         }
23962 
23963         if (def->opts.pciopts.chassisNr != -1 ||
23964             def->opts.pciopts.chassis != -1 ||
23965             def->opts.pciopts.port != -1 ||
23966             def->opts.pciopts.busNr != -1 ||
23967             def->opts.pciopts.targetIndex != -1 ||
23968             def->opts.pciopts.numaNode != -1 ||
23969             def->opts.pciopts.hotplug != VIR_TRISTATE_SWITCH_ABSENT) {
23970             virBufferAddLit(&childBuf, "<target");
23971             if (def->opts.pciopts.chassisNr != -1)
23972                 virBufferAsprintf(&childBuf, " chassisNr='%d'",
23973                                   def->opts.pciopts.chassisNr);
23974             if (def->opts.pciopts.chassis != -1)
23975                 virBufferAsprintf(&childBuf, " chassis='%d'",
23976                                   def->opts.pciopts.chassis);
23977             if (def->opts.pciopts.port != -1)
23978                 virBufferAsprintf(&childBuf, " port='0x%x'",
23979                                   def->opts.pciopts.port);
23980             if (def->opts.pciopts.busNr != -1)
23981                 virBufferAsprintf(&childBuf, " busNr='%d'",
23982                                   def->opts.pciopts.busNr);
23983             if (def->opts.pciopts.targetIndex != -1)
23984                 virBufferAsprintf(&childBuf, " index='%d'",
23985                                   def->opts.pciopts.targetIndex);
23986             if (def->opts.pciopts.hotplug != VIR_TRISTATE_SWITCH_ABSENT) {
23987                 virBufferAsprintf(&childBuf, " hotplug='%s'",
23988                                   virTristateSwitchTypeToString(def->opts.pciopts.hotplug));
23989             }
23990             if (def->opts.pciopts.numaNode == -1) {
23991                 virBufferAddLit(&childBuf, "/>\n");
23992             } else {
23993                 virBufferAddLit(&childBuf, ">\n");
23994                 virBufferAdjustIndent(&childBuf, 2);
23995                 virBufferAsprintf(&childBuf, "<node>%d</node>\n",
23996                                   def->opts.pciopts.numaNode);
23997                 virBufferAdjustIndent(&childBuf, -2);
23998                 virBufferAddLit(&childBuf, "</target>\n");
23999             }
24000         }
24001     }
24002 
24003     virDomainControllerDriverFormat(&childBuf, def);
24004 
24005     virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
24006 
24007     if (def->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
24008         def->opts.pciopts.pcihole64) {
24009         virBufferAsprintf(&childBuf, "<pcihole64 unit='KiB'>%lu</"
24010                           "pcihole64>\n", def->opts.pciopts.pcihole64size);
24011     }
24012 
24013     virXMLFormatElement(buf, "controller", &attrBuf, &childBuf);
24014 
24015     return 0;
24016 }
24017 
24018 
24019 int
virDomainFSIndexByName(virDomainDef * def,const char * name)24020 virDomainFSIndexByName(virDomainDef *def, const char *name)
24021 {
24022     virDomainFSDef *fs;
24023     size_t i;
24024 
24025     for (i = 0; i < def->nfss; i++) {
24026         fs = def->fss[i];
24027         if (STREQ(fs->dst, name))
24028             return i;
24029     }
24030     return -1;
24031 }
24032 
24033 
24034 static int
virDomainFSDefFormat(virBuffer * buf,virDomainFSDef * def,unsigned int flags)24035 virDomainFSDefFormat(virBuffer *buf,
24036                      virDomainFSDef *def,
24037                      unsigned int flags)
24038 {
24039     const char *type = virDomainFSTypeToString(def->type);
24040     const char *accessmode = virDomainFSAccessModeTypeToString(def->accessmode);
24041     const char *fsdriver = virDomainFSDriverTypeToString(def->fsdriver);
24042     const char *wrpolicy = virDomainFSWrpolicyTypeToString(def->wrpolicy);
24043     const char *multidevs = virDomainFSMultidevsTypeToString(def->multidevs);
24044     const char *src = def->src->path;
24045     g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
24046     g_auto(virBuffer) driverBuf = VIR_BUFFER_INIT_CHILD(buf);
24047     g_auto(virBuffer) binaryAttrBuf = VIR_BUFFER_INITIALIZER;
24048     g_auto(virBuffer) binaryBuf = VIR_BUFFER_INIT_CHILD(buf);
24049 
24050     if (!type) {
24051         virReportError(VIR_ERR_INTERNAL_ERROR,
24052                        _("unexpected filesystem type %d"), def->type);
24053         return -1;
24054     }
24055 
24056    if (!accessmode) {
24057         virReportError(VIR_ERR_INTERNAL_ERROR,
24058                        _("unexpected accessmode %d"), def->accessmode);
24059         return -1;
24060     }
24061 
24062     if (!multidevs) {
24063         virReportError(VIR_ERR_INTERNAL_ERROR,
24064                        _("unexpected multidevs %d"), def->multidevs);
24065         return -1;
24066     }
24067 
24068     virBufferAsprintf(buf, "<filesystem type='%s'", type);
24069     if (def->accessmode != VIR_DOMAIN_FS_ACCESSMODE_DEFAULT)
24070         virBufferAsprintf(buf, " accessmode='%s'", accessmode);
24071     if (def->model) {
24072         virBufferAsprintf(buf, " model='%s'",
24073                           virDomainFSModelTypeToString(def->model));
24074     }
24075     if (def->multidevs)
24076         virBufferAsprintf(buf, " multidevs='%s'", multidevs);
24077 
24078     if (def->fmode)
24079         virBufferAsprintf(buf, " fmode='%04o'", def->fmode);
24080 
24081     if (def->dmode)
24082         virBufferAsprintf(buf, " dmode='%04o'", def->dmode);
24083 
24084     virBufferAddLit(buf, ">\n");
24085 
24086     virBufferAdjustIndent(buf, 2);
24087     virBufferAdjustIndent(&driverBuf, 2);
24088     virBufferAdjustIndent(&binaryBuf, 2);
24089     if (def->fsdriver) {
24090         virBufferAsprintf(&driverAttrBuf, " type='%s'", fsdriver);
24091 
24092         if (def->format)
24093             virBufferAsprintf(&driverAttrBuf, " format='%s'",
24094                               virStorageFileFormatTypeToString(def->format));
24095 
24096         /* Don't generate anything if wrpolicy is set to default */
24097         if (def->wrpolicy)
24098             virBufferAsprintf(&driverAttrBuf, " wrpolicy='%s'", wrpolicy);
24099 
24100         if (def->queue_size)
24101             virBufferAsprintf(&driverAttrBuf, " queue='%llu'", def->queue_size);
24102 
24103     }
24104 
24105     if (def->fsdriver == VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS) {
24106         g_auto(virBuffer) lockAttrBuf = VIR_BUFFER_INITIALIZER;
24107         virBufferEscapeString(&binaryAttrBuf, " path='%s'", def->binary);
24108 
24109         if (def->xattr != VIR_TRISTATE_SWITCH_ABSENT) {
24110             virBufferAsprintf(&binaryAttrBuf, " xattr='%s'",
24111                               virTristateSwitchTypeToString(def->xattr));
24112         }
24113 
24114         if (def->cache != VIR_DOMAIN_FS_CACHE_MODE_DEFAULT) {
24115             virBufferAsprintf(&binaryBuf, "<cache mode='%s'/>\n",
24116                               virDomainFSCacheModeTypeToString(def->cache));
24117         }
24118 
24119         if (def->sandbox != VIR_DOMAIN_FS_SANDBOX_MODE_DEFAULT) {
24120             virBufferAsprintf(&binaryBuf, "<sandbox mode='%s'/>\n",
24121                               virDomainFSSandboxModeTypeToString(def->sandbox));
24122         }
24123 
24124         if (def->posix_lock != VIR_TRISTATE_SWITCH_ABSENT) {
24125             virBufferAsprintf(&lockAttrBuf, " posix='%s'",
24126                               virTristateSwitchTypeToString(def->posix_lock));
24127         }
24128 
24129         if (def->flock != VIR_TRISTATE_SWITCH_ABSENT) {
24130             virBufferAsprintf(&lockAttrBuf, " flock='%s'",
24131                               virTristateSwitchTypeToString(def->flock));
24132         }
24133 
24134         virXMLFormatElement(&binaryBuf, "lock", &lockAttrBuf, NULL);
24135     }
24136 
24137     virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio);
24138 
24139     virXMLFormatElement(buf, "driver", &driverAttrBuf, &driverBuf);
24140     virXMLFormatElement(buf, "binary", &binaryAttrBuf, &binaryBuf);
24141 
24142     switch (def->type) {
24143     case VIR_DOMAIN_FS_TYPE_MOUNT:
24144     case VIR_DOMAIN_FS_TYPE_BIND:
24145         if (!def->sock)
24146             virBufferEscapeString(buf, "<source dir='%s'/>\n", src);
24147         else
24148             virBufferEscapeString(buf, "<source socket='%s'/>\n", def->sock);
24149         break;
24150 
24151     case VIR_DOMAIN_FS_TYPE_BLOCK:
24152         virBufferEscapeString(buf, "<source dev='%s'/>\n",
24153                               src);
24154         break;
24155 
24156     case VIR_DOMAIN_FS_TYPE_FILE:
24157         virBufferEscapeString(buf, "<source file='%s'/>\n",
24158                               src);
24159         break;
24160 
24161     case VIR_DOMAIN_FS_TYPE_TEMPLATE:
24162         virBufferEscapeString(buf, "<source name='%s'/>\n",
24163                               src);
24164         break;
24165 
24166     case VIR_DOMAIN_FS_TYPE_RAM:
24167         virBufferAsprintf(buf, "<source usage='%lld' units='KiB'/>\n",
24168                           def->usage / 1024);
24169         break;
24170 
24171     case VIR_DOMAIN_FS_TYPE_VOLUME:
24172         virBufferAddLit(buf, "<source");
24173         virBufferEscapeString(buf, " pool='%s'", def->src->srcpool->pool);
24174         virBufferEscapeString(buf, " volume='%s'", def->src->srcpool->volume);
24175         virBufferAddLit(buf, "/>\n");
24176         break;
24177     }
24178 
24179     virBufferEscapeString(buf, "<target dir='%s'/>\n",
24180                           def->dst);
24181 
24182     if (def->readonly)
24183         virBufferAddLit(buf, "<readonly/>\n");
24184 
24185     virDomainDeviceInfoFormat(buf, &def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT);
24186 
24187     if (def->space_hard_limit)
24188         virBufferAsprintf(buf, "<space_hard_limit unit='bytes'>"
24189                           "%llu</space_hard_limit>\n", def->space_hard_limit);
24190     if (def->space_soft_limit) {
24191         virBufferAsprintf(buf, "<space_soft_limit unit='bytes'>"
24192                           "%llu</space_soft_limit>\n", def->space_soft_limit);
24193     }
24194     virBufferAdjustIndent(buf, -2);
24195     virBufferAddLit(buf, "</filesystem>\n");
24196 
24197     return 0;
24198 }
24199 
24200 
24201 static int
virDomainNetIPInfoFormat(virBuffer * buf,virNetDevIPInfo * def)24202 virDomainNetIPInfoFormat(virBuffer *buf,
24203                          virNetDevIPInfo *def)
24204 {
24205     size_t i;
24206 
24207     /* Output IP addresses */
24208     for (i = 0; i < def->nips; i++) {
24209         virSocketAddr *address = &def->ips[i]->address;
24210         char *ipStr = virSocketAddrFormat(address);
24211         const char *familyStr = NULL;
24212 
24213         if (!ipStr)
24214             return -1;
24215         if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET6))
24216             familyStr = "ipv6";
24217         else if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET))
24218             familyStr = "ipv4";
24219         virBufferAsprintf(buf, "<ip address='%s'",
24220                           ipStr);
24221         VIR_FREE(ipStr);
24222         if (familyStr)
24223             virBufferAsprintf(buf, " family='%s'", familyStr);
24224         if (def->ips[i]->prefix)
24225             virBufferAsprintf(buf, " prefix='%u'", def->ips[i]->prefix);
24226         if (VIR_SOCKET_ADDR_VALID(&def->ips[i]->peer)) {
24227             if (!(ipStr = virSocketAddrFormat(&def->ips[i]->peer)))
24228                 return -1;
24229             virBufferAsprintf(buf, " peer='%s'", ipStr);
24230             VIR_FREE(ipStr);
24231         }
24232         virBufferAddLit(buf, "/>\n");
24233     }
24234 
24235     for (i = 0; i < def->nroutes; i++)
24236         if (virNetDevIPRouteFormat(buf, def->routes[i]) < 0)
24237             return -1;
24238     return 0;
24239 }
24240 
24241 
24242 static void
virDomainHostdevDefFormatSubsysUSB(virBuffer * buf,virDomainHostdevDef * def,unsigned int flags,bool includeTypeInAddr)24243 virDomainHostdevDefFormatSubsysUSB(virBuffer *buf,
24244                                    virDomainHostdevDef *def,
24245                                    unsigned int flags,
24246                                    bool includeTypeInAddr)
24247 {
24248     g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
24249     g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(buf);
24250     virDomainHostdevSubsysUSB *usbsrc = &def->source.subsys.u.usb;
24251 
24252     if (def->startupPolicy)
24253         virBufferAsprintf(&sourceAttrBuf, " startupPolicy='%s'",
24254                           virDomainStartupPolicyTypeToString(def->startupPolicy));
24255 
24256     if (usbsrc->autoAddress && (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE))
24257         virBufferAddLit(&sourceAttrBuf, " autoAddress='yes'");
24258 
24259     if (def->missing && !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
24260         virBufferAddLit(&sourceAttrBuf, " missing='yes'");
24261 
24262     if (usbsrc->vendor) {
24263         virBufferAsprintf(&sourceChildBuf, "<vendor id='0x%.4x'/>\n", usbsrc->vendor);
24264         virBufferAsprintf(&sourceChildBuf, "<product id='0x%.4x'/>\n", usbsrc->product);
24265     }
24266 
24267     if (usbsrc->bus || usbsrc->device)
24268         virBufferAsprintf(&sourceChildBuf, "<address %sbus='%d' device='%d'/>\n",
24269                           includeTypeInAddr ? "type='usb' " : "",
24270                           usbsrc->bus, usbsrc->device);
24271 
24272     virXMLFormatElement(buf, "source", &sourceAttrBuf, &sourceChildBuf);
24273 }
24274 
24275 
24276 static int
virDomainHostdevDefFormatSubsysPCI(virBuffer * buf,virDomainHostdevDef * def,unsigned int flags,bool includeTypeInAddr)24277 virDomainHostdevDefFormatSubsysPCI(virBuffer *buf,
24278                                    virDomainHostdevDef *def,
24279                                    unsigned int flags,
24280                                    bool includeTypeInAddr)
24281 {
24282     g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
24283     g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(buf);
24284     g_auto(virBuffer) origstatesChildBuf = VIR_BUFFER_INIT_CHILD(&sourceChildBuf);
24285     virDomainHostdevSubsysPCI *pcisrc = &def->source.subsys.u.pci;
24286 
24287     if (def->writeFiltering != VIR_TRISTATE_BOOL_ABSENT)
24288             virBufferAsprintf(&sourceAttrBuf, " writeFiltering='%s'",
24289                               virTristateBoolTypeToString(def->writeFiltering));
24290 
24291     if (pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
24292         const char *backend = virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend);
24293 
24294         if (!backend) {
24295             virReportError(VIR_ERR_INTERNAL_ERROR,
24296                            _("unexpected pci hostdev driver name type %d"),
24297                            pcisrc->backend);
24298             return -1;
24299         }
24300 
24301         virBufferAsprintf(buf, "<driver name='%s'/>\n", backend);
24302     }
24303 
24304     virPCIDeviceAddressFormat(&sourceChildBuf, pcisrc->addr, includeTypeInAddr);
24305 
24306     if ((flags & VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES)) {
24307         if (def->origstates.states.pci.unbind_from_stub)
24308             virBufferAddLit(&origstatesChildBuf, "<unbind/>\n");
24309 
24310         if (def->origstates.states.pci.remove_slot)
24311             virBufferAddLit(&origstatesChildBuf, "<removeslot/>\n");
24312 
24313         if (def->origstates.states.pci.reprobe)
24314             virBufferAddLit(&origstatesChildBuf, "<reprobe/>\n");
24315 
24316         virXMLFormatElement(&sourceChildBuf, "origstates", NULL, &origstatesChildBuf);
24317     }
24318 
24319     virXMLFormatElement(buf, "source", &sourceAttrBuf, &sourceChildBuf);
24320     return 0;
24321 }
24322 
24323 
24324 static int
virDomainHostdevDefFormatSubsysSCSI(virBuffer * buf,virDomainHostdevDef * def,unsigned int flags,bool includeTypeInAddr,virDomainXMLOption * xmlopt)24325 virDomainHostdevDefFormatSubsysSCSI(virBuffer *buf,
24326                                     virDomainHostdevDef *def,
24327                                     unsigned int flags,
24328                                     bool includeTypeInAddr,
24329                                     virDomainXMLOption *xmlopt)
24330 {
24331     g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
24332     g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(buf);
24333     virDomainHostdevSubsysSCSI *scsisrc = &def->source.subsys.u.scsi;
24334     virDomainHostdevSubsysSCSIHost *scsihostsrc = &scsisrc->u.host;
24335     virDomainHostdevSubsysSCSIiSCSI *iscsisrc = &scsisrc->u.iscsi;
24336 
24337     if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
24338         virBufferAsprintf(&sourceAttrBuf, " protocol='%s' name='%s'",
24339                           virDomainHostdevSubsysSCSIProtocolTypeToString(scsisrc->protocol),
24340                           iscsisrc->src->path);
24341 
24342         virBufferAddLit(&sourceChildBuf, "<host");
24343         virBufferEscapeString(&sourceChildBuf, " name='%s'", iscsisrc->src->hosts[0].name);
24344         if (iscsisrc->src->hosts[0].port)
24345             virBufferAsprintf(&sourceChildBuf, " port='%u'", iscsisrc->src->hosts[0].port);
24346         virBufferAddLit(&sourceChildBuf, "/>\n");
24347 
24348         if (virDomainDiskSourceFormatPrivateData(&sourceChildBuf, iscsisrc->src,
24349                                                  flags, xmlopt) < 0)
24350             return -1;
24351 
24352         if (iscsisrc->src->auth)
24353             virStorageAuthDefFormat(&sourceChildBuf, iscsisrc->src->auth);
24354 
24355         virStorageSourceInitiatorFormatXML(&iscsisrc->src->initiator,
24356                                            &sourceChildBuf);
24357     } else {
24358         virBufferAsprintf(&sourceChildBuf, "<adapter name='%s'/>\n",
24359                           scsihostsrc->adapter);
24360 
24361         virBufferAddLit(&sourceChildBuf, "<address");
24362         if (includeTypeInAddr)
24363             virBufferAddLit(&sourceChildBuf, " type='scsi'");
24364         virBufferAsprintf(&sourceChildBuf, " bus='%u' target='%u' unit='%llu'",
24365                           scsihostsrc->bus, scsihostsrc->target, scsihostsrc->unit);
24366         virBufferAddLit(&sourceChildBuf, "/>\n");
24367 
24368         if (scsihostsrc->src &&
24369             virDomainDiskSourceFormatPrivateData(&sourceChildBuf, scsihostsrc->src,
24370                                                  flags, xmlopt) < 0)
24371             return -1;
24372     }
24373 
24374     virXMLFormatElement(buf, "source", &sourceAttrBuf, &sourceChildBuf);
24375     return 0;
24376 }
24377 
24378 
24379 static void
virDomainHostdevDefFormatSubsysSCSIHost(virBuffer * buf,virDomainHostdevDef * def)24380 virDomainHostdevDefFormatSubsysSCSIHost(virBuffer *buf,
24381                                         virDomainHostdevDef *def)
24382 {
24383     g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
24384     virDomainHostdevSubsysSCSIVHost *hostsrc = &def->source.subsys.u.scsi_host;
24385 
24386     virBufferAsprintf(&sourceAttrBuf, " protocol='%s' wwpn='%s'",
24387                       virDomainHostdevSubsysSCSIHostProtocolTypeToString(hostsrc->protocol),
24388                       hostsrc->wwpn);
24389 
24390     virXMLFormatElement(buf, "source", &sourceAttrBuf, NULL);
24391 }
24392 
24393 
24394 static void
virDomainHostdevDefFormatSubsysMdev(virBuffer * buf,virDomainHostdevDef * def)24395 virDomainHostdevDefFormatSubsysMdev(virBuffer *buf,
24396                                     virDomainHostdevDef *def)
24397 {
24398     g_auto(virBuffer) sourceChildBuf = VIR_BUFFER_INIT_CHILD(buf);
24399     virDomainHostdevSubsysMediatedDev *mdevsrc = &def->source.subsys.u.mdev;
24400 
24401     virBufferAsprintf(&sourceChildBuf, "<address uuid='%s'/>\n", mdevsrc->uuidstr);
24402 
24403     virXMLFormatElement(buf, "source", NULL, &sourceChildBuf);
24404 }
24405 
24406 
24407 static int
virDomainHostdevDefFormatSubsys(virBuffer * buf,virDomainHostdevDef * def,unsigned int flags,bool includeTypeInAddr,virDomainXMLOption * xmlopt)24408 virDomainHostdevDefFormatSubsys(virBuffer *buf,
24409                                 virDomainHostdevDef *def,
24410                                 unsigned int flags,
24411                                 bool includeTypeInAddr,
24412                                 virDomainXMLOption *xmlopt)
24413 {
24414     switch ((virDomainHostdevSubsysType) def->source.subsys.type) {
24415     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
24416         virDomainHostdevDefFormatSubsysUSB(buf, def, flags, includeTypeInAddr);
24417         return 0;
24418 
24419     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
24420         return virDomainHostdevDefFormatSubsysPCI(buf, def, flags, includeTypeInAddr);
24421 
24422     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
24423         return virDomainHostdevDefFormatSubsysSCSI(buf, def, flags, includeTypeInAddr, xmlopt);
24424 
24425     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
24426         virDomainHostdevDefFormatSubsysSCSIHost(buf, def);
24427         return 0;
24428 
24429     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
24430         virDomainHostdevDefFormatSubsysMdev(buf, def);
24431         return 0;
24432 
24433     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
24434     default:
24435         virReportEnumRangeError(virDomainHostdevSubsysType, def->source.subsys.type);
24436         return -1;
24437     }
24438 
24439     return 0;
24440 }
24441 
24442 static int
virDomainHostdevDefFormatCaps(virBuffer * buf,virDomainHostdevDef * def)24443 virDomainHostdevDefFormatCaps(virBuffer *buf,
24444                               virDomainHostdevDef *def)
24445 {
24446     virBufferAddLit(buf, "<source>\n");
24447 
24448     virBufferAdjustIndent(buf, 2);
24449     switch (def->source.caps.type) {
24450     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
24451         virBufferEscapeString(buf, "<block>%s</block>\n",
24452                               def->source.caps.u.storage.block);
24453         break;
24454     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
24455         virBufferEscapeString(buf, "<char>%s</char>\n",
24456                               def->source.caps.u.misc.chardev);
24457         break;
24458     case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
24459         virBufferEscapeString(buf, "<interface>%s</interface>\n",
24460                               def->source.caps.u.net.ifname);
24461         break;
24462     default:
24463         virReportError(VIR_ERR_INTERNAL_ERROR,
24464                        _("unexpected hostdev type %d"),
24465                        def->source.caps.type);
24466         return -1;
24467     }
24468 
24469     virBufferAdjustIndent(buf, -2);
24470     virBufferAddLit(buf, "</source>\n");
24471 
24472     if (def->source.caps.type == VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET &&
24473         virDomainNetIPInfoFormat(buf, &def->source.caps.u.net.ip) < 0)
24474         return -1;
24475 
24476     return 0;
24477 }
24478 
24479 /* virDomainActualNetDefContentsFormat() - format just the subelements
24480  * of <interface> that may be overridden by what is in the
24481  * virDomainActualNetDef, but inside the current element, rather
24482  * than enclosed in an <actual> subelement.
24483  */
24484 static int
virDomainActualNetDefContentsFormat(virBuffer * buf,virDomainNetDef * def,bool inSubelement,unsigned int flags,virDomainXMLOption * xmlopt)24485 virDomainActualNetDefContentsFormat(virBuffer *buf,
24486                                     virDomainNetDef *def,
24487                                     bool inSubelement,
24488                                     unsigned int flags,
24489                                     virDomainXMLOption *xmlopt)
24490 {
24491     virDomainNetType actualType = virDomainNetGetActualType(def);
24492 
24493     if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
24494         if (virDomainHostdevDefFormatSubsys(buf, virDomainNetGetActualHostdev(def),
24495                                             flags, true, xmlopt) < 0) {
24496             return -1;
24497         }
24498     } else {
24499         virBufferAddLit(buf, "<source");
24500         if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK && !inSubelement) {
24501             /* When we're putting our output into the <actual>
24502              * subelement rather than the main <interface>, the
24503              * network name and portgroup don't need to be included in
24504              * the <source> here because the main interface element's
24505              * <source> has the same info already. If we've been
24506              * called to output directly into the main element's
24507              * <source> though (the case here - "!inSubElement"), we
24508              * *do* need to output network/portgroup, because the
24509              * caller won't have done it).
24510              */
24511             virBufferEscapeString(buf, " network='%s'",
24512                                   def->data.network.name);
24513             virBufferEscapeString(buf, " portgroup='%s'",
24514                                   def->data.network.portgroup);
24515             if (virUUIDIsValid(def->data.network.portid)) {
24516                 char uuidstr[VIR_UUID_STRING_BUFLEN];
24517                 virUUIDFormat(def->data.network.portid, uuidstr);
24518                 virBufferAsprintf(buf, " portid='%s'", uuidstr);
24519             }
24520         }
24521         if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
24522             actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
24523             int macTableManager = virDomainNetGetActualBridgeMACTableManager(def);
24524 
24525             /* actualType == NETWORK includes the name of the bridge
24526              * that is used by the network, whether we are
24527              * "inSubElement" or not.
24528              */
24529             virBufferEscapeString(buf, " bridge='%s'",
24530                                   virDomainNetGetActualBridgeName(def));
24531             if (macTableManager) {
24532                 virBufferAsprintf(buf, " macTableManager='%s'",
24533                                   virNetworkBridgeMACTableManagerTypeToString(macTableManager));
24534             }
24535         } else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
24536             const char *mode;
24537 
24538             virBufferEscapeString(buf, " dev='%s'",
24539                                   virDomainNetGetActualDirectDev(def));
24540             mode = virNetDevMacVLanModeTypeToString(virDomainNetGetActualDirectMode(def));
24541             if (!mode) {
24542                 virReportError(VIR_ERR_INTERNAL_ERROR,
24543                                _("unexpected source mode %d"),
24544                                virDomainNetGetActualDirectMode(def));
24545                 return -1;
24546             }
24547             virBufferAsprintf(buf, " mode='%s'", mode);
24548         }
24549 
24550         virBufferAddLit(buf, "/>\n");
24551     }
24552     if (flags & VIR_DOMAIN_DEF_FORMAT_STATUS &&
24553         def->data.network.actual && def->data.network.actual->class_id) {
24554         virBufferAsprintf(buf, "<class id='%u'/>\n",
24555                           def->data.network.actual->class_id);
24556     }
24557 
24558     if (virNetDevVlanFormat(virDomainNetGetActualVlan(def), buf) < 0)
24559         return -1;
24560     if (virNetDevVPortProfileFormat(virDomainNetGetActualVirtPortProfile(def), buf) < 0)
24561         return -1;
24562     if (virNetDevBandwidthFormat(virDomainNetGetActualBandwidth(def), 0, buf) < 0)
24563         return -1;
24564     virNetworkPortOptionsFormat(virDomainNetGetActualPortOptionsIsolated(def), buf);
24565     return 0;
24566 }
24567 
24568 /* virDomainActualNetDefFormat() - format the ActualNetDef
24569  * info inside an <actual> element, as required for internal storage
24570  * of domain status
24571  */
24572 static int
virDomainActualNetDefFormat(virBuffer * buf,virDomainNetDef * def,unsigned int flags,virDomainXMLOption * xmlopt)24573 virDomainActualNetDefFormat(virBuffer *buf,
24574                             virDomainNetDef *def,
24575                             unsigned int flags,
24576                             virDomainXMLOption *xmlopt)
24577 {
24578     virDomainNetType type;
24579     const char *typeStr;
24580 
24581     if (!def)
24582         return 0;
24583     type = virDomainNetGetActualType(def);
24584     typeStr = virDomainNetTypeToString(type);
24585 
24586     if (!typeStr) {
24587         virReportError(VIR_ERR_INTERNAL_ERROR,
24588                        _("unexpected net type %d"), def->type);
24589         return -1;
24590     }
24591 
24592     virBufferAsprintf(buf, "<actual type='%s'", typeStr);
24593     if (type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
24594         virDomainHostdevDef *hostdef = virDomainNetGetActualHostdev(def);
24595         if  (hostdef && hostdef->managed)
24596             virBufferAddLit(buf, " managed='yes'");
24597     }
24598     if (def->trustGuestRxFilters)
24599         virBufferAsprintf(buf, " trustGuestRxFilters='%s'",
24600                           virTristateBoolTypeToString(def->trustGuestRxFilters));
24601     virBufferAddLit(buf, ">\n");
24602 
24603     virBufferAdjustIndent(buf, 2);
24604     if (virDomainActualNetDefContentsFormat(buf, def, true, flags, xmlopt) < 0)
24605        return -1;
24606     virBufferAdjustIndent(buf, -2);
24607     virBufferAddLit(buf, "</actual>\n");
24608     return 0;
24609 }
24610 
24611 
24612 static void
virDomainVirtioNetGuestOptsFormat(virBuffer * buf,virDomainNetDef * def)24613 virDomainVirtioNetGuestOptsFormat(virBuffer *buf,
24614                                   virDomainNetDef *def)
24615 {
24616     if (def->driver.virtio.guest.csum) {
24617         virBufferAsprintf(buf, " csum='%s'",
24618                           virTristateSwitchTypeToString(def->driver.virtio.guest.csum));
24619     }
24620     if (def->driver.virtio.guest.tso4) {
24621         virBufferAsprintf(buf, " tso4='%s'",
24622                           virTristateSwitchTypeToString(def->driver.virtio.guest.tso4));
24623     }
24624     if (def->driver.virtio.guest.tso6) {
24625         virBufferAsprintf(buf, " tso6='%s'",
24626                           virTristateSwitchTypeToString(def->driver.virtio.guest.tso6));
24627     }
24628     if (def->driver.virtio.guest.ecn) {
24629         virBufferAsprintf(buf, " ecn='%s'",
24630                           virTristateSwitchTypeToString(def->driver.virtio.guest.ecn));
24631     }
24632     if (def->driver.virtio.guest.ufo) {
24633         virBufferAsprintf(buf, " ufo='%s'",
24634                           virTristateSwitchTypeToString(def->driver.virtio.guest.ufo));
24635     }
24636 }
24637 
24638 
24639 static void
virDomainVirtioNetHostOptsFormat(virBuffer * buf,virDomainNetDef * def)24640 virDomainVirtioNetHostOptsFormat(virBuffer *buf,
24641                                  virDomainNetDef *def)
24642 {
24643     if (def->driver.virtio.host.csum) {
24644         virBufferAsprintf(buf, " csum='%s'",
24645                           virTristateSwitchTypeToString(def->driver.virtio.host.csum));
24646     }
24647     if (def->driver.virtio.host.gso) {
24648         virBufferAsprintf(buf, " gso='%s'",
24649                           virTristateSwitchTypeToString(def->driver.virtio.host.gso));
24650     }
24651     if (def->driver.virtio.host.tso4) {
24652         virBufferAsprintf(buf, " tso4='%s'",
24653                           virTristateSwitchTypeToString(def->driver.virtio.host.tso4));
24654     }
24655     if (def->driver.virtio.host.tso6) {
24656         virBufferAsprintf(buf, " tso6='%s'",
24657                           virTristateSwitchTypeToString(def->driver.virtio.host.tso6));
24658     }
24659     if (def->driver.virtio.host.ecn) {
24660         virBufferAsprintf(buf, " ecn='%s'",
24661                           virTristateSwitchTypeToString(def->driver.virtio.host.ecn));
24662     }
24663     if (def->driver.virtio.host.ufo) {
24664         virBufferAsprintf(buf, " ufo='%s'",
24665                           virTristateSwitchTypeToString(def->driver.virtio.host.ufo));
24666     }
24667     if (def->driver.virtio.host.mrg_rxbuf) {
24668         virBufferAsprintf(buf, " mrg_rxbuf='%s'",
24669                           virTristateSwitchTypeToString(def->driver.virtio.host.mrg_rxbuf));
24670     }
24671 }
24672 
24673 
24674 static void
virDomainVirtioNetDriverFormat(virBuffer * buf,virDomainNetDef * def)24675 virDomainVirtioNetDriverFormat(virBuffer *buf,
24676                                virDomainNetDef *def)
24677 {
24678     if (def->driver.virtio.name) {
24679         virBufferAsprintf(buf, " name='%s'",
24680                           virDomainNetBackendTypeToString(def->driver.virtio.name));
24681     }
24682     if (def->driver.virtio.txmode) {
24683         virBufferAsprintf(buf, " txmode='%s'",
24684                           virDomainNetVirtioTxModeTypeToString(def->driver.virtio.txmode));
24685     }
24686     if (def->driver.virtio.ioeventfd) {
24687         virBufferAsprintf(buf, " ioeventfd='%s'",
24688                           virTristateSwitchTypeToString(def->driver.virtio.ioeventfd));
24689     }
24690     if (def->driver.virtio.event_idx) {
24691         virBufferAsprintf(buf, " event_idx='%s'",
24692                           virTristateSwitchTypeToString(def->driver.virtio.event_idx));
24693     }
24694     if (def->driver.virtio.queues)
24695         virBufferAsprintf(buf, " queues='%u'", def->driver.virtio.queues);
24696     if (def->driver.virtio.rx_queue_size)
24697         virBufferAsprintf(buf, " rx_queue_size='%u'",
24698                           def->driver.virtio.rx_queue_size);
24699     if (def->driver.virtio.tx_queue_size)
24700         virBufferAsprintf(buf, " tx_queue_size='%u'",
24701                           def->driver.virtio.tx_queue_size);
24702 
24703     virDomainVirtioOptionsFormat(buf, def->virtio);
24704 }
24705 
24706 
24707 static void
virDomainChrSourceReconnectDefFormat(virBuffer * buf,virDomainChrSourceReconnectDef * def)24708 virDomainChrSourceReconnectDefFormat(virBuffer *buf,
24709                                      virDomainChrSourceReconnectDef *def)
24710 {
24711     if (def->enabled == VIR_TRISTATE_BOOL_ABSENT)
24712         return;
24713 
24714     virBufferAsprintf(buf, "<reconnect enabled='%s'",
24715                       virTristateBoolTypeToString(def->enabled));
24716 
24717     if (def->enabled == VIR_TRISTATE_BOOL_YES)
24718         virBufferAsprintf(buf, " timeout='%u'", def->timeout);
24719 
24720     virBufferAddLit(buf, "/>\n");
24721 }
24722 
24723 
24724 static void
virDomainNetTeamingInfoFormat(virDomainNetTeamingInfo * teaming,virBuffer * buf)24725 virDomainNetTeamingInfoFormat(virDomainNetTeamingInfo *teaming,
24726                               virBuffer *buf)
24727 {
24728     if (teaming && teaming->type != VIR_DOMAIN_NET_TEAMING_TYPE_NONE) {
24729         virBufferAsprintf(buf, "<teaming type='%s'",
24730                           virDomainNetTeamingTypeToString(teaming->type));
24731         virBufferEscapeString(buf, " persistent='%s'", teaming->persistent);
24732         virBufferAddLit(buf, "/>\n");
24733     }
24734 }
24735 
24736 
24737 int
virDomainNetDefFormat(virBuffer * buf,virDomainNetDef * def,virDomainXMLOption * xmlopt,unsigned int flags)24738 virDomainNetDefFormat(virBuffer *buf,
24739                       virDomainNetDef *def,
24740                       virDomainXMLOption *xmlopt,
24741                       unsigned int flags)
24742 {
24743     virDomainNetType actualType = virDomainNetGetActualType(def);
24744     bool publicActual = false;
24745     int sourceLines = 0;
24746     const char *typeStr;
24747     virDomainHostdevDef *hostdef = NULL;
24748     char macstr[VIR_MAC_STRING_BUFLEN];
24749     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
24750     const char *prefix = xmlopt ? xmlopt->config.netPrefix : NULL;
24751 
24752     /* publicActual is true if we should report the current state in
24753      * def->data.network.actual *instead of* the config (*not* in
24754      * addition to)
24755      */
24756     if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
24757         def->data.network.actual &&
24758         !(flags & (VIR_DOMAIN_DEF_FORMAT_INACTIVE |
24759                    VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET |
24760                    VIR_DOMAIN_DEF_FORMAT_MIGRATABLE)))
24761         publicActual = true;
24762 
24763     if (publicActual) {
24764         if (!(typeStr = virDomainNetTypeToString(actualType))) {
24765             virReportError(VIR_ERR_INTERNAL_ERROR,
24766                            _("unexpected actual net type %d"), actualType);
24767             return -1;
24768         }
24769         if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV)
24770             hostdef = virDomainNetGetActualHostdev(def);
24771     } else {
24772         if (!(typeStr = virDomainNetTypeToString(def->type))) {
24773             virReportError(VIR_ERR_INTERNAL_ERROR,
24774                            _("unexpected net type %d"), def->type);
24775             return -1;
24776         }
24777         if (def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
24778             hostdef = &def->data.hostdev.def;
24779     }
24780 
24781     virBufferAsprintf(buf, "<interface type='%s'", typeStr);
24782     if (hostdef && hostdef->managed)
24783         virBufferAddLit(buf, " managed='yes'");
24784     if (def->trustGuestRxFilters)
24785         virBufferAsprintf(buf, " trustGuestRxFilters='%s'",
24786                           virTristateBoolTypeToString(def->trustGuestRxFilters));
24787     virBufferAddLit(buf, ">\n");
24788 
24789     virBufferAdjustIndent(buf, 2);
24790     virBufferAsprintf(buf, "<mac address='%s'",
24791                       virMacAddrFormat(&def->mac, macstr));
24792     if (def->mac_type)
24793         virBufferAsprintf(buf, " type='%s'", virDomainNetMacTypeTypeToString(def->mac_type));
24794     if (def->mac_check != VIR_TRISTATE_BOOL_ABSENT)
24795         virBufferAsprintf(buf, " check='%s'", virTristateBoolTypeToString(def->mac_check));
24796     virBufferAddLit(buf, "/>\n");
24797 
24798     if (publicActual) {
24799         /* when there is a virDomainActualNetDef, and we haven't been
24800          * asked to 1) report the domain's inactive XML, or 2) give
24801          * the internal version of the ActualNetDef separately in an
24802          * <actual> subelement, we can just put the ActualDef data in
24803          * the standard place...  (this is for public reporting of
24804          * interface status)
24805          */
24806         if (virDomainActualNetDefContentsFormat(buf, def, false, flags, xmlopt) < 0)
24807             return -1;
24808     } else {
24809         /* ...but if we've asked for the inactive XML (rather than
24810          * status), or to report the ActualDef as a separate <actual>
24811          * subelement (this is how we privately store interface
24812          * status), or there simply *isn't* any ActualNetDef, then
24813          * format the NetDef's data here, and optionally format the
24814          * ActualNetDef as an <actual> subelement of this element.
24815          */
24816         switch (def->type) {
24817         case VIR_DOMAIN_NET_TYPE_NETWORK:
24818             virBufferEscapeString(buf, "<source network='%s'",
24819                                   def->data.network.name);
24820             virBufferEscapeString(buf, " portgroup='%s'",
24821                                   def->data.network.portgroup);
24822             if (virUUIDIsValid(def->data.network.portid) &&
24823                 !(flags & (VIR_DOMAIN_DEF_FORMAT_INACTIVE))) {
24824                 char portidstr[VIR_UUID_STRING_BUFLEN];
24825                 virUUIDFormat(def->data.network.portid, portidstr);
24826                 virBufferEscapeString(buf, " portid='%s'", portidstr);
24827             }
24828             sourceLines++;
24829             break;
24830 
24831         case VIR_DOMAIN_NET_TYPE_ETHERNET:
24832             break;
24833 
24834         case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
24835             if (def->data.vhostuser->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
24836                 virBufferAddLit(buf, "<source type='unix'");
24837                 virBufferEscapeString(buf, " path='%s'",
24838                                       def->data.vhostuser->data.nix.path);
24839                 virBufferAsprintf(buf, " mode='%s'",
24840                                   def->data.vhostuser->data.nix.listen ?
24841                                   "server"  : "client");
24842                 sourceLines++;
24843                 if (def->data.vhostuser->data.nix.reconnect.enabled) {
24844                     virBufferAddLit(buf, ">\n");
24845                     sourceLines++;
24846                     virBufferAdjustIndent(buf, 2);
24847                     virDomainChrSourceReconnectDefFormat(buf,
24848                                                          &def->data.vhostuser->data.nix.reconnect);
24849                     virBufferAdjustIndent(buf, -2);
24850                 }
24851 
24852             }
24853             break;
24854 
24855         case VIR_DOMAIN_NET_TYPE_BRIDGE:
24856            if (def->data.bridge.brname) {
24857                virBufferEscapeString(buf, "<source bridge='%s'",
24858                                      def->data.bridge.brname);
24859                sourceLines++;
24860            }
24861             break;
24862 
24863         case VIR_DOMAIN_NET_TYPE_SERVER:
24864         case VIR_DOMAIN_NET_TYPE_CLIENT:
24865         case VIR_DOMAIN_NET_TYPE_MCAST:
24866         case VIR_DOMAIN_NET_TYPE_UDP:
24867             if (def->data.socket.address) {
24868                 virBufferAsprintf(buf, "<source address='%s' port='%d'",
24869                                   def->data.socket.address,
24870                                   def->data.socket.port);
24871             } else {
24872                 virBufferAsprintf(buf, "<source port='%d'",
24873                                   def->data.socket.port);
24874             }
24875             sourceLines++;
24876 
24877             if (def->type != VIR_DOMAIN_NET_TYPE_UDP)
24878                 break;
24879 
24880             virBufferAddLit(buf, ">\n");
24881             sourceLines++;
24882             virBufferAdjustIndent(buf, 2);
24883 
24884             virBufferAsprintf(buf, "<local address='%s' port='%d'/>\n",
24885                               def->data.socket.localaddr,
24886                               def->data.socket.localport);
24887             virBufferAdjustIndent(buf, -2);
24888             break;
24889 
24890         case VIR_DOMAIN_NET_TYPE_INTERNAL:
24891             if (def->data.internal.name) {
24892                 virBufferEscapeString(buf, "<source name='%s'",
24893                                       def->data.internal.name);
24894                 sourceLines++;
24895             }
24896             break;
24897 
24898         case VIR_DOMAIN_NET_TYPE_DIRECT:
24899             virBufferEscapeString(buf, "<source dev='%s'",
24900                                   def->data.direct.linkdev);
24901             virBufferAsprintf(buf, " mode='%s'",
24902                               virNetDevMacVLanModeTypeToString(def->data.direct.mode));
24903             sourceLines++;
24904             break;
24905 
24906         case VIR_DOMAIN_NET_TYPE_HOSTDEV:
24907             if (virDomainHostdevDefFormatSubsys(buf, &def->data.hostdev.def,
24908                                                 flags, true, xmlopt) < 0) {
24909                 return -1;
24910             }
24911             break;
24912 
24913         case VIR_DOMAIN_NET_TYPE_VDPA:
24914            if (def->data.vdpa.devicepath) {
24915                virBufferEscapeString(buf, "<source dev='%s'",
24916                                      def->data.vdpa.devicepath);
24917                sourceLines++;
24918            }
24919             break;
24920 
24921         case VIR_DOMAIN_NET_TYPE_USER:
24922         case VIR_DOMAIN_NET_TYPE_LAST:
24923             break;
24924         }
24925 
24926         /* if sourceLines == 0 - no <source> info at all so far
24927          *    sourceLines == 1 - first line written, no terminating ">"
24928          *    sourceLines > 1 - multiple lines, including subelements
24929          */
24930         if (def->hostIP.nips || def->hostIP.nroutes) {
24931             if (sourceLines == 0) {
24932                 virBufferAddLit(buf, "<source>\n");
24933                 sourceLines += 2;
24934             } else if (sourceLines == 1) {
24935                 virBufferAddLit(buf, ">\n");
24936                 sourceLines++;
24937             }
24938             virBufferAdjustIndent(buf, 2);
24939             if (virDomainNetIPInfoFormat(buf, &def->hostIP) < 0)
24940                 return -1;
24941             virBufferAdjustIndent(buf, -2);
24942         }
24943         if (sourceLines == 1)
24944             virBufferAddLit(buf, "/>\n");
24945         else if (sourceLines > 1)
24946             virBufferAddLit(buf, "</source>\n");
24947 
24948         if (virNetDevVlanFormat(&def->vlan, buf) < 0)
24949             return -1;
24950         if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
24951             return -1;
24952         if (virNetDevBandwidthFormat(def->bandwidth, 0, buf) < 0)
24953             return -1;
24954         virNetworkPortOptionsFormat(def->isolatedPort, buf);
24955 
24956         /* ONLY for internal status storage - format the ActualNetDef
24957          * as a subelement of <interface> so that no persistent config
24958          * data is overwritten.
24959          */
24960         if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
24961             (flags & VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET) &&
24962             (virDomainActualNetDefFormat(buf, def, flags, xmlopt) < 0))
24963             return -1;
24964 
24965     }
24966 
24967     if (virDomainNetIPInfoFormat(buf, &def->guestIP) < 0)
24968         return -1;
24969 
24970     virBufferEscapeString(buf, "<script path='%s'/>\n",
24971                           def->script);
24972     virBufferEscapeString(buf, "<downscript path='%s'/>\n",
24973                           def->downscript);
24974     virBufferEscapeString(buf, "<backenddomain name='%s'/>\n", def->domain_name);
24975 
24976     if (def->ifname &&
24977         (def->managed_tap == VIR_TRISTATE_BOOL_NO ||
24978          !((flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) &&
24979            (STRPREFIX(def->ifname, VIR_NET_GENERATED_VNET_PREFIX) ||
24980             STRPREFIX(def->ifname, VIR_NET_GENERATED_MACVTAP_PREFIX) ||
24981             STRPREFIX(def->ifname, VIR_NET_GENERATED_MACVLAN_PREFIX) ||
24982             (prefix && STRPREFIX(def->ifname, prefix)))))) {
24983         /* Skip auto-generated target names for inactive config. */
24984         virBufferEscapeString(&attrBuf, " dev='%s'", def->ifname);
24985     }
24986     if (def->managed_tap != VIR_TRISTATE_BOOL_ABSENT) {
24987         virBufferAsprintf(&attrBuf, " managed='%s'",
24988                           virTristateBoolTypeToString(def->managed_tap));
24989     }
24990 
24991     virXMLFormatElement(buf, "target", &attrBuf, NULL);
24992 
24993     if (def->ifname_guest || def->ifname_guest_actual) {
24994         virBufferAddLit(buf, "<guest");
24995         /* Skip auto-generated target names for inactive config. */
24996         if (def->ifname_guest)
24997             virBufferEscapeString(buf, " dev='%s'", def->ifname_guest);
24998 
24999         /* Only set if the host is running, so shouldn't pollute output */
25000         if (def->ifname_guest_actual)
25001             virBufferEscapeString(buf, " actual='%s'", def->ifname_guest_actual);
25002         virBufferAddLit(buf, "/>\n");
25003     }
25004     if (virDomainNetGetModelString(def)) {
25005         virBufferEscapeString(buf, "<model type='%s'/>\n",
25006                               virDomainNetGetModelString(def));
25007         if (virDomainNetIsVirtioModel(def)) {
25008             g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
25009             g_auto(virBuffer) driverChildBuf = VIR_BUFFER_INIT_CHILD(buf);
25010             g_auto(virBuffer) hostAttrBuf = VIR_BUFFER_INITIALIZER;
25011             g_auto(virBuffer) guestAttrBuf = VIR_BUFFER_INITIALIZER;
25012 
25013             virDomainVirtioNetDriverFormat(&driverAttrBuf, def);
25014             virDomainVirtioNetGuestOptsFormat(&guestAttrBuf, def);
25015             virDomainVirtioNetHostOptsFormat(&hostAttrBuf, def);
25016 
25017             virXMLFormatElement(&driverChildBuf, "host", &hostAttrBuf, NULL);
25018             virXMLFormatElement(&driverChildBuf, "guest", &guestAttrBuf, NULL);
25019             virXMLFormatElement(buf, "driver", &driverAttrBuf, &driverChildBuf);
25020         }
25021     }
25022     if (def->backend.tap || def->backend.vhost) {
25023         virBufferAddLit(buf, "<backend");
25024         virBufferEscapeString(buf, " tap='%s'", def->backend.tap);
25025         virBufferEscapeString(buf, " vhost='%s'", def->backend.vhost);
25026         virBufferAddLit(buf, "/>\n");
25027     }
25028     if (def->filter) {
25029         if (virNWFilterFormatParamAttributes(buf, def->filterparams,
25030                                              def->filter) < 0)
25031             return -1;
25032     }
25033 
25034     if (def->tune.sndbuf_specified) {
25035         virBufferAddLit(buf,   "<tune>\n");
25036         virBufferAdjustIndent(buf, 2);
25037         virBufferAsprintf(buf, "<sndbuf>%lu</sndbuf>\n", def->tune.sndbuf);
25038         virBufferAdjustIndent(buf, -2);
25039         virBufferAddLit(buf,   "</tune>\n");
25040     }
25041 
25042     virDomainNetTeamingInfoFormat(def->teaming, buf);
25043 
25044     if (def->linkstate) {
25045         virBufferAsprintf(buf, "<link state='%s'/>\n",
25046                           virDomainNetInterfaceLinkStateTypeToString(def->linkstate));
25047     }
25048 
25049     if (def->mtu)
25050         virBufferAsprintf(buf, "<mtu size='%u'/>\n", def->mtu);
25051 
25052     virDomainNetDefCoalesceFormatXML(buf, def->coalesce);
25053 
25054     virDomainDeviceInfoFormat(buf, &def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT
25055                                                      | VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM);
25056 
25057     virBufferAdjustIndent(buf, -2);
25058     virBufferAddLit(buf, "</interface>\n");
25059     return 0;
25060 }
25061 
25062 
25063 /* Assumes that "<device" has already been generated, and starts
25064  * output at " type='type'>". */
25065 static int
virDomainChrAttrsDefFormat(virBuffer * buf,virDomainChrSourceDef * def,bool tty_compat)25066 virDomainChrAttrsDefFormat(virBuffer *buf,
25067                            virDomainChrSourceDef *def,
25068                            bool tty_compat)
25069 {
25070     const char *type = virDomainChrTypeToString(def->type);
25071 
25072     if (!type) {
25073         virReportError(VIR_ERR_INTERNAL_ERROR,
25074                        _("unexpected char type %d"), def->type);
25075         return -1;
25076     }
25077 
25078     /* Compat with legacy <console tty='/dev/pts/5'/> syntax */
25079     virBufferAsprintf(buf, " type='%s'", type);
25080     if (tty_compat) {
25081         virBufferEscapeString(buf, " tty='%s'",
25082                               def->data.file.path);
25083     }
25084     return 0;
25085 }
25086 
25087 static void
virDomainChrSourceDefFormat(virBuffer * buf,virDomainChrSourceDef * def,unsigned int flags)25088 virDomainChrSourceDefFormat(virBuffer *buf,
25089                             virDomainChrSourceDef *def,
25090                             unsigned int flags)
25091 {
25092     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
25093     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
25094 
25095     switch ((virDomainChrType)def->type) {
25096     case VIR_DOMAIN_CHR_TYPE_NULL:
25097     case VIR_DOMAIN_CHR_TYPE_VC:
25098     case VIR_DOMAIN_CHR_TYPE_STDIO:
25099     case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
25100     case VIR_DOMAIN_CHR_TYPE_LAST:
25101         /* nada */
25102         break;
25103 
25104     case VIR_DOMAIN_CHR_TYPE_PTY:
25105     case VIR_DOMAIN_CHR_TYPE_DEV:
25106     case VIR_DOMAIN_CHR_TYPE_FILE:
25107     case VIR_DOMAIN_CHR_TYPE_PIPE:
25108         if (def->type != VIR_DOMAIN_CHR_TYPE_PTY ||
25109             (def->data.file.path &&
25110              !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))) {
25111             virBufferEscapeString(&attrBuf, " path='%s'",
25112                                   def->data.file.path);
25113             if (def->type == VIR_DOMAIN_CHR_TYPE_FILE &&
25114                 def->data.file.append != VIR_TRISTATE_SWITCH_ABSENT)
25115                 virBufferAsprintf(&attrBuf, " append='%s'",
25116                     virTristateSwitchTypeToString(def->data.file.append));
25117             virDomainSourceDefFormatSeclabel(&childBuf, def->nseclabels,
25118                                              def->seclabels, flags);
25119 
25120             virXMLFormatElement(buf, "source", &attrBuf, &childBuf);
25121         }
25122         break;
25123 
25124     case VIR_DOMAIN_CHR_TYPE_NMDM:
25125         virBufferEscapeString(buf, "<source master='%s' ",
25126                               def->data.nmdm.master);
25127         virBufferEscapeString(buf, "slave='%s'/>\n", def->data.nmdm.slave);
25128         break;
25129 
25130     case VIR_DOMAIN_CHR_TYPE_UDP:
25131         if (def->data.udp.bindService || def->data.udp.bindHost) {
25132             virBufferAddLit(buf, "<source mode='bind'");
25133             virBufferEscapeString(buf, " host='%s'", def->data.udp.bindHost);
25134             virBufferEscapeString(buf, " service='%s'", def->data.udp.bindService);
25135             virBufferAddLit(buf, "/>\n");
25136         }
25137 
25138         if (def->data.udp.connectService || def->data.udp.connectHost) {
25139             virBufferAddLit(buf, "<source mode='connect'");
25140             virBufferEscapeString(buf, " host='%s'", def->data.udp.connectHost);
25141             virBufferEscapeString(buf, " service='%s'", def->data.udp.connectService);
25142             virBufferAddLit(buf, "/>\n");
25143         }
25144         break;
25145 
25146     case VIR_DOMAIN_CHR_TYPE_TCP:
25147         virBufferAsprintf(&attrBuf, " mode='%s' ",
25148                           def->data.tcp.listen ? "bind" : "connect");
25149         virBufferEscapeString(&attrBuf, "host='%s' ", def->data.tcp.host);
25150         virBufferEscapeString(&attrBuf, "service='%s'", def->data.tcp.service);
25151         if (def->data.tcp.haveTLS != VIR_TRISTATE_BOOL_ABSENT &&
25152             !(flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE &&
25153               def->data.tcp.tlsFromConfig))
25154             virBufferAsprintf(&attrBuf, " tls='%s'",
25155                     virTristateBoolTypeToString(def->data.tcp.haveTLS));
25156         if (flags & VIR_DOMAIN_DEF_FORMAT_STATUS)
25157             virBufferAsprintf(&attrBuf, " tlsFromConfig='%d'",
25158                               def->data.tcp.tlsFromConfig);
25159 
25160         virDomainChrSourceReconnectDefFormat(&childBuf,
25161                                              &def->data.tcp.reconnect);
25162 
25163         virXMLFormatElement(buf, "source", &attrBuf, &childBuf);
25164 
25165         virBufferAsprintf(buf, "<protocol type='%s'/>\n",
25166                           virDomainChrTcpProtocolTypeToString(
25167                               def->data.tcp.protocol));
25168         break;
25169 
25170     case VIR_DOMAIN_CHR_TYPE_UNIX:
25171         if (def->data.nix.path) {
25172             virBufferAsprintf(&attrBuf, " mode='%s'",
25173                               def->data.nix.listen ? "bind" : "connect");
25174             virBufferEscapeString(&attrBuf, " path='%s'", def->data.nix.path);
25175             virDomainSourceDefFormatSeclabel(&childBuf, def->nseclabels,
25176                                              def->seclabels, flags);
25177 
25178             virDomainChrSourceReconnectDefFormat(&childBuf,
25179                                                  &def->data.nix.reconnect);
25180 
25181             virXMLFormatElement(buf, "source", &attrBuf, &childBuf);
25182         }
25183         break;
25184 
25185     case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
25186         virBufferEscapeString(buf, "<source channel='%s'/>\n",
25187                               def->data.spiceport.channel);
25188         break;
25189 
25190     }
25191 
25192     if (def->logfile) {
25193         virBufferEscapeString(buf, "<log file='%s'", def->logfile);
25194         if (def->logappend != VIR_TRISTATE_SWITCH_ABSENT) {
25195             virBufferAsprintf(buf, " append='%s'",
25196                               virTristateSwitchTypeToString(def->logappend));
25197         }
25198         virBufferAddLit(buf, "/>\n");
25199     }
25200 }
25201 
25202 
25203 static int
virDomainChrTargetDefFormat(virBuffer * buf,const virDomainChrDef * def,unsigned int flags)25204 virDomainChrTargetDefFormat(virBuffer *buf,
25205                             const virDomainChrDef *def,
25206                             unsigned int flags)
25207 {
25208     const char *targetType = virDomainChrTargetTypeToString(def->deviceType,
25209                                                             def->targetType);
25210 
25211     switch ((virDomainChrDeviceType) def->deviceType) {
25212     case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL: {
25213         if (!targetType) {
25214             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
25215                            _("Could not format channel target type"));
25216             return -1;
25217         }
25218         virBufferAsprintf(buf, "<target type='%s'", targetType);
25219 
25220         switch (def->targetType) {
25221         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD: {
25222             int port = virSocketAddrGetPort(def->target.addr);
25223             g_autofree char *addr = NULL;
25224             if (port < 0) {
25225                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
25226                                _("Unable to format guestfwd port"));
25227                 return -1;
25228             }
25229 
25230             addr = virSocketAddrFormat(def->target.addr);
25231             if (addr == NULL)
25232                 return -1;
25233 
25234             virBufferAsprintf(buf, " address='%s' port='%d'",
25235                               addr, port);
25236             break;
25237         }
25238 
25239         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
25240         case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
25241             if (def->target.name)
25242                 virBufferEscapeString(buf, " name='%s'", def->target.name);
25243 
25244             if (def->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
25245                 def->state != VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT &&
25246                 !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
25247                 virBufferAsprintf(buf, " state='%s'",
25248                                   virDomainChrDeviceStateTypeToString(def->state));
25249             }
25250             break;
25251         }
25252 
25253         virBufferAddLit(buf, "/>\n");
25254         break;
25255     }
25256 
25257     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
25258         if (!targetType) {
25259             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
25260                            _("Could not format console target type"));
25261             return -1;
25262         }
25263 
25264         virBufferAsprintf(buf,
25265                           "<target type='%s' port='%d'/>\n",
25266                           targetType, def->target.port);
25267         break;
25268 
25269     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
25270         if (!targetType) {
25271             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
25272                            _("Could not format serial target type"));
25273             return -1;
25274         }
25275 
25276         virBufferAddLit(buf, "<target ");
25277 
25278         if (def->targetType != VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_NONE) {
25279             virBufferAsprintf(buf,
25280                               "type='%s' ",
25281                               targetType);
25282         }
25283 
25284         virBufferAsprintf(buf,
25285                           "port='%d'",
25286                           def->target.port);
25287 
25288         if (def->targetModel != VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE) {
25289             virBufferAddLit(buf, ">\n");
25290 
25291             virBufferAdjustIndent(buf, 2);
25292             virBufferAsprintf(buf,
25293                               "<model name='%s'/>\n",
25294                               virDomainChrSerialTargetModelTypeToString(def->targetModel));
25295             virBufferAdjustIndent(buf, -2);
25296 
25297             virBufferAddLit(buf, "</target>\n");
25298         } else {
25299             virBufferAddLit(buf, "/>\n");
25300         }
25301 
25302         break;
25303 
25304     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
25305         virBufferAsprintf(buf, "<target port='%d'/>\n",
25306                           def->target.port);
25307         break;
25308 
25309     case VIR_DOMAIN_CHR_DEVICE_TYPE_LAST:
25310         virReportError(VIR_ERR_INTERNAL_ERROR,
25311                        _("unexpected char device type %d"),
25312                        def->deviceType);
25313         return -1;
25314     }
25315 
25316     return 0;
25317 }
25318 
25319 
25320 static int
virDomainChrDefFormat(virBuffer * buf,virDomainChrDef * def,unsigned int flags)25321 virDomainChrDefFormat(virBuffer *buf,
25322                       virDomainChrDef *def,
25323                       unsigned int flags)
25324 {
25325     const char *elementName = virDomainChrDeviceTypeToString(def->deviceType);
25326     bool tty_compat;
25327 
25328     if (!elementName) {
25329         virReportError(VIR_ERR_INTERNAL_ERROR,
25330                        _("unexpected char device type %d"),
25331                        def->deviceType);
25332         return -1;
25333     }
25334 
25335     virBufferAsprintf(buf, "<%s", elementName);
25336     virBufferAdjustIndent(buf, 2);
25337     tty_compat = (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
25338                   def->target.port == 0 &&
25339                   def->source->type == VIR_DOMAIN_CHR_TYPE_PTY &&
25340                   !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE) &&
25341                   def->source->data.file.path);
25342     if (virDomainChrAttrsDefFormat(buf, def->source, tty_compat) < 0)
25343         return -1;
25344     virBufferAddLit(buf, ">\n");
25345 
25346     virDomainChrSourceDefFormat(buf, def->source, flags);
25347 
25348     if (virDomainChrTargetDefFormat(buf, def, flags) < 0)
25349         return -1;
25350 
25351     virDomainDeviceInfoFormat(buf, &def->info, flags);
25352 
25353     virBufferAdjustIndent(buf, -2);
25354     virBufferAsprintf(buf, "</%s>\n", elementName);
25355 
25356     return 0;
25357 }
25358 
25359 static int
virDomainSmartcardDefFormat(virBuffer * buf,virDomainSmartcardDef * def,unsigned int flags)25360 virDomainSmartcardDefFormat(virBuffer *buf,
25361                             virDomainSmartcardDef *def,
25362                             unsigned int flags)
25363 {
25364     const char *mode = virDomainSmartcardTypeToString(def->type);
25365     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
25366     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
25367     size_t i;
25368 
25369     if (!mode) {
25370         virReportError(VIR_ERR_INTERNAL_ERROR,
25371                        _("unexpected smartcard type %d"), def->type);
25372         return -1;
25373     }
25374 
25375     switch (def->type) {
25376     case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
25377         break;
25378 
25379     case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
25380         for (i = 0; i < VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES; i++) {
25381             virBufferEscapeString(&childBuf, "<certificate>%s</certificate>\n",
25382                                   def->data.cert.file[i]);
25383         }
25384         virBufferEscapeString(&childBuf, "<database>%s</database>\n",
25385                               def->data.cert.database);
25386         break;
25387 
25388     case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
25389         virDomainChrSourceDefFormat(&childBuf, def->data.passthru, flags);
25390         break;
25391 
25392     case VIR_DOMAIN_SMARTCARD_TYPE_LAST:
25393     default:
25394         virReportEnumRangeError(virDomainSmartcardType, def->type);
25395         return -1;
25396     }
25397     virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
25398 
25399     virBufferAsprintf(&attrBuf, " mode='%s'", mode);
25400     if (def->type == VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH &&
25401         virDomainChrAttrsDefFormat(&attrBuf, def->data.passthru, false) < 0) {
25402         return -1;
25403     }
25404 
25405     virXMLFormatElement(buf, "smartcard", &attrBuf, &childBuf);
25406 
25407     return 0;
25408 }
25409 
25410 static int
virDomainSoundCodecDefFormat(virBuffer * buf,virDomainSoundCodecDef * def)25411 virDomainSoundCodecDefFormat(virBuffer *buf,
25412                              virDomainSoundCodecDef *def)
25413 {
25414     const char *type = virDomainSoundCodecTypeToString(def->type);
25415 
25416     if (!type) {
25417         virReportError(VIR_ERR_INTERNAL_ERROR,
25418                        _("unexpected codec type %d"), def->type);
25419         return -1;
25420     }
25421 
25422     virBufferAsprintf(buf, "<codec type='%s'/>\n",  type);
25423 
25424     return 0;
25425 }
25426 
25427 static int
virDomainTPMDefFormat(virBuffer * buf,virDomainTPMDef * def,unsigned int flags)25428 virDomainTPMDefFormat(virBuffer *buf,
25429                       virDomainTPMDef *def,
25430                       unsigned int flags)
25431 {
25432     virBufferAsprintf(buf, "<tpm model='%s'>\n",
25433                       virDomainTPMModelTypeToString(def->model));
25434     virBufferAdjustIndent(buf, 2);
25435     virBufferAsprintf(buf, "<backend type='%s'",
25436                       virDomainTPMBackendTypeToString(def->type));
25437 
25438     switch (def->type) {
25439     case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
25440         virBufferAddLit(buf, ">\n");
25441         virBufferAdjustIndent(buf, 2);
25442         virBufferEscapeString(buf, "<device path='%s'/>\n",
25443                               def->data.passthrough.source->data.file.path);
25444         virBufferAdjustIndent(buf, -2);
25445         virBufferAddLit(buf, "</backend>\n");
25446         break;
25447     case VIR_DOMAIN_TPM_TYPE_EMULATOR:
25448         virBufferAsprintf(buf, " version='%s'",
25449                           virDomainTPMVersionTypeToString(def->version));
25450         if (def->data.emulator.persistent_state)
25451             virBufferAddLit(buf, " persistent_state='yes'");
25452         if (def->data.emulator.hassecretuuid) {
25453             char uuidstr[VIR_UUID_STRING_BUFLEN];
25454             virBufferAddLit(buf, ">\n");
25455             virBufferAdjustIndent(buf, 2);
25456             virBufferAsprintf(buf, "<encryption secret='%s'/>\n",
25457                 virUUIDFormat(def->data.emulator.secretuuid, uuidstr));
25458             virBufferAdjustIndent(buf, -2);
25459         }
25460         if (def->data.emulator.activePcrBanks) {
25461             size_t i;
25462             virBufferAddLit(buf, ">\n");
25463             virBufferAdjustIndent(buf, 2);
25464             virBufferAddLit(buf, "<active_pcr_banks>\n");
25465             virBufferAdjustIndent(buf, 2);
25466             for (i = VIR_DOMAIN_TPM_PCR_BANK_SHA1; i < VIR_DOMAIN_TPM_PCR_BANK_LAST; i++) {
25467                 if ((def->data.emulator.activePcrBanks & (1 << i)))
25468                     virBufferAsprintf(buf, "<%s/>\n",
25469                                       virDomainTPMPcrBankTypeToString(i));
25470             }
25471             virBufferAdjustIndent(buf, -2);
25472             virBufferAddLit(buf, "</active_pcr_banks>\n");
25473             virBufferAdjustIndent(buf, -2);
25474         }
25475         if (def->data.emulator.hassecretuuid ||
25476             def->data.emulator.activePcrBanks)
25477             virBufferAddLit(buf, "</backend>\n");
25478         else
25479             virBufferAddLit(buf, "/>\n");
25480         break;
25481     case VIR_DOMAIN_TPM_TYPE_LAST:
25482         break;
25483     }
25484 
25485     virDomainDeviceInfoFormat(buf, &def->info, flags);
25486 
25487     virBufferAdjustIndent(buf, -2);
25488     virBufferAddLit(buf, "</tpm>\n");
25489 
25490     return 0;
25491 }
25492 
25493 
25494 static int
virDomainSoundDefFormat(virBuffer * buf,virDomainSoundDef * def,unsigned int flags)25495 virDomainSoundDefFormat(virBuffer *buf,
25496                         virDomainSoundDef *def,
25497                         unsigned int flags)
25498 {
25499     const char *model = virDomainSoundModelTypeToString(def->model);
25500     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
25501     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
25502     size_t i;
25503 
25504     if (!model) {
25505         virReportError(VIR_ERR_INTERNAL_ERROR,
25506                        _("unexpected sound model %d"), def->model);
25507         return -1;
25508     }
25509 
25510     for (i = 0; i < def->ncodecs; i++)
25511         virDomainSoundCodecDefFormat(&childBuf, def->codecs[i]);
25512 
25513     if (def->audioId > 0)
25514         virBufferAsprintf(&childBuf, "<audio id='%d'/>\n", def->audioId);
25515 
25516     virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
25517 
25518     virBufferAsprintf(&attrBuf, " model='%s'",  model);
25519 
25520     virXMLFormatElement(buf,  "sound", &attrBuf, &childBuf);
25521 
25522     return 0;
25523 }
25524 
25525 
25526 static void
virDomainAudioCommonFormat(virDomainAudioIOCommon * def,virBuffer * childBuf,virBuffer * backendAttrBuf,const char * direction)25527 virDomainAudioCommonFormat(virDomainAudioIOCommon *def,
25528                            virBuffer *childBuf,
25529                            virBuffer *backendAttrBuf,
25530                            const char *direction)
25531 {
25532     g_auto(virBuffer) settingsBuf = VIR_BUFFER_INITIALIZER;
25533 
25534     if (def->fixedSettings == VIR_TRISTATE_BOOL_YES) {
25535         if (def->frequency)
25536             virBufferAsprintf(&settingsBuf, " frequency='%u'",
25537                               def->frequency);
25538         if (def->channels)
25539             virBufferAsprintf(&settingsBuf, " channels='%u'",
25540                               def->channels);
25541         if (def->format)
25542             virBufferAsprintf(&settingsBuf, " format='%s'",
25543                               virDomainAudioFormatTypeToString(def->format));
25544     }
25545 
25546     if (def->mixingEngine || def->fixedSettings ||
25547         def->voices || def->bufferLength ||
25548         virBufferUse(backendAttrBuf)) {
25549         virBufferAsprintf(childBuf, "<%s", direction);
25550         if (def->mixingEngine)
25551             virBufferAsprintf(childBuf, " mixingEngine='%s'",
25552                               virTristateBoolTypeToString(def->mixingEngine));
25553         if (def->fixedSettings)
25554             virBufferAsprintf(childBuf, " fixedSettings='%s'",
25555                               virTristateBoolTypeToString(def->fixedSettings));
25556         if (def->voices)
25557             virBufferAsprintf(childBuf, " voices='%u'",
25558                               def->voices);
25559         if (def->bufferLength)
25560             virBufferAsprintf(childBuf, " bufferLength='%u'",
25561                               def->bufferLength);
25562         if (virBufferUse(backendAttrBuf))
25563             virBufferAdd(childBuf, virBufferCurrentContent(backendAttrBuf), -1);
25564         if (def->fixedSettings == VIR_TRISTATE_BOOL_YES) {
25565             virBufferAddLit(childBuf, ">\n");
25566             virBufferAdjustIndent(childBuf, 2);
25567             virBufferAddLit(childBuf, "<settings");
25568             if (virBufferUse(&settingsBuf)) {
25569                 virBufferAdd(childBuf, virBufferCurrentContent(&settingsBuf), -1);
25570             }
25571             virBufferAddLit(childBuf, "/>\n");
25572             virBufferAdjustIndent(childBuf, -2);
25573             virBufferAsprintf(childBuf, "</%s>\n", direction);
25574         } else {
25575             virBufferAddLit(childBuf, "/>\n");
25576         }
25577     }
25578 }
25579 
25580 
25581 static void
virDomainAudioALSAFormat(virDomainAudioIOALSA * def,virBuffer * buf)25582 virDomainAudioALSAFormat(virDomainAudioIOALSA *def,
25583                          virBuffer *buf)
25584 {
25585     virBufferEscapeString(buf, " dev='%s'", def->dev);
25586 }
25587 
25588 
25589 static void
virDomainAudioCoreAudioFormat(virDomainAudioIOCoreAudio * def,virBuffer * buf)25590 virDomainAudioCoreAudioFormat(virDomainAudioIOCoreAudio *def,
25591                               virBuffer *buf)
25592 {
25593     if (def->bufferCount)
25594         virBufferAsprintf(buf, " bufferCount='%u'", def->bufferCount);
25595 }
25596 
25597 
25598 static void
virDomainAudioJackFormat(virDomainAudioIOJack * def,virBuffer * buf)25599 virDomainAudioJackFormat(virDomainAudioIOJack *def,
25600                          virBuffer *buf)
25601 {
25602     virBufferEscapeString(buf, " serverName='%s'", def->serverName);
25603     virBufferEscapeString(buf, " clientName='%s'", def->clientName);
25604     virBufferEscapeString(buf, " connectPorts='%s'", def->connectPorts);
25605     if (def->exactName)
25606         virBufferAsprintf(buf, " exactName='%s'",
25607                           virTristateBoolTypeToString(def->exactName));
25608 }
25609 
25610 
25611 static void
virDomainAudioOSSFormat(virDomainAudioIOOSS * def,virBuffer * buf)25612 virDomainAudioOSSFormat(virDomainAudioIOOSS *def,
25613                         virBuffer *buf)
25614 {
25615     virBufferEscapeString(buf, " dev='%s'", def->dev);
25616     if (def->bufferCount)
25617         virBufferAsprintf(buf, " bufferCount='%u'", def->bufferCount);
25618     if (def->tryPoll)
25619         virBufferAsprintf(buf, " tryPoll='%s'",
25620                           virTristateBoolTypeToString(def->tryPoll));
25621 }
25622 
25623 
25624 static void
virDomainAudioPulseAudioFormat(virDomainAudioIOPulseAudio * def,virBuffer * buf)25625 virDomainAudioPulseAudioFormat(virDomainAudioIOPulseAudio *def,
25626                                virBuffer *buf)
25627 {
25628     virBufferEscapeString(buf, " name='%s'", def->name);
25629     virBufferEscapeString(buf, " streamName='%s'", def->streamName);
25630     if (def->latency)
25631         virBufferAsprintf(buf, " latency='%u'", def->latency);
25632 
25633 }
25634 
25635 
25636 static void
virDomainAudioSDLFormat(virDomainAudioIOSDL * def,virBuffer * buf)25637 virDomainAudioSDLFormat(virDomainAudioIOSDL *def,
25638                         virBuffer *buf)
25639 {
25640     if (def->bufferCount)
25641         virBufferAsprintf(buf, " bufferCount='%u'", def->bufferCount);
25642 }
25643 
25644 
25645 static int
virDomainAudioDefFormat(virBuffer * buf,virDomainAudioDef * def)25646 virDomainAudioDefFormat(virBuffer *buf,
25647                         virDomainAudioDef *def)
25648 {
25649     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
25650     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
25651     g_auto(virBuffer) inputBuf = VIR_BUFFER_INITIALIZER;
25652     g_auto(virBuffer) outputBuf = VIR_BUFFER_INITIALIZER;
25653     const char *type = virDomainAudioTypeTypeToString(def->type);
25654 
25655     if (!type) {
25656         virReportError(VIR_ERR_INTERNAL_ERROR,
25657                        _("unexpected audio type %d"), def->type);
25658         return -1;
25659     }
25660 
25661     virBufferAsprintf(&attrBuf, " id='%d' type='%s'", def->id, type);
25662 
25663     if (def->timerPeriod)
25664         virBufferAsprintf(&attrBuf, " timerPeriod='%u'", def->timerPeriod);
25665 
25666     switch (def->type) {
25667     case VIR_DOMAIN_AUDIO_TYPE_NONE:
25668         break;
25669 
25670     case VIR_DOMAIN_AUDIO_TYPE_ALSA:
25671         virDomainAudioALSAFormat(&def->backend.alsa.input, &inputBuf);
25672         virDomainAudioALSAFormat(&def->backend.alsa.output, &outputBuf);
25673         break;
25674 
25675     case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
25676         virDomainAudioCoreAudioFormat(&def->backend.coreaudio.input, &inputBuf);
25677         virDomainAudioCoreAudioFormat(&def->backend.coreaudio.output, &outputBuf);
25678         break;
25679 
25680     case VIR_DOMAIN_AUDIO_TYPE_JACK:
25681         virDomainAudioJackFormat(&def->backend.jack.input, &inputBuf);
25682         virDomainAudioJackFormat(&def->backend.jack.output, &outputBuf);
25683         break;
25684 
25685     case VIR_DOMAIN_AUDIO_TYPE_OSS:
25686         if (def->backend.oss.tryMMap)
25687             virBufferAsprintf(&attrBuf, " tryMMap='%s'",
25688                               virTristateBoolTypeToString(def->backend.oss.tryMMap));
25689         if (def->backend.oss.exclusive)
25690             virBufferAsprintf(&attrBuf, " exclusive='%s'",
25691                               virTristateBoolTypeToString(def->backend.oss.exclusive));
25692         if (def->backend.oss.dspPolicySet)
25693             virBufferAsprintf(&attrBuf, " dspPolicy='%d'", def->backend.oss.dspPolicy);
25694 
25695         virDomainAudioOSSFormat(&def->backend.oss.input, &inputBuf);
25696         virDomainAudioOSSFormat(&def->backend.oss.output, &outputBuf);
25697         break;
25698 
25699     case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
25700         virBufferEscapeString(&attrBuf, " serverName='%s'",
25701                               def->backend.pulseaudio.serverName);
25702 
25703         virDomainAudioPulseAudioFormat(&def->backend.pulseaudio.input, &inputBuf);
25704         virDomainAudioPulseAudioFormat(&def->backend.pulseaudio.output, &outputBuf);
25705         break;
25706 
25707     case VIR_DOMAIN_AUDIO_TYPE_SDL:
25708         if (def->backend.sdl.driver)
25709             virBufferAsprintf(&attrBuf, " driver='%s'",
25710                               virDomainAudioSDLDriverTypeToString(
25711                                   def->backend.sdl.driver));
25712 
25713         virDomainAudioSDLFormat(&def->backend.sdl.input, &inputBuf);
25714         virDomainAudioSDLFormat(&def->backend.sdl.output, &outputBuf);
25715         break;
25716 
25717     case VIR_DOMAIN_AUDIO_TYPE_SPICE:
25718         break;
25719 
25720     case VIR_DOMAIN_AUDIO_TYPE_FILE:
25721         virBufferEscapeString(&attrBuf, " path='%s'", def->backend.file.path);
25722         break;
25723 
25724     case VIR_DOMAIN_AUDIO_TYPE_LAST:
25725     default:
25726         virReportEnumRangeError(virDomainAudioType, def->type);
25727         return -1;
25728     }
25729 
25730     virDomainAudioCommonFormat(&def->input, &childBuf, &inputBuf, "input");
25731     virDomainAudioCommonFormat(&def->output, &childBuf, &outputBuf, "output");
25732 
25733     virXMLFormatElement(buf, "audio", &attrBuf, &childBuf);
25734 
25735     return 0;
25736 }
25737 
25738 
25739 static int
virDomainMemballoonDefFormat(virBuffer * buf,virDomainMemballoonDef * def,unsigned int flags)25740 virDomainMemballoonDefFormat(virBuffer *buf,
25741                              virDomainMemballoonDef *def,
25742                              unsigned int flags)
25743 {
25744     const char *model = virDomainMemballoonModelTypeToString(def->model);
25745     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
25746     g_auto(virBuffer) childrenBuf = VIR_BUFFER_INIT_CHILD(buf);
25747     g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
25748 
25749     if (!model) {
25750         virReportError(VIR_ERR_INTERNAL_ERROR,
25751                        _("unexpected memballoon model %d"), def->model);
25752         return -1;
25753     }
25754 
25755     virBufferAsprintf(&attrBuf, " model='%s'", model);
25756 
25757     if (def->autodeflate != VIR_TRISTATE_SWITCH_ABSENT)
25758         virBufferAsprintf(&attrBuf, " autodeflate='%s'",
25759                           virTristateSwitchTypeToString(def->autodeflate));
25760 
25761     if (def->free_page_reporting != VIR_TRISTATE_SWITCH_ABSENT)
25762         virBufferAsprintf(&attrBuf, " freePageReporting='%s'",
25763                           virTristateSwitchTypeToString(def->free_page_reporting));
25764 
25765     if (def->period)
25766         virBufferAsprintf(&childrenBuf, "<stats period='%i'/>\n", def->period);
25767 
25768     virDomainDeviceInfoFormat(&childrenBuf, &def->info, flags);
25769 
25770     virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio);
25771 
25772     virXMLFormatElement(&childrenBuf, "driver", &driverAttrBuf, NULL);
25773     virXMLFormatElement(buf, "memballoon", &attrBuf, &childrenBuf);
25774 
25775     return 0;
25776 }
25777 
25778 static void
virDomainNVRAMDefFormat(virBuffer * buf,virDomainNVRAMDef * def,unsigned int flags)25779 virDomainNVRAMDefFormat(virBuffer *buf,
25780                         virDomainNVRAMDef *def,
25781                         unsigned int flags)
25782 {
25783     virBufferAddLit(buf, "<nvram>\n");
25784     virBufferAdjustIndent(buf, 2);
25785     virDomainDeviceInfoFormat(buf, &def->info, flags);
25786 
25787     virBufferAdjustIndent(buf, -2);
25788     virBufferAddLit(buf, "</nvram>\n");
25789 }
25790 
25791 
25792 static int
virDomainWatchdogDefFormat(virBuffer * buf,virDomainWatchdogDef * def,unsigned int flags)25793 virDomainWatchdogDefFormat(virBuffer *buf,
25794                            virDomainWatchdogDef *def,
25795                            unsigned int flags)
25796 {
25797     const char *model = virDomainWatchdogModelTypeToString(def->model);
25798     const char *action = virDomainWatchdogActionTypeToString(def->action);
25799     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
25800     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
25801 
25802     if (!model) {
25803         virReportError(VIR_ERR_INTERNAL_ERROR,
25804                        _("unexpected watchdog model %d"), def->model);
25805         return -1;
25806     }
25807 
25808     if (!action) {
25809         virReportError(VIR_ERR_INTERNAL_ERROR,
25810                        _("unexpected watchdog action %d"), def->action);
25811         return -1;
25812     }
25813 
25814     virBufferAsprintf(&attrBuf, " model='%s' action='%s'", model, action);
25815 
25816     virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
25817 
25818     virXMLFormatElement(buf, "watchdog", &attrBuf, &childBuf);
25819 
25820     return 0;
25821 }
25822 
virDomainPanicDefFormat(virBuffer * buf,virDomainPanicDef * def)25823 static void virDomainPanicDefFormat(virBuffer *buf, virDomainPanicDef *def)
25824 {
25825     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
25826     g_auto(virBuffer) childrenBuf = VIR_BUFFER_INIT_CHILD(buf);
25827 
25828     if (def->model)
25829         virBufferAsprintf(&attrBuf, " model='%s'",
25830                           virDomainPanicModelTypeToString(def->model));
25831 
25832     virDomainDeviceInfoFormat(&childrenBuf, &def->info, 0);
25833 
25834     virXMLFormatElement(buf, "panic", &attrBuf, &childrenBuf);
25835 }
25836 
25837 static void
virDomainShmemDefFormat(virBuffer * buf,virDomainShmemDef * def,unsigned int flags)25838 virDomainShmemDefFormat(virBuffer *buf,
25839                         virDomainShmemDef *def,
25840                         unsigned int flags)
25841 {
25842     virBufferEscapeString(buf, "<shmem name='%s'", def->name);
25843     if (def->role)
25844         virBufferEscapeString(buf, " role='%s'",
25845                               virDomainShmemRoleTypeToString(def->role));
25846 
25847     virBufferAddLit(buf, ">\n");
25848     virBufferAdjustIndent(buf, 2);
25849 
25850     virBufferAsprintf(buf, "<model type='%s'/>\n",
25851                       virDomainShmemModelTypeToString(def->model));
25852 
25853     if (def->size)
25854         virBufferAsprintf(buf, "<size unit='M'>%llu</size>\n", def->size >> 20);
25855 
25856     if (def->server.enabled) {
25857         virBufferAddLit(buf, "<server");
25858         virBufferEscapeString(buf, " path='%s'", def->server.chr->data.nix.path);
25859         virBufferAddLit(buf, "/>\n");
25860     }
25861 
25862     if (def->msi.enabled) {
25863         virBufferAddLit(buf, "<msi");
25864         if (def->msi.vectors)
25865             virBufferAsprintf(buf, " vectors='%u'", def->msi.vectors);
25866         if (def->msi.ioeventfd)
25867             virBufferAsprintf(buf, " ioeventfd='%s'",
25868                               virTristateSwitchTypeToString(def->msi.ioeventfd));
25869         virBufferAddLit(buf, "/>\n");
25870     }
25871 
25872     virDomainDeviceInfoFormat(buf, &def->info, flags);
25873 
25874     virBufferAdjustIndent(buf, -2);
25875     virBufferAddLit(buf, "</shmem>\n");
25876 }
25877 
25878 static int
virDomainRNGDefFormat(virBuffer * buf,virDomainRNGDef * def,unsigned int flags)25879 virDomainRNGDefFormat(virBuffer *buf,
25880                       virDomainRNGDef *def,
25881                       unsigned int flags)
25882 {
25883     const char *model = virDomainRNGModelTypeToString(def->model);
25884     const char *backend = virDomainRNGBackendTypeToString(def->backend);
25885     g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
25886 
25887     virBufferAsprintf(buf, "<rng model='%s'>\n", model);
25888     virBufferAdjustIndent(buf, 2);
25889     if (def->rate) {
25890         virBufferAsprintf(buf, "<rate bytes='%u'", def->rate);
25891         if (def->period)
25892             virBufferAsprintf(buf, " period='%u'", def->period);
25893         virBufferAddLit(buf, "/>\n");
25894     }
25895     virBufferAsprintf(buf, "<backend model='%s'", backend);
25896 
25897     switch ((virDomainRNGBackend) def->backend) {
25898     case VIR_DOMAIN_RNG_BACKEND_RANDOM:
25899         virBufferEscapeString(buf, ">%s</backend>\n", def->source.file);
25900         break;
25901 
25902     case VIR_DOMAIN_RNG_BACKEND_EGD:
25903         if (virDomainChrAttrsDefFormat(buf, def->source.chardev, false) < 0)
25904             return -1;
25905         virBufferAddLit(buf, ">\n");
25906         virBufferAdjustIndent(buf, 2);
25907         virDomainChrSourceDefFormat(buf, def->source.chardev, flags);
25908         virBufferAdjustIndent(buf, -2);
25909         virBufferAddLit(buf, "</backend>\n");
25910         break;
25911 
25912     case VIR_DOMAIN_RNG_BACKEND_BUILTIN:
25913         virBufferAddLit(buf, "/>\n");
25914         break;
25915 
25916     case VIR_DOMAIN_RNG_BACKEND_LAST:
25917         break;
25918     }
25919 
25920     virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio);
25921 
25922     virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL);
25923 
25924     virDomainDeviceInfoFormat(buf, &def->info, flags);
25925 
25926     virBufferAdjustIndent(buf, -2);
25927     virBufferAddLit(buf, "</rng>\n");
25928 
25929     return 0;
25930 }
25931 
25932 void
virDomainRNGDefFree(virDomainRNGDef * def)25933 virDomainRNGDefFree(virDomainRNGDef *def)
25934 {
25935     if (!def)
25936         return;
25937 
25938     switch ((virDomainRNGBackend) def->backend) {
25939     case VIR_DOMAIN_RNG_BACKEND_RANDOM:
25940         g_free(def->source.file);
25941         break;
25942     case VIR_DOMAIN_RNG_BACKEND_EGD:
25943         virObjectUnref(def->source.chardev);
25944         break;
25945     case VIR_DOMAIN_RNG_BACKEND_BUILTIN:
25946     case VIR_DOMAIN_RNG_BACKEND_LAST:
25947         break;
25948     }
25949 
25950     virDomainDeviceInfoClear(&def->info);
25951     g_free(def->virtio);
25952     g_free(def);
25953 }
25954 
25955 
25956 static int
virDomainMemorySourceDefFormat(virBuffer * buf,virDomainMemoryDef * def)25957 virDomainMemorySourceDefFormat(virBuffer *buf,
25958                                virDomainMemoryDef *def)
25959 {
25960     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
25961     g_autofree char *bitmap = NULL;
25962 
25963     switch (def->model) {
25964     case VIR_DOMAIN_MEMORY_MODEL_DIMM:
25965     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
25966         if (def->sourceNodes) {
25967             if (!(bitmap = virBitmapFormat(def->sourceNodes)))
25968                 return -1;
25969 
25970             virBufferAsprintf(&childBuf, "<nodemask>%s</nodemask>\n", bitmap);
25971         }
25972 
25973         if (def->pagesize)
25974             virBufferAsprintf(&childBuf, "<pagesize unit='KiB'>%llu</pagesize>\n",
25975                               def->pagesize);
25976         break;
25977 
25978     case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
25979         virBufferEscapeString(&childBuf, "<path>%s</path>\n", def->nvdimmPath);
25980 
25981         if (def->alignsize)
25982             virBufferAsprintf(&childBuf, "<alignsize unit='KiB'>%llu</alignsize>\n",
25983                               def->alignsize);
25984 
25985         if (def->nvdimmPmem)
25986             virBufferAddLit(&childBuf, "<pmem/>\n");
25987         break;
25988 
25989     case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
25990         virBufferEscapeString(&childBuf, "<path>%s</path>\n", def->nvdimmPath);
25991         break;
25992 
25993     case VIR_DOMAIN_MEMORY_MODEL_NONE:
25994     case VIR_DOMAIN_MEMORY_MODEL_LAST:
25995         break;
25996     }
25997 
25998     virXMLFormatElement(buf, "source", NULL, &childBuf);
25999 
26000     return 0;
26001 }
26002 
26003 
26004 static void
virDomainMemoryTargetDefFormat(virBuffer * buf,virDomainMemoryDef * def,unsigned int flags)26005 virDomainMemoryTargetDefFormat(virBuffer *buf,
26006                                virDomainMemoryDef *def,
26007                                unsigned int flags)
26008 {
26009     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
26010 
26011     virBufferAsprintf(&childBuf, "<size unit='KiB'>%llu</size>\n", def->size);
26012     if (def->targetNode >= 0)
26013         virBufferAsprintf(&childBuf, "<node>%d</node>\n", def->targetNode);
26014     if (def->labelsize) {
26015         g_auto(virBuffer) labelChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
26016 
26017         virBufferAsprintf(&labelChildBuf, "<size unit='KiB'>%llu</size>\n", def->labelsize);
26018         virXMLFormatElement(&childBuf, "label", NULL, &labelChildBuf);
26019     }
26020     if (def->readonly)
26021         virBufferAddLit(&childBuf, "<readonly/>\n");
26022 
26023     if (def->blocksize) {
26024         virBufferAsprintf(&childBuf, "<block unit='KiB'>%llu</block>\n",
26025                           def->blocksize);
26026 
26027         virBufferAsprintf(&childBuf, "<requested unit='KiB'>%llu</requested>\n",
26028                           def->requestedsize);
26029         if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
26030             virBufferAsprintf(&childBuf, "<current unit='KiB'>%llu</current>\n",
26031                               def->currentsize);
26032         }
26033     }
26034 
26035     virXMLFormatElement(buf, "target", NULL, &childBuf);
26036 }
26037 
26038 static int
virDomainMemoryDefFormat(virBuffer * buf,virDomainMemoryDef * def,unsigned int flags)26039 virDomainMemoryDefFormat(virBuffer *buf,
26040                          virDomainMemoryDef *def,
26041                          unsigned int flags)
26042 {
26043     const char *model = virDomainMemoryModelTypeToString(def->model);
26044 
26045     virBufferAsprintf(buf, "<memory model='%s'", model);
26046     if (def->access)
26047         virBufferAsprintf(buf, " access='%s'",
26048                           virDomainMemoryAccessTypeToString(def->access));
26049     if (def->discard)
26050         virBufferAsprintf(buf, " discard='%s'",
26051                           virTristateBoolTypeToString(def->discard));
26052     virBufferAddLit(buf, ">\n");
26053     virBufferAdjustIndent(buf, 2);
26054 
26055     if (def->uuid) {
26056         char uuidstr[VIR_UUID_STRING_BUFLEN];
26057 
26058         virUUIDFormat(def->uuid, uuidstr);
26059         virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
26060     }
26061 
26062     if (virDomainMemorySourceDefFormat(buf, def) < 0)
26063         return -1;
26064 
26065     virDomainMemoryTargetDefFormat(buf, def, flags);
26066 
26067     virDomainDeviceInfoFormat(buf, &def->info, flags);
26068 
26069     virBufferAdjustIndent(buf, -2);
26070     virBufferAddLit(buf, "</memory>\n");
26071     return 0;
26072 }
26073 
26074 static void
virDomainVideoAccelDefFormat(virBuffer * buf,virDomainVideoAccelDef * def)26075 virDomainVideoAccelDefFormat(virBuffer *buf,
26076                              virDomainVideoAccelDef *def)
26077 {
26078     virBufferAddLit(buf, "<acceleration");
26079     if (def->accel3d) {
26080         virBufferAsprintf(buf, " accel3d='%s'",
26081                           virTristateBoolTypeToString(def->accel3d));
26082     }
26083     if (def->accel2d) {
26084         virBufferAsprintf(buf, " accel2d='%s'",
26085                           virTristateBoolTypeToString(def->accel2d));
26086     }
26087     virBufferEscapeString(buf, " rendernode='%s'", def->rendernode);
26088     virBufferAddLit(buf, "/>\n");
26089 }
26090 
26091 static void
virDomainVideoResolutionDefFormat(virBuffer * buf,virDomainVideoResolutionDef * def)26092 virDomainVideoResolutionDefFormat(virBuffer *buf,
26093                                   virDomainVideoResolutionDef *def)
26094 {
26095     virBufferAddLit(buf, "<resolution");
26096     if (def->x && def->y) {
26097         virBufferAsprintf(buf, " x='%u' y='%u'",
26098                           def->x, def->y);
26099     }
26100     virBufferAddLit(buf, "/>\n");
26101 }
26102 
26103 static int
virDomainVideoDefFormat(virBuffer * buf,virDomainVideoDef * def,unsigned int flags)26104 virDomainVideoDefFormat(virBuffer *buf,
26105                         virDomainVideoDef *def,
26106                         unsigned int flags)
26107 {
26108     const char *model = virDomainVideoTypeToString(def->type);
26109     g_auto(virBuffer) driverBuf = VIR_BUFFER_INITIALIZER;
26110 
26111     if (!model) {
26112         virReportError(VIR_ERR_INTERNAL_ERROR,
26113                        _("unexpected video model %d"), def->type);
26114         return -1;
26115     }
26116 
26117     virBufferAddLit(buf, "<video>\n");
26118     virBufferAdjustIndent(buf, 2);
26119     virDomainVirtioOptionsFormat(&driverBuf, def->virtio);
26120     if (virBufferUse(&driverBuf) || (def->driver && def->driver->vgaconf) ||
26121         def->backend != VIR_DOMAIN_VIDEO_BACKEND_TYPE_DEFAULT) {
26122         virBufferAddLit(buf, "<driver");
26123         if (virBufferUse(&driverBuf))
26124             virBufferAddBuffer(buf, &driverBuf);
26125         if (def->driver && def->driver->vgaconf)
26126             virBufferAsprintf(buf, " vgaconf='%s'",
26127                               virDomainVideoVGAConfTypeToString(def->driver->vgaconf));
26128         if (def->backend != VIR_DOMAIN_VIDEO_BACKEND_TYPE_DEFAULT)
26129             virBufferAsprintf(buf, " name='%s'",
26130                               virDomainVideoBackendTypeToString(def->backend));
26131         virBufferAddLit(buf, "/>\n");
26132     }
26133     virBufferAsprintf(buf, "<model type='%s'",
26134                       model);
26135     if (def->ram)
26136         virBufferAsprintf(buf, " ram='%u'", def->ram);
26137     if (def->vram)
26138         virBufferAsprintf(buf, " vram='%u'", def->vram);
26139     if (def->vram64)
26140         virBufferAsprintf(buf, " vram64='%u'", def->vram64);
26141     if (def->vgamem)
26142         virBufferAsprintf(buf, " vgamem='%u'", def->vgamem);
26143     if (def->heads)
26144         virBufferAsprintf(buf, " heads='%u'", def->heads);
26145     if (def->primary)
26146         virBufferAddLit(buf, " primary='yes'");
26147     if (def->accel || def->res) {
26148         virBufferAddLit(buf, ">\n");
26149         virBufferAdjustIndent(buf, 2);
26150         if (def->accel)
26151             virDomainVideoAccelDefFormat(buf, def->accel);
26152         if (def->res)
26153             virDomainVideoResolutionDefFormat(buf, def->res);
26154         virBufferAdjustIndent(buf, -2);
26155         virBufferAddLit(buf, "</model>\n");
26156     } else {
26157         virBufferAddLit(buf, "/>\n");
26158     }
26159 
26160     virDomainDeviceInfoFormat(buf, &def->info, flags);
26161 
26162     virBufferAdjustIndent(buf, -2);
26163     virBufferAddLit(buf, "</video>\n");
26164 
26165     return 0;
26166 }
26167 
26168 static int
virDomainInputDefFormat(virBuffer * buf,virDomainInputDef * def,unsigned int flags)26169 virDomainInputDefFormat(virBuffer *buf,
26170                         virDomainInputDef *def,
26171                         unsigned int flags)
26172 {
26173     const char *type = virDomainInputTypeToString(def->type);
26174     const char *bus = virDomainInputBusTypeToString(def->bus);
26175     const char *grab = virDomainInputSourceGrabTypeToString(def->source.grab);
26176     const char *grabToggle = virDomainInputSourceGrabToggleTypeToString(def->source.grabToggle);
26177     const char *repeat = virTristateSwitchTypeToString(def->source.repeat);
26178     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
26179     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
26180     g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
26181     g_auto(virBuffer) sourceAttrBuf = VIR_BUFFER_INITIALIZER;
26182 
26183     /* don't format keyboard into migratable XML for backward compatibility */
26184     if (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE &&
26185         def->type == VIR_DOMAIN_INPUT_TYPE_KBD &&
26186         (def->bus == VIR_DOMAIN_INPUT_BUS_PS2 ||
26187          def->bus == VIR_DOMAIN_INPUT_BUS_XEN))
26188         return 0;
26189 
26190     if (!type) {
26191         virReportError(VIR_ERR_INTERNAL_ERROR,
26192                        _("unexpected input type %d"), def->type);
26193         return -1;
26194     }
26195     if (!bus) {
26196         virReportError(VIR_ERR_INTERNAL_ERROR,
26197                        _("unexpected input bus type %d"), def->bus);
26198         return -1;
26199     }
26200 
26201     virBufferAsprintf(&attrBuf, " type='%s'", type);
26202     if (def->bus != VIR_DOMAIN_INPUT_BUS_NONE)
26203         virBufferAsprintf(&attrBuf, " bus='%s'", bus);
26204 
26205     if (def->model) {
26206         const char *model = virDomainInputModelTypeToString(def->model);
26207 
26208         if (!model) {
26209             virReportError(VIR_ERR_INTERNAL_ERROR,
26210                            _("unexpected input model %d"), def->model);
26211             return -1;
26212         }
26213 
26214         virBufferAsprintf(&attrBuf, " model='%s'", model);
26215     }
26216 
26217     virDomainVirtioOptionsFormat(&driverAttrBuf, def->virtio);
26218 
26219     virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL);
26220 
26221     if (def->type == VIR_DOMAIN_INPUT_TYPE_EVDEV)
26222         virBufferEscapeString(&sourceAttrBuf, " dev='%s'", def->source.evdev);
26223     else
26224         virBufferEscapeString(&sourceAttrBuf, " evdev='%s'", def->source.evdev);
26225 
26226     if (def->source.grab)
26227         virBufferAsprintf(&sourceAttrBuf, " grab='%s'", grab);
26228     if (def->source.grabToggle)
26229         virBufferAsprintf(&sourceAttrBuf, " grabToggle='%s'", grabToggle);
26230     if (def->source.repeat)
26231         virBufferAsprintf(&sourceAttrBuf, " repeat='%s'", repeat);
26232 
26233     virXMLFormatElement(&childBuf, "source", &sourceAttrBuf, NULL);
26234 
26235     virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
26236 
26237     virXMLFormatElement(buf, "input", &attrBuf, &childBuf);
26238 
26239     return 0;
26240 }
26241 
26242 
26243 static int
virDomainTimerDefFormat(virBuffer * buf,virDomainTimerDef * def)26244 virDomainTimerDefFormat(virBuffer *buf,
26245                         virDomainTimerDef *def)
26246 {
26247     const char *name = virDomainTimerNameTypeToString(def->name);
26248 
26249     if (!name) {
26250         virReportError(VIR_ERR_INTERNAL_ERROR,
26251                        _("unexpected timer name %d"), def->name);
26252         return -1;
26253     }
26254     virBufferAsprintf(buf, "<timer name='%s'", name);
26255 
26256     if (def->present == 0) {
26257         virBufferAddLit(buf, " present='no'");
26258     } else if (def->present == 1) {
26259         virBufferAddLit(buf, " present='yes'");
26260     }
26261 
26262     if (def->tickpolicy != -1) {
26263         const char *tickpolicy
26264             = virDomainTimerTickpolicyTypeToString(def->tickpolicy);
26265         if (!tickpolicy) {
26266             virReportError(VIR_ERR_INTERNAL_ERROR,
26267                            _("unexpected timer tickpolicy %d"),
26268                            def->tickpolicy);
26269             return -1;
26270         }
26271         virBufferAsprintf(buf, " tickpolicy='%s'", tickpolicy);
26272     }
26273 
26274     if ((def->name == VIR_DOMAIN_TIMER_NAME_PLATFORM)
26275         || (def->name == VIR_DOMAIN_TIMER_NAME_RTC)) {
26276         if (def->track != -1) {
26277             const char *track
26278                 = virDomainTimerTrackTypeToString(def->track);
26279             if (!track) {
26280                 virReportError(VIR_ERR_INTERNAL_ERROR,
26281                                _("unexpected timer track %d"),
26282                                def->track);
26283                 return -1;
26284             }
26285             virBufferAsprintf(buf, " track='%s'", track);
26286         }
26287     }
26288 
26289     if (def->name == VIR_DOMAIN_TIMER_NAME_TSC) {
26290         if (def->frequency > 0)
26291             virBufferAsprintf(buf, " frequency='%llu'", def->frequency);
26292 
26293         if (def->mode != -1) {
26294             const char *mode
26295                 = virDomainTimerModeTypeToString(def->mode);
26296             if (!mode) {
26297                 virReportError(VIR_ERR_INTERNAL_ERROR,
26298                                _("unexpected timer mode %d"),
26299                                def->mode);
26300                 return -1;
26301             }
26302             virBufferAsprintf(buf, " mode='%s'", mode);
26303         }
26304     }
26305 
26306     if (def->catchup.threshold == 0 && def->catchup.slew == 0 &&
26307         def->catchup.limit == 0) {
26308         virBufferAddLit(buf, "/>\n");
26309     } else {
26310         virBufferAddLit(buf, ">\n");
26311         virBufferAdjustIndent(buf, 2);
26312         virBufferAddLit(buf, "<catchup");
26313         if (def->catchup.threshold > 0)
26314             virBufferAsprintf(buf, " threshold='%lu'", def->catchup.threshold);
26315         if (def->catchup.slew > 0)
26316             virBufferAsprintf(buf, " slew='%lu'", def->catchup.slew);
26317         if (def->catchup.limit > 0)
26318             virBufferAsprintf(buf, " limit='%lu'", def->catchup.limit);
26319         virBufferAddLit(buf, "/>\n");
26320         virBufferAdjustIndent(buf, -2);
26321         virBufferAddLit(buf, "</timer>\n");
26322     }
26323 
26324     return 0;
26325 }
26326 
26327 static void
virDomainGraphicsAuthDefFormatAttr(virBuffer * buf,virDomainGraphicsAuthDef * def,unsigned int flags)26328 virDomainGraphicsAuthDefFormatAttr(virBuffer *buf,
26329                                    virDomainGraphicsAuthDef *def,
26330                                    unsigned int flags)
26331 {
26332     if (!def->passwd)
26333         return;
26334 
26335     if (flags & VIR_DOMAIN_DEF_FORMAT_SECURE)
26336         virBufferEscapeString(buf, " passwd='%s'",
26337                               def->passwd);
26338 
26339     if (def->expires) {
26340         g_autoptr(GDateTime) then = NULL;
26341         g_autofree char *thenstr = NULL;
26342 
26343         then = g_date_time_new_from_unix_utc(def->validTo);
26344         thenstr = g_date_time_format(then, "%Y-%m-%dT%H:%M:%S");
26345         virBufferAsprintf(buf, " passwdValidTo='%s'", thenstr);
26346     }
26347 
26348     if (def->connected)
26349         virBufferEscapeString(buf, " connected='%s'",
26350                               virDomainGraphicsAuthConnectedTypeToString(def->connected));
26351 }
26352 
26353 
26354 static void
virDomainGraphicsListenDefFormat(virBuffer * buf,virDomainGraphicsListenDef * def,unsigned int flags)26355 virDomainGraphicsListenDefFormat(virBuffer *buf,
26356                                  virDomainGraphicsListenDef *def,
26357                                  unsigned int flags)
26358 {
26359     /* If generating migratable XML, skip listen address
26360      * dragged in from config file */
26361     if ((flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE) && def->fromConfig)
26362         return;
26363 
26364     virBufferAddLit(buf, "<listen");
26365     virBufferAsprintf(buf, " type='%s'",
26366                       virDomainGraphicsListenTypeToString(def->type));
26367 
26368     if (def->address &&
26369         (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS ||
26370          (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK &&
26371           !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)))) {
26372         /* address may also be set to show current status when type='network',
26373          * but we don't want to print that if INACTIVE data is requested. */
26374         virBufferAsprintf(buf, " address='%s'", def->address);
26375     }
26376 
26377     if (def->network &&
26378         (def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK)) {
26379         virBufferEscapeString(buf, " network='%s'", def->network);
26380     }
26381 
26382     if (def->socket &&
26383         def->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET &&
26384         !(def->autoGenerated &&
26385           (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE))) {
26386         virBufferEscapeString(buf, " socket='%s'", def->socket);
26387     }
26388 
26389     if (flags & VIR_DOMAIN_DEF_FORMAT_STATUS) {
26390         virBufferAsprintf(buf, " fromConfig='%d'", def->fromConfig);
26391         virBufferAsprintf(buf, " autoGenerated='%s'",
26392                           def->autoGenerated ? "yes" : "no");
26393     }
26394 
26395     virBufferAddLit(buf, "/>\n");
26396 }
26397 
26398 
26399 /**
26400  * virDomainGraphicsListenDefFormatAddr:
26401  * @buf: buffer where the output XML is written
26402  * @glisten: first listen element
26403  * @flags: bit-wise or of VIR_DOMAIN_DEF_FORMAT_*
26404  *
26405  * This is used to add a legacy 'listen' attribute into <graphics> element to
26406  * improve backward compatibility.
26407  */
26408 static void
virDomainGraphicsListenDefFormatAddr(virBuffer * buf,virDomainGraphicsListenDef * glisten,unsigned int flags)26409 virDomainGraphicsListenDefFormatAddr(virBuffer *buf,
26410                                      virDomainGraphicsListenDef *glisten,
26411                                      unsigned int flags)
26412 {
26413     if (!glisten)
26414         return;
26415 
26416     if (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE && glisten->fromConfig)
26417         return;
26418 
26419     if (glisten->type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK &&
26420         flags & (VIR_DOMAIN_DEF_FORMAT_INACTIVE |
26421                  VIR_DOMAIN_DEF_FORMAT_MIGRATABLE))
26422         return;
26423 
26424     if (glisten->address)
26425         virBufferAsprintf(buf, " listen='%s'", glisten->address);
26426 }
26427 
26428 static void
virDomainSpiceGLDefFormat(virBuffer * buf,virDomainGraphicsDef * def)26429 virDomainSpiceGLDefFormat(virBuffer *buf, virDomainGraphicsDef *def)
26430 {
26431     if (def->data.spice.gl == VIR_TRISTATE_BOOL_ABSENT)
26432         return;
26433 
26434     virBufferAsprintf(buf, "<gl enable='%s'",
26435                       virTristateBoolTypeToString(def->data.spice.gl));
26436     virBufferEscapeString(buf, " rendernode='%s'", def->data.spice.rendernode);
26437     virBufferAddLit(buf, "/>\n");
26438 }
26439 
26440 static int
virDomainGraphicsDefFormat(virBuffer * buf,virDomainGraphicsDef * def,unsigned int flags)26441 virDomainGraphicsDefFormat(virBuffer *buf,
26442                            virDomainGraphicsDef *def,
26443                            unsigned int flags)
26444 {
26445     virDomainGraphicsListenDef *glisten = virDomainGraphicsGetListen(def, 0);
26446     const char *type = virDomainGraphicsTypeToString(def->type);
26447     bool children = false;
26448     size_t i;
26449 
26450     if (!type) {
26451         virReportError(VIR_ERR_INTERNAL_ERROR,
26452                        _("unexpected net type %d"), def->type);
26453         return -1;
26454     }
26455 
26456     virBufferAsprintf(buf, "<graphics type='%s'", type);
26457 
26458     switch (def->type) {
26459     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
26460         if (!glisten) {
26461             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
26462                            _("missing listen element for graphics"));
26463             return -1;
26464         }
26465 
26466         switch (glisten->type) {
26467         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
26468             /* To not break migration we shouldn't print the 'socket' attribute
26469              * if it's auto-generated or if it's based on config option from
26470              * qemu.conf.  If the socket is provided by user we need to print it
26471              * into migratable XML. */
26472             if (glisten->socket &&
26473                 !((glisten->autoGenerated || glisten->fromConfig) &&
26474                   (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE))) {
26475                 virBufferEscapeString(buf, " socket='%s'", glisten->socket);
26476             }
26477             break;
26478 
26479         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
26480         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
26481             if (def->data.vnc.port &&
26482                 (!def->data.vnc.autoport || !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)))
26483                 virBufferAsprintf(buf, " port='%d'",
26484                                   def->data.vnc.port);
26485             else if (def->data.vnc.autoport)
26486                 virBufferAddLit(buf, " port='-1'");
26487 
26488             virBufferAsprintf(buf, " autoport='%s'",
26489                               def->data.vnc.autoport ? "yes" : "no");
26490 
26491             if (def->data.vnc.websocketGenerated &&
26492                 (flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
26493                 virBufferAddLit(buf, " websocket='-1'");
26494             else if (def->data.vnc.websocket)
26495                 virBufferAsprintf(buf, " websocket='%d'", def->data.vnc.websocket);
26496 
26497             if (flags & VIR_DOMAIN_DEF_FORMAT_STATUS)
26498                 virBufferAsprintf(buf, " websocketGenerated='%s'",
26499                                   def->data.vnc.websocketGenerated ? "yes" : "no");
26500 
26501             virDomainGraphicsListenDefFormatAddr(buf, glisten, flags);
26502             break;
26503         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
26504         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
26505             break;
26506         }
26507 
26508         if (def->data.vnc.keymap)
26509             virBufferEscapeString(buf, " keymap='%s'",
26510                                   def->data.vnc.keymap);
26511 
26512         if (def->data.vnc.sharePolicy)
26513             virBufferAsprintf(buf, " sharePolicy='%s'",
26514                               virDomainGraphicsVNCSharePolicyTypeToString(
26515                               def->data.vnc.sharePolicy));
26516 
26517         if (def->data.vnc.powerControl)
26518             virBufferAsprintf(buf, " powerControl='%s'",
26519                               virTristateBoolTypeToString(def->data.vnc.powerControl));
26520 
26521         virDomainGraphicsAuthDefFormatAttr(buf, &def->data.vnc.auth, flags);
26522         break;
26523 
26524     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
26525         if (def->data.sdl.display)
26526             virBufferEscapeString(buf, " display='%s'",
26527                                   def->data.sdl.display);
26528 
26529         if (def->data.sdl.xauth)
26530             virBufferEscapeString(buf, " xauth='%s'",
26531                                   def->data.sdl.xauth);
26532         if (def->data.sdl.fullscreen)
26533             virBufferAddLit(buf, " fullscreen='yes'");
26534 
26535         if (!children && def->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT) {
26536             virBufferAddLit(buf, ">\n");
26537             virBufferAdjustIndent(buf, 2);
26538             children = true;
26539         }
26540 
26541         if (def->data.sdl.gl != VIR_TRISTATE_BOOL_ABSENT) {
26542             virBufferAsprintf(buf, "<gl enable='%s'",
26543                               virTristateBoolTypeToString(def->data.sdl.gl));
26544             virBufferAddLit(buf, "/>\n");
26545         }
26546 
26547         break;
26548 
26549     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
26550         if (def->data.rdp.port)
26551             virBufferAsprintf(buf, " port='%d'",
26552                               def->data.rdp.port);
26553         else if (def->data.rdp.autoport)
26554             virBufferAddLit(buf, " port='0'");
26555 
26556         if (def->data.rdp.autoport)
26557             virBufferAddLit(buf, " autoport='yes'");
26558 
26559         if (def->data.rdp.replaceUser)
26560             virBufferAddLit(buf, " replaceUser='yes'");
26561 
26562         if (def->data.rdp.multiUser)
26563             virBufferAddLit(buf, " multiUser='yes'");
26564 
26565         virDomainGraphicsListenDefFormatAddr(buf, glisten, flags);
26566 
26567         break;
26568 
26569     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
26570         if (def->data.desktop.display)
26571             virBufferEscapeString(buf, " display='%s'",
26572                                   def->data.desktop.display);
26573 
26574         if (def->data.desktop.fullscreen)
26575             virBufferAddLit(buf, " fullscreen='yes'");
26576 
26577         break;
26578 
26579     case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
26580         if (!glisten) {
26581             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
26582                            _("missing listen element for spice graphics"));
26583             return -1;
26584         }
26585 
26586         switch (glisten->type) {
26587         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS:
26588         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK:
26589             if (def->data.spice.port)
26590                 virBufferAsprintf(buf, " port='%d'",
26591                                   def->data.spice.port);
26592 
26593             if (def->data.spice.tlsPort)
26594                 virBufferAsprintf(buf, " tlsPort='%d'",
26595                                   def->data.spice.tlsPort);
26596 
26597             virBufferAsprintf(buf, " autoport='%s'",
26598                               def->data.spice.autoport ? "yes" : "no");
26599 
26600             virDomainGraphicsListenDefFormatAddr(buf, glisten, flags);
26601             break;
26602 
26603         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE:
26604             if (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE)
26605                 virBufferAddStr(buf, " autoport='no'");
26606             break;
26607 
26608         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET:
26609             /* If socket is auto-generated based on config option we don't
26610              * add any listen element into migratable XML because the original
26611              * listen type is "address".
26612              * We need to set autoport to make sure that libvirt on destination
26613              * will parse it as listen type "address", without autoport it is
26614              * parsed as listen type "none". */
26615             if ((flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE) &&
26616                 glisten->fromConfig) {
26617                 virBufferAddStr(buf, " autoport='yes'");
26618             }
26619             break;
26620 
26621         case VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST:
26622             break;
26623         }
26624 
26625         if (def->data.spice.keymap)
26626             virBufferEscapeString(buf, " keymap='%s'",
26627                                   def->data.spice.keymap);
26628 
26629         if (def->data.spice.defaultMode != VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY)
26630             virBufferAsprintf(buf, " defaultMode='%s'",
26631               virDomainGraphicsSpiceChannelModeTypeToString(def->data.spice.defaultMode));
26632 
26633         virDomainGraphicsAuthDefFormatAttr(buf, &def->data.spice.auth, flags);
26634         break;
26635 
26636     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
26637         if (!def->data.egl_headless.rendernode)
26638             break;
26639 
26640         if (!children) {
26641             virBufferAddLit(buf, ">\n");
26642             virBufferAdjustIndent(buf, 2);
26643             children = true;
26644         }
26645 
26646         virBufferAddLit(buf, "<gl");
26647         virBufferEscapeString(buf, " rendernode='%s'",
26648                               def->data.egl_headless.rendernode);
26649         virBufferAddLit(buf, "/>\n");
26650         break;
26651     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
26652         break;
26653     }
26654 
26655     for (i = 0; i < def->nListens; i++) {
26656         if (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE) {
26657             /* If the listen is based on config options from qemu.conf we need
26658              * to skip it.  It's up to user to properly configure both hosts for
26659              * migration. */
26660             if (def->listens[i].fromConfig)
26661                 continue;
26662 
26663             /* If the socket is provided by user in the XML we need to skip this
26664              * listen type to support migration back to old libvirt since old
26665              * libvirt supports specifying socket path inside graphics element
26666              * as 'socket' attribute.  Auto-generated socket is a new feature
26667              * thus we can generate it in the migrateble XML. */
26668             if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
26669                 def->listens[i].type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET &&
26670                 def->listens[i].socket &&
26671                 !def->listens[i].autoGenerated)
26672                 continue;
26673 
26674             /* The new listen type none is in the migratable XML represented as
26675              * port=0 and autoport=no because old libvirt support this
26676              * configuration for spice. */
26677             if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
26678                 def->listens[i].type == VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NONE)
26679                 continue;
26680         }
26681         if (!children) {
26682             virBufferAddLit(buf, ">\n");
26683             virBufferAdjustIndent(buf, 2);
26684             children = true;
26685         }
26686         virDomainGraphicsListenDefFormat(buf, &def->listens[i], flags);
26687     }
26688 
26689     if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) {
26690         for (i = 0; i < VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST; i++) {
26691             int mode = def->data.spice.channels[i];
26692             if (mode == VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY)
26693                 continue;
26694 
26695             if (!children) {
26696                 virBufferAddLit(buf, ">\n");
26697                 virBufferAdjustIndent(buf, 2);
26698                 children = true;
26699             }
26700 
26701             virBufferAsprintf(buf, "<channel name='%s' mode='%s'/>\n",
26702                               virDomainGraphicsSpiceChannelNameTypeToString(i),
26703                               virDomainGraphicsSpiceChannelModeTypeToString(mode));
26704         }
26705         if (!children && (def->data.spice.image || def->data.spice.jpeg ||
26706                           def->data.spice.zlib || def->data.spice.playback ||
26707                           def->data.spice.streaming || def->data.spice.copypaste ||
26708                           def->data.spice.mousemode || def->data.spice.filetransfer ||
26709                           def->data.spice.gl)) {
26710             virBufferAddLit(buf, ">\n");
26711             virBufferAdjustIndent(buf, 2);
26712             children = true;
26713         }
26714         if (def->data.spice.image)
26715             virBufferAsprintf(buf, "<image compression='%s'/>\n",
26716                               virDomainGraphicsSpiceImageCompressionTypeToString(def->data.spice.image));
26717         if (def->data.spice.jpeg)
26718             virBufferAsprintf(buf, "<jpeg compression='%s'/>\n",
26719                               virDomainGraphicsSpiceJpegCompressionTypeToString(def->data.spice.jpeg));
26720         if (def->data.spice.zlib)
26721             virBufferAsprintf(buf, "<zlib compression='%s'/>\n",
26722                               virDomainGraphicsSpiceZlibCompressionTypeToString(def->data.spice.zlib));
26723         if (def->data.spice.playback)
26724             virBufferAsprintf(buf, "<playback compression='%s'/>\n",
26725                               virTristateSwitchTypeToString(def->data.spice.playback));
26726         if (def->data.spice.streaming)
26727             virBufferAsprintf(buf, "<streaming mode='%s'/>\n",
26728                               virDomainGraphicsSpiceStreamingModeTypeToString(def->data.spice.streaming));
26729         if (def->data.spice.mousemode)
26730             virBufferAsprintf(buf, "<mouse mode='%s'/>\n",
26731                               virDomainGraphicsSpiceMouseModeTypeToString(def->data.spice.mousemode));
26732         if (def->data.spice.copypaste)
26733             virBufferAsprintf(buf, "<clipboard copypaste='%s'/>\n",
26734                               virTristateBoolTypeToString(def->data.spice.copypaste));
26735         if (def->data.spice.filetransfer)
26736             virBufferAsprintf(buf, "<filetransfer enable='%s'/>\n",
26737                               virTristateBoolTypeToString(def->data.spice.filetransfer));
26738 
26739         virDomainSpiceGLDefFormat(buf, def);
26740     }
26741 
26742     if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
26743         if (!children) {
26744             virBufferAddLit(buf, ">\n");
26745             virBufferAdjustIndent(buf, 2);
26746             children = true;
26747         }
26748 
26749         if (def->data.vnc.audioId > 0)
26750             virBufferAsprintf(buf, "<audio id='%d'/>\n",
26751                               def->data.vnc.audioId);
26752     }
26753 
26754     if (children) {
26755         virBufferAdjustIndent(buf, -2);
26756         virBufferAddLit(buf, "</graphics>\n");
26757     } else {
26758         virBufferAddLit(buf, "/>\n");
26759     }
26760 
26761     return 0;
26762 }
26763 
26764 
26765 static int
virDomainHostdevDefFormat(virBuffer * buf,virDomainHostdevDef * def,unsigned int flags,virDomainXMLOption * xmlopt)26766 virDomainHostdevDefFormat(virBuffer *buf,
26767                           virDomainHostdevDef *def,
26768                           unsigned int flags,
26769                           virDomainXMLOption *xmlopt)
26770 {
26771     const char *mode = virDomainHostdevModeTypeToString(def->mode);
26772     virDomainHostdevSubsysSCSI *scsisrc = &def->source.subsys.u.scsi;
26773     virDomainHostdevSubsysMediatedDev *mdevsrc = &def->source.subsys.u.mdev;
26774     virDomainHostdevSubsysSCSIVHost *scsihostsrc = &def->source.subsys.u.scsi_host;
26775     const char *type;
26776 
26777     if (!mode) {
26778         virReportError(VIR_ERR_INTERNAL_ERROR,
26779                        _("unexpected hostdev mode %d"), def->mode);
26780         return -1;
26781     }
26782 
26783     switch (def->mode) {
26784     case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
26785         type = virDomainHostdevSubsysTypeToString(def->source.subsys.type);
26786         if (!type) {
26787             virReportError(VIR_ERR_INTERNAL_ERROR,
26788                            _("unexpected hostdev type %d"),
26789                            def->source.subsys.type);
26790             return -1;
26791         }
26792         break;
26793     case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
26794         type = virDomainHostdevCapsTypeToString(def->source.caps.type);
26795         if (!type) {
26796             virReportError(VIR_ERR_INTERNAL_ERROR,
26797                            _("unexpected hostdev type %d"),
26798                            def->source.caps.type);
26799             return -1;
26800         }
26801         break;
26802     default:
26803         virReportError(VIR_ERR_INTERNAL_ERROR,
26804                        _("unexpected hostdev mode %d"), def->mode);
26805         return -1;
26806     }
26807 
26808     virBufferAsprintf(buf, "<hostdev mode='%s' type='%s'",
26809                       mode, type);
26810     if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
26811         virBufferAsprintf(buf, " managed='%s'",
26812                           def->managed ? "yes" : "no");
26813 
26814         if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
26815             scsisrc->sgio)
26816             virBufferAsprintf(buf, " sgio='%s'",
26817                               virDomainDeviceSGIOTypeToString(scsisrc->sgio));
26818 
26819         if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
26820             scsisrc->rawio) {
26821             virBufferAsprintf(buf, " rawio='%s'",
26822                               virTristateBoolTypeToString(scsisrc->rawio));
26823         }
26824 
26825         if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST &&
26826             scsihostsrc->model) {
26827             virBufferAsprintf(buf, " model='%s'",
26828                               virDomainHostdevSubsysSCSIVHostModelTypeToString(scsihostsrc->model));
26829         }
26830 
26831         if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV) {
26832             virBufferAsprintf(buf, " model='%s'",
26833                               virMediatedDeviceModelTypeToString(mdevsrc->model));
26834             if (mdevsrc->display != VIR_TRISTATE_SWITCH_ABSENT)
26835                 virBufferAsprintf(buf, " display='%s'",
26836                                   virTristateSwitchTypeToString(mdevsrc->display));
26837             if (mdevsrc->ramfb != VIR_TRISTATE_SWITCH_ABSENT)
26838                 virBufferAsprintf(buf, " ramfb='%s'",
26839                                   virTristateSwitchTypeToString(mdevsrc->ramfb));
26840         }
26841 
26842     }
26843     virBufferAddLit(buf, ">\n");
26844     virBufferAdjustIndent(buf, 2);
26845 
26846     switch (def->mode) {
26847     case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
26848         if (virDomainHostdevDefFormatSubsys(buf, def, flags, false, xmlopt) < 0)
26849             return -1;
26850         break;
26851     case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
26852         if (virDomainHostdevDefFormatCaps(buf, def) < 0)
26853             return -1;
26854         break;
26855     }
26856 
26857     virDomainNetTeamingInfoFormat(def->teaming, buf);
26858 
26859     if (def->readonly)
26860         virBufferAddLit(buf, "<readonly/>\n");
26861     if (def->shareable)
26862         virBufferAddLit(buf, "<shareable/>\n");
26863 
26864     virDomainDeviceInfoFormat(buf, def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT
26865                                                     | VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM);
26866 
26867     virBufferAdjustIndent(buf, -2);
26868     virBufferAddLit(buf, "</hostdev>\n");
26869 
26870     return 0;
26871 }
26872 
26873 static int
virDomainRedirdevDefFormat(virBuffer * buf,virDomainRedirdevDef * def,unsigned int flags)26874 virDomainRedirdevDefFormat(virBuffer *buf,
26875                            virDomainRedirdevDef *def,
26876                            unsigned int flags)
26877 {
26878     const char *bus;
26879 
26880     bus = virDomainRedirdevBusTypeToString(def->bus);
26881 
26882     virBufferAsprintf(buf, "<redirdev bus='%s'", bus);
26883     if (virDomainChrAttrsDefFormat(buf, def->source, false) < 0)
26884         return -1;
26885     virBufferAddLit(buf, ">\n");
26886     virBufferAdjustIndent(buf, 2);
26887 
26888     virDomainChrSourceDefFormat(buf, def->source, flags);
26889 
26890     virDomainDeviceInfoFormat(buf, &def->info, flags | VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT);
26891     virBufferAdjustIndent(buf, -2);
26892     virBufferAddLit(buf, "</redirdev>\n");
26893     return 0;
26894 }
26895 
26896 static void
virDomainRedirFilterDefFormat(virBuffer * buf,virDomainRedirFilterDef * filter)26897 virDomainRedirFilterDefFormat(virBuffer *buf,
26898                               virDomainRedirFilterDef *filter)
26899 {
26900     size_t i;
26901 
26902     /* no need format an empty redirfilter */
26903     if (filter->nusbdevs == 0)
26904         return;
26905 
26906     virBufferAddLit(buf, "<redirfilter>\n");
26907     virBufferAdjustIndent(buf, 2);
26908     for (i = 0; i < filter->nusbdevs; i++) {
26909         virDomainRedirFilterUSBDevDef *usbdev = filter->usbdevs[i];
26910         virBufferAddLit(buf, "<usbdev");
26911         if (usbdev->usbClass >= 0)
26912             virBufferAsprintf(buf, " class='0x%02X'", usbdev->usbClass);
26913 
26914         if (usbdev->vendor >= 0)
26915             virBufferAsprintf(buf, " vendor='0x%04X'", usbdev->vendor);
26916 
26917         if (usbdev->product >= 0)
26918             virBufferAsprintf(buf, " product='0x%04X'", usbdev->product);
26919 
26920         if (usbdev->version >= 0)
26921             virBufferAsprintf(buf, " version='%d.%02d'",
26922                                  ((usbdev->version & 0xf000) >> 12) * 10 +
26923                                  ((usbdev->version & 0x0f00) >>  8),
26924                                  ((usbdev->version & 0x00f0) >>  4) * 10 +
26925                                  ((usbdev->version & 0x000f) >>  0));
26926 
26927         virBufferAsprintf(buf, " allow='%s'/>\n", usbdev->allow ? "yes" : "no");
26928 
26929     }
26930     virBufferAdjustIndent(buf, -2);
26931     virBufferAddLit(buf, "</redirfilter>\n");
26932 }
26933 
26934 static int
virDomainHubDefFormat(virBuffer * buf,virDomainHubDef * def,unsigned int flags)26935 virDomainHubDefFormat(virBuffer *buf,
26936                       virDomainHubDef *def,
26937                       unsigned int flags)
26938 {
26939     const char *type = virDomainHubTypeToString(def->type);
26940     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
26941     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
26942 
26943     if (!type) {
26944         virReportError(VIR_ERR_INTERNAL_ERROR,
26945                        _("unexpected hub type %d"), def->type);
26946         return -1;
26947     }
26948 
26949     virDomainDeviceInfoFormat(&childBuf, &def->info, flags);
26950 
26951     virBufferAsprintf(&attrBuf, " type='%s'", type);
26952 
26953     virXMLFormatElement(buf, "hub", &attrBuf, &childBuf);
26954 
26955     return 0;
26956 }
26957 
26958 
26959 static void
virDomainResourceDefFormat(virBuffer * buf,virDomainResourceDef * def)26960 virDomainResourceDefFormat(virBuffer *buf,
26961                            virDomainResourceDef *def)
26962 {
26963     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
26964 
26965     if (!def)
26966         return;
26967 
26968     if (def->partition)
26969         virBufferEscapeString(&childBuf, "<partition>%s</partition>\n", def->partition);
26970 
26971     if (def->appid)
26972         virBufferEscapeString(&childBuf, "<fibrechannel appid='%s'/>\n", def->appid);
26973 
26974     virXMLFormatElement(buf, "resource", NULL, &childBuf);
26975 }
26976 
26977 
26978 static int
virDomainHugepagesFormatBuf(virBuffer * buf,virDomainHugePage * hugepage)26979 virDomainHugepagesFormatBuf(virBuffer *buf,
26980                             virDomainHugePage *hugepage)
26981 {
26982     virBufferAsprintf(buf, "<page size='%llu' unit='KiB'",
26983                       hugepage->size);
26984 
26985     if (hugepage->nodemask) {
26986         g_autofree char *nodeset = NULL;
26987         if (!(nodeset = virBitmapFormat(hugepage->nodemask)))
26988             return -1;
26989         virBufferAsprintf(buf, " nodeset='%s'", nodeset);
26990     }
26991 
26992     virBufferAddLit(buf, "/>\n");
26993 
26994     return 0;
26995 }
26996 
26997 static void
virDomainHugepagesFormat(virBuffer * buf,virDomainHugePage * hugepages,size_t nhugepages)26998 virDomainHugepagesFormat(virBuffer *buf,
26999                          virDomainHugePage *hugepages,
27000                          size_t nhugepages)
27001 {
27002     size_t i;
27003 
27004     if (nhugepages == 1 &&
27005         hugepages[0].size == 0) {
27006         virBufferAddLit(buf, "<hugepages/>\n");
27007         return;
27008     }
27009 
27010     virBufferAddLit(buf, "<hugepages>\n");
27011     virBufferAdjustIndent(buf, 2);
27012 
27013     for (i = 0; i < nhugepages; i++)
27014         virDomainHugepagesFormatBuf(buf, &hugepages[i]);
27015 
27016     virBufferAdjustIndent(buf, -2);
27017     virBufferAddLit(buf, "</hugepages>\n");
27018 }
27019 
27020 static void
virDomainLoaderDefFormat(virBuffer * buf,virDomainLoaderDef * loader)27021 virDomainLoaderDefFormat(virBuffer *buf,
27022                          virDomainLoaderDef *loader)
27023 {
27024     const char *readonly = virTristateBoolTypeToString(loader->readonly);
27025     const char *secure = virTristateBoolTypeToString(loader->secure);
27026     const char *type = virDomainLoaderTypeToString(loader->type);
27027 
27028     virBufferAddLit(buf, "<loader");
27029 
27030     if (loader->readonly)
27031         virBufferAsprintf(buf, " readonly='%s'", readonly);
27032 
27033     if (loader->secure)
27034         virBufferAsprintf(buf, " secure='%s'", secure);
27035 
27036     if (loader->type != VIR_DOMAIN_LOADER_TYPE_NONE)
27037         virBufferAsprintf(buf, " type='%s'", type);
27038 
27039     if (loader->path)
27040         virBufferEscapeString(buf, ">%s</loader>\n", loader->path);
27041     else
27042         virBufferAddLit(buf, "/>\n");
27043 
27044     if (loader->nvram || loader->templt) {
27045         virBufferAddLit(buf, "<nvram");
27046         virBufferEscapeString(buf, " template='%s'", loader->templt);
27047         if (loader->nvram)
27048             virBufferEscapeString(buf, ">%s</nvram>\n", loader->nvram);
27049         else
27050             virBufferAddLit(buf, "/>\n");
27051     }
27052 }
27053 
27054 static void
virDomainKeyWrapDefFormat(virBuffer * buf,virDomainKeyWrapDef * keywrap)27055 virDomainKeyWrapDefFormat(virBuffer *buf, virDomainKeyWrapDef *keywrap)
27056 {
27057     virBufferAddLit(buf, "<keywrap>\n");
27058     virBufferAdjustIndent(buf, 2);
27059 
27060     if (keywrap->aes)
27061         virBufferAsprintf(buf, "<cipher name='aes' state='%s'/>\n",
27062                           virTristateSwitchTypeToString(keywrap->aes));
27063 
27064     if (keywrap->dea)
27065         virBufferAsprintf(buf, "<cipher name='dea' state='%s'/>\n",
27066                           virTristateSwitchTypeToString(keywrap->dea));
27067 
27068     virBufferAdjustIndent(buf, -2);
27069     virBufferAddLit(buf, "</keywrap>\n");
27070 }
27071 
27072 
27073 static void
virDomainSecDefFormat(virBuffer * buf,virDomainSecDef * sec)27074 virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec)
27075 {
27076     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
27077     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
27078 
27079     if (!sec)
27080         return;
27081 
27082     virBufferAsprintf(&attrBuf, " type='%s'",
27083                       virDomainLaunchSecurityTypeToString(sec->sectype));
27084 
27085     switch ((virDomainLaunchSecurity) sec->sectype) {
27086     case VIR_DOMAIN_LAUNCH_SECURITY_SEV: {
27087         virDomainSEVDef *sev = &sec->data.sev;
27088 
27089         if (sev->haveCbitpos)
27090             virBufferAsprintf(&childBuf, "<cbitpos>%d</cbitpos>\n", sev->cbitpos);
27091 
27092         if (sev->haveReducedPhysBits)
27093             virBufferAsprintf(&childBuf, "<reducedPhysBits>%d</reducedPhysBits>\n",
27094                               sev->reduced_phys_bits);
27095         virBufferAsprintf(&childBuf, "<policy>0x%04x</policy>\n", sev->policy);
27096         if (sev->dh_cert)
27097             virBufferEscapeString(&childBuf, "<dhCert>%s</dhCert>\n", sev->dh_cert);
27098 
27099         if (sev->session)
27100             virBufferEscapeString(&childBuf, "<session>%s</session>\n", sev->session);
27101 
27102         break;
27103     }
27104 
27105     case VIR_DOMAIN_LAUNCH_SECURITY_PV:
27106         break;
27107 
27108     case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
27109     case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
27110         return;
27111     }
27112 
27113     virXMLFormatElement(buf, "launchSecurity", &attrBuf, &childBuf);
27114 }
27115 
27116 
27117 static void
virDomainPerfDefFormat(virBuffer * buf,virDomainPerfDef * perf)27118 virDomainPerfDefFormat(virBuffer *buf, virDomainPerfDef *perf)
27119 {
27120     size_t i;
27121     bool wantPerf = false;
27122 
27123     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
27124         if (perf->events[i])
27125             wantPerf = true;
27126     }
27127     if (!wantPerf)
27128         return;
27129 
27130     virBufferAddLit(buf, "<perf>\n");
27131     virBufferAdjustIndent(buf, 2);
27132 
27133     for (i = 0; i < VIR_PERF_EVENT_LAST; i++) {
27134         if (perf->events[i])
27135             virBufferAsprintf(buf, "<event name='%s' enabled='%s'/>\n",
27136                               virPerfEventTypeToString(i),
27137                               virTristateBoolTypeToString(perf->events[i]));
27138     }
27139 
27140     virBufferAdjustIndent(buf, -2);
27141     virBufferAddLit(buf, "</perf>\n");
27142 }
27143 
27144 
27145 static void
virDomainSchedulerFormat(virBuffer * buf,const char * name,virDomainThreadSchedParam * sched,size_t id,bool multiple_threads)27146 virDomainSchedulerFormat(virBuffer *buf,
27147                          const char *name,
27148                          virDomainThreadSchedParam *sched,
27149                          size_t id,
27150                          bool multiple_threads)
27151 {
27152     switch (sched->policy) {
27153         case VIR_PROC_POLICY_BATCH:
27154         case VIR_PROC_POLICY_IDLE:
27155             virBufferAsprintf(buf, "<%ssched", name);
27156             if (multiple_threads)
27157                 virBufferAsprintf(buf, " %ss='%zu'", name, id);
27158             virBufferAsprintf(buf, " scheduler='%s'/>\n",
27159                               virProcessSchedPolicyTypeToString(sched->policy));
27160             break;
27161 
27162         case VIR_PROC_POLICY_RR:
27163         case VIR_PROC_POLICY_FIFO:
27164             virBufferAsprintf(buf, "<%ssched", name);
27165             if (multiple_threads)
27166                 virBufferAsprintf(buf, " %ss='%zu'", name, id);
27167             virBufferAsprintf(buf, " scheduler='%s' priority='%d'/>\n",
27168                               virProcessSchedPolicyTypeToString(sched->policy),
27169                               sched->priority);
27170             break;
27171 
27172         case VIR_PROC_POLICY_NONE:
27173         case VIR_PROC_POLICY_LAST:
27174             break;
27175         }
27176 
27177 }
27178 
27179 
27180 static int
virDomainCachetuneDefFormatHelper(unsigned int level,virCacheType type,unsigned int cache,unsigned long long size,void * opaque)27181 virDomainCachetuneDefFormatHelper(unsigned int level,
27182                                   virCacheType type,
27183                                   unsigned int cache,
27184                                   unsigned long long size,
27185                                   void *opaque)
27186 {
27187     const char *unit;
27188     virBuffer *buf = opaque;
27189     unsigned long long short_size = virFormatIntPretty(size, &unit);
27190 
27191     virBufferAsprintf(buf,
27192                       "<cache id='%u' level='%u' type='%s' "
27193                       "size='%llu' unit='%s'/>\n",
27194                       cache, level, virCacheTypeToString(type),
27195                       short_size, unit);
27196 
27197     return 0;
27198 }
27199 
27200 
27201 static int
virDomainResctrlMonDefFormatHelper(virDomainResctrlMonDef * domresmon,virResctrlMonitorType tag,virBuffer * buf)27202 virDomainResctrlMonDefFormatHelper(virDomainResctrlMonDef *domresmon,
27203                                    virResctrlMonitorType tag,
27204                                    virBuffer *buf)
27205 {
27206     g_autofree char *vcpus = NULL;
27207 
27208     if (domresmon->tag != tag)
27209         return 0;
27210 
27211     virBufferAddLit(buf, "<monitor ");
27212 
27213     if (tag == VIR_RESCTRL_MONITOR_TYPE_CACHE) {
27214         virBufferAsprintf(buf, "level='%u' ",
27215                           VIR_DOMAIN_RESCTRL_MONITOR_CACHELEVEL);
27216     }
27217 
27218     vcpus = virBitmapFormat(domresmon->vcpus);
27219     if (!vcpus)
27220         return -1;
27221 
27222     virBufferAsprintf(buf, "vcpus='%s'/>\n", vcpus);
27223 
27224     return 0;
27225 }
27226 
27227 
27228 static int
virDomainCachetuneDefFormat(virBuffer * buf,virDomainResctrlDef * resctrl,unsigned int flags)27229 virDomainCachetuneDefFormat(virBuffer *buf,
27230                             virDomainResctrlDef *resctrl,
27231                             unsigned int flags)
27232 {
27233     g_auto(virBuffer) childrenBuf = VIR_BUFFER_INIT_CHILD(buf);
27234     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
27235     size_t i = 0;
27236     g_autofree char *vcpus = NULL;
27237 
27238     if (virResctrlAllocForeachCache(resctrl->alloc,
27239                                     virDomainCachetuneDefFormatHelper,
27240                                     &childrenBuf) < 0)
27241         return -1;
27242 
27243     for (i = 0; i < resctrl->nmonitors; i++) {
27244         if (virDomainResctrlMonDefFormatHelper(resctrl->monitors[i],
27245                                                VIR_RESCTRL_MONITOR_TYPE_CACHE,
27246                                                &childrenBuf) < 0)
27247             return -1;
27248     }
27249 
27250     if (!virBufferUse(&childrenBuf))
27251         return 0;
27252 
27253     vcpus = virBitmapFormat(resctrl->vcpus);
27254     if (!vcpus)
27255         return -1;
27256 
27257     virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
27258 
27259     if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
27260         const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
27261         if (!alloc_id)
27262             return -1;
27263 
27264         virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
27265     }
27266 
27267     virXMLFormatElement(buf, "cachetune", &attrBuf, &childrenBuf);
27268 
27269     return 0;
27270 }
27271 
27272 
27273 static int
virDomainMemorytuneDefFormatHelper(unsigned int id,unsigned int bandwidth,void * opaque)27274 virDomainMemorytuneDefFormatHelper(unsigned int id,
27275                                    unsigned int bandwidth,
27276                                    void *opaque)
27277 {
27278     virBuffer *buf = opaque;
27279 
27280     virBufferAsprintf(buf,
27281                       "<node id='%u' bandwidth='%u'/>\n",
27282                       id, bandwidth);
27283     return 0;
27284 }
27285 
27286 
27287 static int
virDomainMemorytuneDefFormat(virBuffer * buf,virDomainResctrlDef * resctrl,unsigned int flags)27288 virDomainMemorytuneDefFormat(virBuffer *buf,
27289                             virDomainResctrlDef *resctrl,
27290                             unsigned int flags)
27291 {
27292     g_auto(virBuffer) childrenBuf = VIR_BUFFER_INIT_CHILD(buf);
27293     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
27294     g_autofree char *vcpus = NULL;
27295     size_t i = 0;
27296 
27297     if (virResctrlAllocForeachMemory(resctrl->alloc,
27298                                      virDomainMemorytuneDefFormatHelper,
27299                                      &childrenBuf) < 0)
27300         return -1;
27301 
27302     for (i = 0; i< resctrl->nmonitors; i++) {
27303         if (virDomainResctrlMonDefFormatHelper(resctrl->monitors[i],
27304                                                VIR_RESCTRL_MONITOR_TYPE_MEMBW,
27305                                                &childrenBuf) < 0)
27306             return -1;
27307     }
27308 
27309     if (!virBufferUse(&childrenBuf))
27310         return 0;
27311 
27312     vcpus = virBitmapFormat(resctrl->vcpus);
27313     if (!vcpus)
27314         return -1;
27315 
27316     virBufferAsprintf(&attrBuf, " vcpus='%s'", vcpus);
27317 
27318     if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
27319         const char *alloc_id = virResctrlAllocGetID(resctrl->alloc);
27320         if (!alloc_id)
27321             return -1;
27322 
27323         virBufferAsprintf(&attrBuf, " id='%s'", alloc_id);
27324     }
27325 
27326     virXMLFormatElement(buf, "memorytune", &attrBuf, &childrenBuf);
27327 
27328     return 0;
27329 }
27330 
27331 static int
virDomainCputuneDefFormat(virBuffer * buf,virDomainDef * def,unsigned int flags)27332 virDomainCputuneDefFormat(virBuffer *buf,
27333                           virDomainDef *def,
27334                           unsigned int flags)
27335 {
27336     size_t i;
27337     g_auto(virBuffer) childrenBuf = VIR_BUFFER_INIT_CHILD(buf);
27338 
27339 
27340     if (def->cputune.sharesSpecified)
27341         virBufferAsprintf(&childrenBuf, "<shares>%llu</shares>\n",
27342                           def->cputune.shares);
27343     if (def->cputune.period)
27344         virBufferAsprintf(&childrenBuf, "<period>%llu</period>\n",
27345                           def->cputune.period);
27346     if (def->cputune.quota)
27347         virBufferAsprintf(&childrenBuf, "<quota>%lld</quota>\n",
27348                           def->cputune.quota);
27349     if (def->cputune.global_period)
27350         virBufferAsprintf(&childrenBuf, "<global_period>%llu</global_period>\n",
27351                           def->cputune.global_period);
27352     if (def->cputune.global_quota)
27353         virBufferAsprintf(&childrenBuf, "<global_quota>%lld</global_quota>\n",
27354                           def->cputune.global_quota);
27355 
27356     if (def->cputune.emulator_period)
27357         virBufferAsprintf(&childrenBuf, "<emulator_period>%llu"
27358                           "</emulator_period>\n",
27359                           def->cputune.emulator_period);
27360 
27361     if (def->cputune.emulator_quota)
27362         virBufferAsprintf(&childrenBuf, "<emulator_quota>%lld"
27363                           "</emulator_quota>\n",
27364                           def->cputune.emulator_quota);
27365 
27366     if (def->cputune.iothread_period)
27367         virBufferAsprintf(&childrenBuf, "<iothread_period>%llu"
27368                           "</iothread_period>\n",
27369                           def->cputune.iothread_period);
27370 
27371     if (def->cputune.iothread_quota)
27372         virBufferAsprintf(&childrenBuf, "<iothread_quota>%lld"
27373                           "</iothread_quota>\n",
27374                           def->cputune.iothread_quota);
27375 
27376     for (i = 0; i < def->maxvcpus; i++) {
27377         char *cpumask;
27378         virDomainVcpuDef *vcpu = def->vcpus[i];
27379 
27380         if (!vcpu->cpumask)
27381             continue;
27382 
27383         if (!(cpumask = virBitmapFormat(vcpu->cpumask)))
27384             return -1;
27385 
27386         virBufferAsprintf(&childrenBuf,
27387                           "<vcpupin vcpu='%zu' cpuset='%s'/>\n", i, cpumask);
27388 
27389         VIR_FREE(cpumask);
27390     }
27391 
27392     if (def->cputune.emulatorpin) {
27393         char *cpumask;
27394         virBufferAddLit(&childrenBuf, "<emulatorpin ");
27395 
27396         if (!(cpumask = virBitmapFormat(def->cputune.emulatorpin)))
27397             return -1;
27398 
27399         virBufferAsprintf(&childrenBuf, "cpuset='%s'/>\n", cpumask);
27400         VIR_FREE(cpumask);
27401     }
27402 
27403     for (i = 0; i < def->niothreadids; i++) {
27404         char *cpumask;
27405 
27406         /* Ignore iothreadids with no cpumask */
27407         if (!def->iothreadids[i]->cpumask)
27408             continue;
27409 
27410         virBufferAsprintf(&childrenBuf, "<iothreadpin iothread='%u' ",
27411                           def->iothreadids[i]->iothread_id);
27412 
27413         if (!(cpumask = virBitmapFormat(def->iothreadids[i]->cpumask)))
27414             return -1;
27415 
27416         virBufferAsprintf(&childrenBuf, "cpuset='%s'/>\n", cpumask);
27417         VIR_FREE(cpumask);
27418     }
27419 
27420     if (def->cputune.emulatorsched) {
27421         virDomainSchedulerFormat(&childrenBuf, "emulator",
27422                                  def->cputune.emulatorsched, 0, false);
27423     }
27424 
27425     for (i = 0; i < def->maxvcpus; i++) {
27426         virDomainSchedulerFormat(&childrenBuf, "vcpu",
27427                                  &def->vcpus[i]->sched, i, true);
27428     }
27429 
27430     for (i = 0; i < def->niothreadids; i++) {
27431         virDomainSchedulerFormat(&childrenBuf, "iothread",
27432                                  &def->iothreadids[i]->sched,
27433                                  def->iothreadids[i]->iothread_id,
27434                                  true);
27435     }
27436 
27437     for (i = 0; i < def->nresctrls; i++)
27438         virDomainCachetuneDefFormat(&childrenBuf, def->resctrls[i], flags);
27439 
27440     for (i = 0; i < def->nresctrls; i++)
27441         virDomainMemorytuneDefFormat(&childrenBuf, def->resctrls[i], flags);
27442 
27443     virXMLFormatElement(buf, "cputune", NULL, &childrenBuf);
27444 
27445     return 0;
27446 }
27447 
27448 
27449 static int
virDomainCpuDefFormat(virBuffer * buf,const virDomainDef * def)27450 virDomainCpuDefFormat(virBuffer *buf,
27451                       const virDomainDef *def)
27452 {
27453     virDomainVcpuDef *vcpu;
27454     size_t i;
27455     g_autofree char *cpumask = NULL;
27456 
27457     virBufferAddLit(buf, "<vcpu");
27458     virBufferAsprintf(buf, " placement='%s'",
27459                       virDomainCpuPlacementModeTypeToString(def->placement_mode));
27460 
27461     if (def->cpumask && !virBitmapIsAllSet(def->cpumask)) {
27462         if ((cpumask = virBitmapFormat(def->cpumask)) == NULL)
27463             return -1;
27464         virBufferAsprintf(buf, " cpuset='%s'", cpumask);
27465     }
27466     if (virDomainDefHasVcpusOffline(def))
27467         virBufferAsprintf(buf, " current='%u'", virDomainDefGetVcpus(def));
27468     virBufferAsprintf(buf, ">%u</vcpu>\n", virDomainDefGetVcpusMax(def));
27469 
27470     if (def->individualvcpus) {
27471         virBufferAddLit(buf, "<vcpus>\n");
27472         virBufferAdjustIndent(buf, 2);
27473         for (i = 0; i < def->maxvcpus; i++) {
27474             vcpu = def->vcpus[i];
27475 
27476             virBufferAsprintf(buf, "<vcpu id='%zu' enabled='%s'",
27477                               i, vcpu->online ? "yes" : "no");
27478             if (vcpu->hotpluggable)
27479                 virBufferAsprintf(buf, " hotpluggable='%s'",
27480                                   virTristateBoolTypeToString(vcpu->hotpluggable));
27481 
27482             if (vcpu->order != 0)
27483                 virBufferAsprintf(buf, " order='%d'", vcpu->order);
27484 
27485             virBufferAddLit(buf, "/>\n");
27486         }
27487         virBufferAdjustIndent(buf, -2);
27488         virBufferAddLit(buf, "</vcpus>\n");
27489     }
27490 
27491     return 0;
27492 }
27493 
27494 
27495 static bool
virDomainDefIothreadShouldFormat(virDomainDef * def)27496 virDomainDefIothreadShouldFormat(virDomainDef *def)
27497 {
27498     size_t i;
27499 
27500     for (i = 0; i < def->niothreadids; i++) {
27501         if (!def->iothreadids[i]->autofill)
27502             return true;
27503     }
27504 
27505     return false;
27506 }
27507 
27508 
27509 static void
virDomainIOMMUDefFormat(virBuffer * buf,const virDomainIOMMUDef * iommu)27510 virDomainIOMMUDefFormat(virBuffer *buf,
27511                         const virDomainIOMMUDef *iommu)
27512 {
27513     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
27514     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
27515     g_auto(virBuffer) driverAttrBuf = VIR_BUFFER_INITIALIZER;
27516 
27517     if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT) {
27518         virBufferAsprintf(&driverAttrBuf, " intremap='%s'",
27519                           virTristateSwitchTypeToString(iommu->intremap));
27520     }
27521     if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT) {
27522         virBufferAsprintf(&driverAttrBuf, " caching_mode='%s'",
27523                           virTristateSwitchTypeToString(iommu->caching_mode));
27524     }
27525     if (iommu->eim != VIR_TRISTATE_SWITCH_ABSENT) {
27526         virBufferAsprintf(&driverAttrBuf, " eim='%s'",
27527                           virTristateSwitchTypeToString(iommu->eim));
27528     }
27529     if (iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT) {
27530         virBufferAsprintf(&driverAttrBuf, " iotlb='%s'",
27531                           virTristateSwitchTypeToString(iommu->iotlb));
27532     }
27533     if (iommu->aw_bits > 0) {
27534         virBufferAsprintf(&driverAttrBuf, " aw_bits='%d'",
27535                           iommu->aw_bits);
27536     }
27537 
27538     virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL);
27539 
27540     virBufferAsprintf(&attrBuf, " model='%s'",
27541                       virDomainIOMMUModelTypeToString(iommu->model));
27542 
27543     virXMLFormatElement(buf, "iommu", &attrBuf, &childBuf);
27544 }
27545 
27546 
27547 static void
virDomainMemtuneFormat(virBuffer * buf,const virDomainMemtune * mem)27548 virDomainMemtuneFormat(virBuffer *buf,
27549                        const virDomainMemtune *mem)
27550 {
27551     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
27552 
27553     if (virMemoryLimitIsSet(mem->hard_limit)) {
27554         virBufferAsprintf(&childBuf,
27555                           "<hard_limit unit='KiB'>%llu</hard_limit>\n",
27556                           mem->hard_limit);
27557     }
27558     if (virMemoryLimitIsSet(mem->soft_limit)) {
27559         virBufferAsprintf(&childBuf,
27560                           "<soft_limit unit='KiB'>%llu</soft_limit>\n",
27561                           mem->soft_limit);
27562     }
27563     if (mem->min_guarantee) {
27564         virBufferAsprintf(&childBuf,
27565                           "<min_guarantee unit='KiB'>%llu</min_guarantee>\n",
27566                           mem->min_guarantee);
27567     }
27568     if (virMemoryLimitIsSet(mem->swap_hard_limit)) {
27569         virBufferAsprintf(&childBuf,
27570                           "<swap_hard_limit unit='KiB'>%llu</swap_hard_limit>\n",
27571                           mem->swap_hard_limit);
27572     }
27573 
27574     virXMLFormatElement(buf, "memtune", NULL, &childBuf);
27575 }
27576 
27577 
27578 static void
virDomainMemorybackingFormat(virBuffer * buf,const virDomainMemtune * mem)27579 virDomainMemorybackingFormat(virBuffer *buf,
27580                              const virDomainMemtune *mem)
27581 {
27582     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
27583 
27584     if (mem->nhugepages)
27585         virDomainHugepagesFormat(&childBuf, mem->hugepages, mem->nhugepages);
27586     if (mem->nosharepages)
27587         virBufferAddLit(&childBuf, "<nosharepages/>\n");
27588     if (mem->locked)
27589         virBufferAddLit(&childBuf, "<locked/>\n");
27590     if (mem->source)
27591         virBufferAsprintf(&childBuf, "<source type='%s'/>\n",
27592                           virDomainMemorySourceTypeToString(mem->source));
27593     if (mem->access)
27594         virBufferAsprintf(&childBuf, "<access mode='%s'/>\n",
27595                           virDomainMemoryAccessTypeToString(mem->access));
27596     if (mem->allocation)
27597         virBufferAsprintf(&childBuf, "<allocation mode='%s'/>\n",
27598                           virDomainMemoryAllocationTypeToString(mem->allocation));
27599     if (mem->discard)
27600         virBufferAddLit(&childBuf, "<discard/>\n");
27601 
27602     virXMLFormatElement(buf, "memoryBacking", NULL, &childBuf);
27603 }
27604 
27605 
27606 static void
virDomainVsockDefFormat(virBuffer * buf,virDomainVsockDef * vsock)27607 virDomainVsockDefFormat(virBuffer *buf,
27608                         virDomainVsockDef *vsock)
27609 {
27610     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
27611     g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
27612     g_auto(virBuffer) cidAttrBuf = VIR_BUFFER_INITIALIZER;
27613     g_auto(virBuffer) drvAttrBuf = VIR_BUFFER_INITIALIZER;
27614 
27615     if (vsock->model) {
27616         virBufferAsprintf(&attrBuf, " model='%s'",
27617                           virDomainVsockModelTypeToString(vsock->model));
27618     }
27619 
27620     if (vsock->auto_cid != VIR_TRISTATE_BOOL_ABSENT) {
27621         virBufferAsprintf(&cidAttrBuf, " auto='%s'",
27622                           virTristateBoolTypeToString(vsock->auto_cid));
27623     }
27624     if (vsock->guest_cid != 0)
27625         virBufferAsprintf(&cidAttrBuf, " address='%u'", vsock->guest_cid);
27626     virXMLFormatElement(&childBuf, "cid", &cidAttrBuf, NULL);
27627 
27628     virDomainDeviceInfoFormat(&childBuf, &vsock->info, 0);
27629 
27630     virDomainVirtioOptionsFormat(&drvAttrBuf, vsock->virtio);
27631 
27632     virXMLFormatElement(&childBuf, "driver", &drvAttrBuf, NULL);
27633     virXMLFormatElement(buf, "vsock", &attrBuf, &childBuf);
27634 }
27635 
27636 
27637 static void
virDomainDefFormatBlkiotune(virBuffer * buf,virDomainDef * def)27638 virDomainDefFormatBlkiotune(virBuffer *buf,
27639                             virDomainDef *def)
27640 {
27641     g_auto(virBuffer) childrenBuf = VIR_BUFFER_INIT_CHILD(buf);
27642     ssize_t n;
27643 
27644     if (def->blkio.weight)
27645         virBufferAsprintf(&childrenBuf, "<weight>%u</weight>\n",
27646                           def->blkio.weight);
27647 
27648     for (n = 0; n < def->blkio.ndevices; n++) {
27649         virBlkioDevice *dev = &def->blkio.devices[n];
27650 
27651         if (!dev->weight && !dev->riops && !dev->wiops &&
27652             !dev->rbps && !dev->wbps)
27653             continue;
27654         virBufferAddLit(&childrenBuf, "<device>\n");
27655         virBufferAdjustIndent(&childrenBuf, 2);
27656         virBufferEscapeString(&childrenBuf, "<path>%s</path>\n",
27657                               dev->path);
27658         if (dev->weight)
27659             virBufferAsprintf(&childrenBuf, "<weight>%u</weight>\n",
27660                               dev->weight);
27661         if (dev->riops)
27662             virBufferAsprintf(&childrenBuf, "<read_iops_sec>%u</read_iops_sec>\n",
27663                               dev->riops);
27664         if (dev->wiops)
27665             virBufferAsprintf(&childrenBuf, "<write_iops_sec>%u</write_iops_sec>\n",
27666                               dev->wiops);
27667         if (dev->rbps)
27668             virBufferAsprintf(&childrenBuf, "<read_bytes_sec>%llu</read_bytes_sec>\n",
27669                               dev->rbps);
27670         if (dev->wbps)
27671             virBufferAsprintf(&childrenBuf, "<write_bytes_sec>%llu</write_bytes_sec>\n",
27672                               dev->wbps);
27673         virBufferAdjustIndent(&childrenBuf, -2);
27674         virBufferAddLit(&childrenBuf, "</device>\n");
27675     }
27676 
27677     virXMLFormatElement(buf, "blkiotune", NULL, &childrenBuf);
27678 }
27679 
27680 
27681 static int
virDomainDefFormatFeatures(virBuffer * buf,virDomainDef * def)27682 virDomainDefFormatFeatures(virBuffer *buf,
27683                            virDomainDef *def)
27684 {
27685     g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
27686     size_t i;
27687 
27688     for (i = 0; i < VIR_DOMAIN_FEATURE_LAST; i++) {
27689         g_auto(virBuffer) tmpAttrBuf = VIR_BUFFER_INITIALIZER;
27690         g_auto(virBuffer) tmpChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
27691         const char *name = virDomainFeatureTypeToString(i);
27692         size_t j;
27693 
27694         switch ((virDomainFeature) i) {
27695         case VIR_DOMAIN_FEATURE_ACPI:
27696         case VIR_DOMAIN_FEATURE_PAE:
27697         case VIR_DOMAIN_FEATURE_VIRIDIAN:
27698         case VIR_DOMAIN_FEATURE_PRIVNET:
27699             /* NOTE: This is for old style <opt/> booleans. New XML
27700              * should use the explicit state=on|off output below */
27701             switch ((virTristateSwitch) def->features[i]) {
27702             case VIR_TRISTATE_SWITCH_ABSENT:
27703                 break;
27704 
27705             case VIR_TRISTATE_SWITCH_ON:
27706                virBufferAsprintf(&childBuf, "<%s/>\n", name);
27707                break;
27708 
27709             case VIR_TRISTATE_SWITCH_LAST:
27710             case VIR_TRISTATE_SWITCH_OFF:
27711                virReportError(VIR_ERR_INTERNAL_ERROR,
27712                              _("Unexpected state of feature '%s'"), name);
27713                return -1;
27714                break;
27715             }
27716 
27717             break;
27718 
27719         case VIR_DOMAIN_FEATURE_VMCOREINFO:
27720         case VIR_DOMAIN_FEATURE_HAP:
27721         case VIR_DOMAIN_FEATURE_PMU:
27722         case VIR_DOMAIN_FEATURE_PVSPINLOCK:
27723         case VIR_DOMAIN_FEATURE_VMPORT:
27724         case VIR_DOMAIN_FEATURE_HTM:
27725         case VIR_DOMAIN_FEATURE_NESTED_HV:
27726         case VIR_DOMAIN_FEATURE_CCF_ASSIST:
27727             switch ((virTristateSwitch) def->features[i]) {
27728             case VIR_TRISTATE_SWITCH_LAST:
27729             case VIR_TRISTATE_SWITCH_ABSENT:
27730                 break;
27731 
27732             case VIR_TRISTATE_SWITCH_ON:
27733                virBufferAsprintf(&childBuf, "<%s state='on'/>\n", name);
27734                break;
27735 
27736             case VIR_TRISTATE_SWITCH_OFF:
27737                virBufferAsprintf(&childBuf, "<%s state='off'/>\n", name);
27738                break;
27739             }
27740 
27741             break;
27742 
27743         case VIR_DOMAIN_FEATURE_SMM:
27744             if (def->features[i] == VIR_TRISTATE_SWITCH_ABSENT)
27745                 break;
27746 
27747             virBufferAsprintf(&tmpAttrBuf, " state='%s'",
27748                               virTristateSwitchTypeToString(def->features[i]));
27749 
27750             if (def->features[i] == VIR_TRISTATE_SWITCH_ON &&
27751                 def->tseg_specified) {
27752                 const char *unit;
27753                 unsigned long long short_size = virFormatIntPretty(def->tseg_size,
27754                                                                    &unit);
27755 
27756                 virBufferAsprintf(&tmpChildBuf, "<tseg unit='%s'>%llu</tseg>\n",
27757                                   unit, short_size);
27758             }
27759 
27760             virXMLFormatElement(&childBuf, "smm", &tmpAttrBuf, &tmpChildBuf);
27761 
27762             break;
27763 
27764         case VIR_DOMAIN_FEATURE_APIC:
27765             if (def->features[i] == VIR_TRISTATE_SWITCH_ON) {
27766                 virBufferAddLit(&childBuf, "<apic");
27767                 if (def->apic_eoi) {
27768                     virBufferAsprintf(&childBuf, " eoi='%s'",
27769                                       virTristateSwitchTypeToString(def->apic_eoi));
27770                 }
27771                 virBufferAddLit(&childBuf, "/>\n");
27772             }
27773             break;
27774 
27775         case VIR_DOMAIN_FEATURE_HYPERV:
27776             if (def->features[i] != VIR_TRISTATE_SWITCH_ON)
27777                 break;
27778 
27779             virBufferAddLit(&childBuf, "<hyperv>\n");
27780             virBufferAdjustIndent(&childBuf, 2);
27781             for (j = 0; j < VIR_DOMAIN_HYPERV_LAST; j++) {
27782                 if (def->hyperv_features[j] == VIR_TRISTATE_SWITCH_ABSENT)
27783                     continue;
27784 
27785                 virBufferAsprintf(&childBuf, "<%s state='%s'",
27786                                   virDomainHypervTypeToString(j),
27787                                   virTristateSwitchTypeToString(
27788                                       def->hyperv_features[j]));
27789 
27790                 switch ((virDomainHyperv) j) {
27791                 case VIR_DOMAIN_HYPERV_RELAXED:
27792                 case VIR_DOMAIN_HYPERV_VAPIC:
27793                 case VIR_DOMAIN_HYPERV_VPINDEX:
27794                 case VIR_DOMAIN_HYPERV_RUNTIME:
27795                 case VIR_DOMAIN_HYPERV_SYNIC:
27796                 case VIR_DOMAIN_HYPERV_RESET:
27797                 case VIR_DOMAIN_HYPERV_FREQUENCIES:
27798                 case VIR_DOMAIN_HYPERV_REENLIGHTENMENT:
27799                 case VIR_DOMAIN_HYPERV_TLBFLUSH:
27800                 case VIR_DOMAIN_HYPERV_IPI:
27801                 case VIR_DOMAIN_HYPERV_EVMCS:
27802                     virBufferAddLit(&childBuf, "/>\n");
27803                     break;
27804 
27805                 case VIR_DOMAIN_HYPERV_SPINLOCKS:
27806                     if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) {
27807                         virBufferAddLit(&childBuf, "/>\n");
27808                         break;
27809                     }
27810                     virBufferAsprintf(&childBuf, " retries='%d'/>\n",
27811                                       def->hyperv_spinlocks);
27812                     break;
27813 
27814                 case VIR_DOMAIN_HYPERV_STIMER:
27815                     if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) {
27816                         virBufferAddLit(&childBuf, "/>\n");
27817                         break;
27818                     }
27819                     if (def->hyperv_stimer_direct == VIR_TRISTATE_SWITCH_ON) {
27820                         virBufferAddLit(&childBuf, ">\n");
27821                         virBufferAdjustIndent(&childBuf, 2);
27822                         virBufferAddLit(&childBuf, "<direct state='on'/>\n");
27823                         virBufferAdjustIndent(&childBuf, -2);
27824                         virBufferAddLit(&childBuf, "</stimer>\n");
27825                     } else {
27826                         virBufferAddLit(&childBuf, "/>\n");
27827                     }
27828 
27829                     break;
27830 
27831                 case VIR_DOMAIN_HYPERV_VENDOR_ID:
27832                     if (def->hyperv_features[j] != VIR_TRISTATE_SWITCH_ON) {
27833                         virBufferAddLit(&childBuf, "/>\n");
27834                         break;
27835                     }
27836                     virBufferEscapeString(&childBuf, " value='%s'/>\n",
27837                                           def->hyperv_vendor_id);
27838                     break;
27839 
27840                 case VIR_DOMAIN_HYPERV_LAST:
27841                     break;
27842                 }
27843             }
27844             virBufferAdjustIndent(&childBuf, -2);
27845             virBufferAddLit(&childBuf, "</hyperv>\n");
27846             break;
27847 
27848         case VIR_DOMAIN_FEATURE_KVM:
27849             if (def->features[i] != VIR_TRISTATE_SWITCH_ON)
27850                 break;
27851 
27852             virBufferAddLit(&childBuf, "<kvm>\n");
27853             virBufferAdjustIndent(&childBuf, 2);
27854             for (j = 0; j < VIR_DOMAIN_KVM_LAST; j++) {
27855                 switch ((virDomainKVM) j) {
27856                 case VIR_DOMAIN_KVM_HIDDEN:
27857                 case VIR_DOMAIN_KVM_DEDICATED:
27858                 case VIR_DOMAIN_KVM_POLLCONTROL:
27859                 case VIR_DOMAIN_KVM_PVIPI:
27860                     if (def->kvm_features[j])
27861                         virBufferAsprintf(&childBuf, "<%s state='%s'/>\n",
27862                                           virDomainKVMTypeToString(j),
27863                                           virTristateSwitchTypeToString(
27864                                               def->kvm_features[j]));
27865                     break;
27866 
27867                 case VIR_DOMAIN_KVM_LAST:
27868                     break;
27869                 }
27870             }
27871             virBufferAdjustIndent(&childBuf, -2);
27872             virBufferAddLit(&childBuf, "</kvm>\n");
27873             break;
27874 
27875         case VIR_DOMAIN_FEATURE_XEN:
27876             if (def->features[i] != VIR_TRISTATE_SWITCH_ON)
27877                 break;
27878 
27879             virBufferAddLit(&childBuf, "<xen>\n");
27880             virBufferAdjustIndent(&childBuf, 2);
27881             for (j = 0; j < VIR_DOMAIN_XEN_LAST; j++) {
27882                 if (def->xen_features[j] == VIR_TRISTATE_SWITCH_ABSENT)
27883                     continue;
27884 
27885                 virBufferAsprintf(&childBuf, "<%s state='%s'",
27886                                       virDomainXenTypeToString(j),
27887                                       virTristateSwitchTypeToString(
27888                                           def->xen_features[j]));
27889 
27890                 switch ((virDomainXen) j) {
27891                 case VIR_DOMAIN_XEN_E820_HOST:
27892                     virBufferAddLit(&childBuf, "/>\n");
27893                     break;
27894                 case VIR_DOMAIN_XEN_PASSTHROUGH:
27895                     if (def->xen_features[j] != VIR_TRISTATE_SWITCH_ON) {
27896                         virBufferAddLit(&childBuf, "/>\n");
27897                         break;
27898                     }
27899                     if (def->xen_passthrough_mode == VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SYNC_PT ||
27900                         def->xen_passthrough_mode == VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SHARE_PT) {
27901                         virBufferEscapeString(&childBuf, " mode='%s'/>\n",
27902                                               virDomainXenPassthroughModeTypeToString(def->xen_passthrough_mode));
27903                     } else {
27904                         virBufferAddLit(&childBuf, "/>\n");
27905                     }
27906                     break;
27907 
27908                 case VIR_DOMAIN_XEN_LAST:
27909                     break;
27910                 }
27911             }
27912             virBufferAdjustIndent(&childBuf, -2);
27913             virBufferAddLit(&childBuf, "</xen>\n");
27914             break;
27915 
27916         case VIR_DOMAIN_FEATURE_CAPABILITIES:
27917             for (j = 0; j < VIR_DOMAIN_PROCES_CAPS_FEATURE_LAST; j++) {
27918                 if (def->caps_features[j] != VIR_TRISTATE_SWITCH_ABSENT)
27919                     virBufferAsprintf(&tmpChildBuf, "<%s state='%s'/>\n",
27920                                       virDomainProcessCapsFeatureTypeToString(j),
27921                                       virTristateSwitchTypeToString(def->caps_features[j]));
27922             }
27923 
27924             /* the 'default' policy should be printed if any capability is present */
27925             if (def->features[i] != VIR_DOMAIN_CAPABILITIES_POLICY_DEFAULT ||
27926                 virBufferUse(&tmpChildBuf))
27927                 virBufferAsprintf(&tmpAttrBuf, " policy='%s'",
27928                                   virDomainCapabilitiesPolicyTypeToString(def->features[i]));
27929 
27930             virXMLFormatElement(&childBuf, "capabilities", &tmpAttrBuf, &tmpChildBuf);
27931             break;
27932 
27933         case VIR_DOMAIN_FEATURE_GIC:
27934             if (def->features[i] == VIR_TRISTATE_SWITCH_ON) {
27935                 virBufferAddLit(&childBuf, "<gic");
27936                 if (def->gic_version != VIR_GIC_VERSION_NONE)
27937                     virBufferAsprintf(&childBuf, " version='%s'",
27938                                       virGICVersionTypeToString(def->gic_version));
27939                 virBufferAddLit(&childBuf, "/>\n");
27940             }
27941             break;
27942 
27943         case VIR_DOMAIN_FEATURE_IOAPIC:
27944             if (def->features[i] == VIR_DOMAIN_IOAPIC_NONE)
27945                 break;
27946 
27947             virBufferAsprintf(&childBuf, "<ioapic driver='%s'/>\n",
27948                               virDomainIOAPICTypeToString(def->features[i]));
27949             break;
27950 
27951         case VIR_DOMAIN_FEATURE_HPT:
27952             if (def->features[i] != VIR_TRISTATE_SWITCH_ON)
27953                 break;
27954 
27955             if (def->hpt_resizing != VIR_DOMAIN_HPT_RESIZING_NONE) {
27956                 virBufferAsprintf(&tmpAttrBuf,
27957                                   " resizing='%s'",
27958                                   virDomainHPTResizingTypeToString(def->hpt_resizing));
27959             }
27960             if (def->hpt_maxpagesize > 0) {
27961                 virBufferAsprintf(&tmpChildBuf,
27962                                   "<maxpagesize unit='KiB'>%llu</maxpagesize>\n",
27963                                   def->hpt_maxpagesize);
27964             }
27965 
27966             virXMLFormatElement(&childBuf, "hpt", &tmpAttrBuf, &tmpChildBuf);
27967             break;
27968 
27969         case VIR_DOMAIN_FEATURE_MSRS:
27970             if (def->features[i] != VIR_TRISTATE_SWITCH_ON)
27971                 break;
27972 
27973             virBufferAsprintf(&childBuf, "<msrs unknown='%s'/>\n",
27974                               virDomainMsrsUnknownTypeToString(def->msrs_features[VIR_DOMAIN_MSRS_UNKNOWN]));
27975             break;
27976 
27977         case VIR_DOMAIN_FEATURE_CFPC:
27978             if (def->features[i] == VIR_DOMAIN_CFPC_NONE)
27979                 break;
27980 
27981             virBufferAsprintf(&childBuf, "<cfpc value='%s'/>\n",
27982                               virDomainCFPCTypeToString(def->features[i]));
27983             break;
27984 
27985         case VIR_DOMAIN_FEATURE_SBBC:
27986             if (def->features[i] == VIR_DOMAIN_SBBC_NONE)
27987                 break;
27988 
27989             virBufferAsprintf(&childBuf, "<sbbc value='%s'/>\n",
27990                               virDomainSBBCTypeToString(def->features[i]));
27991             break;
27992 
27993         case VIR_DOMAIN_FEATURE_IBS:
27994             if (def->features[i] == VIR_DOMAIN_IBS_NONE)
27995                 break;
27996 
27997             virBufferAsprintf(&childBuf, "<ibs value='%s'/>\n",
27998                               virDomainIBSTypeToString(def->features[i]));
27999             break;
28000 
28001         case VIR_DOMAIN_FEATURE_LAST:
28002             break;
28003         }
28004     }
28005 
28006     virXMLFormatElement(buf, "features", NULL, &childBuf);
28007     return 0;
28008 }
28009 
28010 int
virDomainDefFormatInternal(virDomainDef * def,virDomainXMLOption * xmlopt,virBuffer * buf,unsigned int flags)28011 virDomainDefFormatInternal(virDomainDef *def,
28012                            virDomainXMLOption *xmlopt,
28013                            virBuffer *buf,
28014                            unsigned int flags)
28015 {
28016     return virDomainDefFormatInternalSetRootName(def, xmlopt, buf,
28017                                                  "domain", flags);
28018 }
28019 
28020 
28021 /* This internal version appends to an existing buffer
28022  * (possibly with auto-indent), rather than flattening
28023  * to string.
28024  * Return -1 on failure.  */
28025 int
virDomainDefFormatInternalSetRootName(virDomainDef * def,virDomainXMLOption * xmlopt,virBuffer * buf,const char * rootname,unsigned int flags)28026 virDomainDefFormatInternalSetRootName(virDomainDef *def,
28027                                       virDomainXMLOption *xmlopt,
28028                                       virBuffer *buf,
28029                                       const char *rootname,
28030                                       unsigned int flags)
28031 {
28032     unsigned char *uuid;
28033     char uuidstr[VIR_UUID_STRING_BUFLEN];
28034     const char *type = NULL;
28035     int n;
28036     size_t i;
28037 
28038     virCheckFlags(VIR_DOMAIN_DEF_FORMAT_COMMON_FLAGS |
28039                   VIR_DOMAIN_DEF_FORMAT_STATUS |
28040                   VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET |
28041                   VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES |
28042                   VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST,
28043                   -1);
28044 
28045     if (!(type = virDomainVirtTypeToString(def->virtType))) {
28046         virReportError(VIR_ERR_INTERNAL_ERROR,
28047                        _("unexpected domain type %d"), def->virtType);
28048         return -1;
28049     }
28050 
28051     if (def->id == -1)
28052         flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE;
28053 
28054     virBufferAsprintf(buf, "<%s type='%s'", rootname, type);
28055     if (!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
28056         virBufferAsprintf(buf, " id='%d'", def->id);
28057     if (def->namespaceData && def->ns.format)
28058         virXMLNamespaceFormatNS(buf, &def->ns);
28059     virBufferAddLit(buf, ">\n");
28060     virBufferAdjustIndent(buf, 2);
28061 
28062     virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
28063 
28064     uuid = def->uuid;
28065     virUUIDFormat(uuid, uuidstr);
28066     virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
28067 
28068     if (def->genidRequested) {
28069         char genidstr[VIR_UUID_STRING_BUFLEN];
28070 
28071         virUUIDFormat(def->genid, genidstr);
28072         virBufferAsprintf(buf, "<genid>%s</genid>\n", genidstr);
28073     }
28074 
28075     virBufferEscapeString(buf, "<title>%s</title>\n", def->title);
28076 
28077     virBufferEscapeString(buf, "<description>%s</description>\n",
28078                           def->description);
28079 
28080     if (virXMLFormatMetadata(buf, def->metadata) < 0)
28081         return -1;
28082 
28083     if (virDomainDefHasMemoryHotplug(def)) {
28084         virBufferAsprintf(buf,
28085                           "<maxMemory slots='%u' unit='KiB'>%llu</maxMemory>\n",
28086                           def->mem.memory_slots, def->mem.max_memory);
28087     }
28088 
28089     virBufferAddLit(buf, "<memory");
28090     if (def->mem.dump_core)
28091         virBufferAsprintf(buf, " dumpCore='%s'",
28092                           virTristateSwitchTypeToString(def->mem.dump_core));
28093     virBufferAsprintf(buf, " unit='KiB'>%llu</memory>\n",
28094                       virDomainDefGetMemoryTotal(def));
28095 
28096     virBufferAsprintf(buf, "<currentMemory unit='KiB'>%llu</currentMemory>\n",
28097                       def->mem.cur_balloon);
28098 
28099     virDomainDefFormatBlkiotune(buf, def);
28100 
28101     virDomainMemtuneFormat(buf, &def->mem);
28102     virDomainMemorybackingFormat(buf, &def->mem);
28103 
28104     if (virDomainCpuDefFormat(buf, def) < 0)
28105         return -1;
28106 
28107     if (def->niothreadids > 0) {
28108         virBufferAsprintf(buf, "<iothreads>%zu</iothreads>\n",
28109                           def->niothreadids);
28110         if (virDomainDefIothreadShouldFormat(def)) {
28111             virBufferAddLit(buf, "<iothreadids>\n");
28112             virBufferAdjustIndent(buf, 2);
28113             for (i = 0; i < def->niothreadids; i++) {
28114                 virBufferAsprintf(buf, "<iothread id='%u'/>\n",
28115                                   def->iothreadids[i]->iothread_id);
28116             }
28117             virBufferAdjustIndent(buf, -2);
28118             virBufferAddLit(buf, "</iothreadids>\n");
28119         }
28120     }
28121 
28122     if (virDomainCputuneDefFormat(buf, def, flags) < 0)
28123         return -1;
28124 
28125     if (virDomainNumatuneFormatXML(buf, def->numa) < 0)
28126         return -1;
28127 
28128     virDomainResourceDefFormat(buf, def->resource);
28129 
28130     for (i = 0; i < def->nsysinfo; i++) {
28131         if (virSysinfoFormat(buf, def->sysinfo[i]) < 0)
28132             return -1;
28133     }
28134 
28135     if (def->os.bootloader) {
28136         virBufferEscapeString(buf, "<bootloader>%s</bootloader>\n",
28137                               def->os.bootloader);
28138         virBufferEscapeString(buf,
28139                               "<bootloader_args>%s</bootloader_args>\n",
28140                               def->os.bootloaderArgs);
28141     }
28142 
28143     virBufferAddLit(buf, "<os");
28144     if (def->os.firmware)
28145         virBufferAsprintf(buf, " firmware='%s'",
28146                           virDomainOsDefFirmwareTypeToString(def->os.firmware));
28147     virBufferAddLit(buf, ">\n");
28148     virBufferAdjustIndent(buf, 2);
28149     virBufferAddLit(buf, "<type");
28150     if (def->os.arch)
28151         virBufferAsprintf(buf, " arch='%s'", virArchToString(def->os.arch));
28152     if (def->os.machine)
28153         virBufferAsprintf(buf, " machine='%s'", def->os.machine);
28154     /*
28155      * HACK: For xen driver we previously used bogus 'linux' as the
28156      * os type for paravirt, whereas capabilities declare it to
28157      * be 'xen'. So we convert to the former for backcompat
28158      */
28159     if (def->virtType == VIR_DOMAIN_VIRT_XEN &&
28160         def->os.type == VIR_DOMAIN_OSTYPE_XEN)
28161         virBufferAsprintf(buf, ">%s</type>\n",
28162                           virDomainOSTypeToString(VIR_DOMAIN_OSTYPE_LINUX));
28163     else
28164         virBufferAsprintf(buf, ">%s</type>\n",
28165                           virDomainOSTypeToString(def->os.type));
28166 
28167     if (def->os.firmwareFeatures) {
28168         virBufferAddLit(buf, "<firmware>\n");
28169         virBufferAdjustIndent(buf, 2);
28170 
28171         for (i = 0; i < VIR_DOMAIN_OS_DEF_FIRMWARE_FEATURE_LAST; i++) {
28172             if (def->os.firmwareFeatures[i] == VIR_TRISTATE_BOOL_ABSENT)
28173                 continue;
28174 
28175             virBufferAsprintf(buf, "<feature enabled='%s' name='%s'/>\n",
28176                               virTristateBoolTypeToString(def->os.firmwareFeatures[i]),
28177                               virDomainOsDefFirmwareFeatureTypeToString(i));
28178         }
28179 
28180         virBufferAdjustIndent(buf, -2);
28181 
28182         virBufferAddLit(buf, "</firmware>\n");
28183     }
28184 
28185     virBufferEscapeString(buf, "<init>%s</init>\n",
28186                           def->os.init);
28187     for (i = 0; def->os.initargv && def->os.initargv[i]; i++)
28188         virBufferEscapeString(buf, "<initarg>%s</initarg>\n",
28189                               def->os.initargv[i]);
28190     for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
28191         virBufferAsprintf(buf, "<initenv name='%s'>%s</initenv>\n",
28192                           def->os.initenv[i]->name, def->os.initenv[i]->value);
28193     if (def->os.initdir)
28194         virBufferEscapeString(buf, "<initdir>%s</initdir>\n",
28195                               def->os.initdir);
28196     if (def->os.inituser)
28197         virBufferAsprintf(buf, "<inituser>%s</inituser>\n", def->os.inituser);
28198     if (def->os.initgroup)
28199         virBufferAsprintf(buf, "<initgroup>%s</initgroup>\n", def->os.initgroup);
28200 
28201     if (def->os.loader)
28202         virDomainLoaderDefFormat(buf, def->os.loader);
28203     virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
28204                           def->os.kernel);
28205     virBufferEscapeString(buf, "<initrd>%s</initrd>\n",
28206                           def->os.initrd);
28207     virBufferEscapeString(buf, "<cmdline>%s</cmdline>\n",
28208                           def->os.cmdline);
28209     virBufferEscapeString(buf, "<dtb>%s</dtb>\n",
28210                           def->os.dtb);
28211     virBufferEscapeString(buf, "<root>%s</root>\n",
28212                           def->os.root);
28213     if (def->os.slic_table) {
28214         virBufferAddLit(buf, "<acpi>\n");
28215         virBufferAdjustIndent(buf, 2);
28216         virBufferEscapeString(buf, "<table type='slic'>%s</table>\n",
28217                               def->os.slic_table);
28218         virBufferAdjustIndent(buf, -2);
28219         virBufferAddLit(buf, "</acpi>\n");
28220     }
28221 
28222     if (!def->os.bootloader) {
28223         for (n = 0; n < def->os.nBootDevs; n++) {
28224             const char *boottype =
28225                 virDomainBootTypeToString(def->os.bootDevs[n]);
28226             if (!boottype) {
28227                 virReportError(VIR_ERR_INTERNAL_ERROR,
28228                                _("unexpected boot device type %d"),
28229                                def->os.bootDevs[n]);
28230                 return -1;
28231             }
28232             virBufferAsprintf(buf, "<boot dev='%s'/>\n", boottype);
28233         }
28234 
28235         if (def->os.bootmenu) {
28236             virBufferAsprintf(buf, "<bootmenu enable='%s'",
28237                               virTristateBoolTypeToString(def->os.bootmenu));
28238             if (def->os.bm_timeout_set)
28239                 virBufferAsprintf(buf, " timeout='%u'", def->os.bm_timeout);
28240             virBufferAddLit(buf, "/>\n");
28241         }
28242 
28243         if (def->os.bios.useserial || def->os.bios.rt_set) {
28244             virBufferAddLit(buf, "<bios");
28245             if (def->os.bios.useserial)
28246                 virBufferAsprintf(buf, " useserial='%s'",
28247                                   virTristateBoolTypeToString(def->os.bios.useserial));
28248             if (def->os.bios.rt_set)
28249                 virBufferAsprintf(buf, " rebootTimeout='%d'", def->os.bios.rt_delay);
28250 
28251             virBufferAddLit(buf, "/>\n");
28252         }
28253     }
28254 
28255     if (def->os.smbios_mode) {
28256         const char *mode;
28257 
28258         mode = virDomainSmbiosModeTypeToString(def->os.smbios_mode);
28259         if (mode == NULL) {
28260             virReportError(VIR_ERR_INTERNAL_ERROR,
28261                            _("unexpected smbios mode %d"), def->os.smbios_mode);
28262             return -1;
28263         }
28264         virBufferAsprintf(buf, "<smbios mode='%s'/>\n", mode);
28265     }
28266 
28267     virBufferAdjustIndent(buf, -2);
28268     virBufferAddLit(buf, "</os>\n");
28269 
28270 
28271     if (def->idmap.uidmap) {
28272         virBufferAddLit(buf, "<idmap>\n");
28273         virBufferAdjustIndent(buf, 2);
28274         for (i = 0; i < def->idmap.nuidmap; i++) {
28275             virBufferAsprintf(buf,
28276                               "<uid start='%u' target='%u' count='%u'/>\n",
28277                               def->idmap.uidmap[i].start,
28278                               def->idmap.uidmap[i].target,
28279                               def->idmap.uidmap[i].count);
28280         }
28281         for (i = 0; i < def->idmap.ngidmap; i++) {
28282             virBufferAsprintf(buf,
28283                               "<gid start='%u' target='%u' count='%u'/>\n",
28284                               def->idmap.gidmap[i].start,
28285                               def->idmap.gidmap[i].target,
28286                               def->idmap.gidmap[i].count);
28287         }
28288         virBufferAdjustIndent(buf, -2);
28289         virBufferAddLit(buf, "</idmap>\n");
28290     }
28291 
28292     if (virDomainDefFormatFeatures(buf, def) < 0)
28293         return -1;
28294 
28295     if (virCPUDefFormatBufFull(buf, def->cpu, def->numa) < 0)
28296         return -1;
28297 
28298     virBufferAsprintf(buf, "<clock offset='%s'",
28299                       virDomainClockOffsetTypeToString(def->clock.offset));
28300     switch (def->clock.offset) {
28301     case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
28302     case VIR_DOMAIN_CLOCK_OFFSET_UTC:
28303         if (def->clock.data.utc_reset)
28304             virBufferAddLit(buf, " adjustment='reset'");
28305         break;
28306     case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
28307         virBufferAsprintf(buf, " adjustment='%lld' basis='%s'",
28308                           def->clock.data.variable.adjustment,
28309                           virDomainClockBasisTypeToString(def->clock.data.variable.basis));
28310         if (flags & VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST) {
28311             if (def->clock.data.variable.adjustment0)
28312                 virBufferAsprintf(buf, " adjustment0='%lld'",
28313                                   def->clock.data.variable.adjustment0);
28314         }
28315         break;
28316     case VIR_DOMAIN_CLOCK_OFFSET_TIMEZONE:
28317         virBufferEscapeString(buf, " timezone='%s'", def->clock.data.timezone);
28318         break;
28319     }
28320     if (def->clock.ntimers == 0) {
28321         virBufferAddLit(buf, "/>\n");
28322     } else {
28323         virBufferAddLit(buf, ">\n");
28324         virBufferAdjustIndent(buf, 2);
28325         for (n = 0; n < def->clock.ntimers; n++) {
28326             if (virDomainTimerDefFormat(buf, def->clock.timers[n]) < 0)
28327                 return -1;
28328         }
28329         virBufferAdjustIndent(buf, -2);
28330         virBufferAddLit(buf, "</clock>\n");
28331     }
28332 
28333     if (virDomainEventActionDefFormat(buf, def->onPoweroff,
28334                                       "on_poweroff",
28335                                       virDomainLifecycleActionTypeToString) < 0)
28336         return -1;
28337     if (virDomainEventActionDefFormat(buf, def->onReboot,
28338                                       "on_reboot",
28339                                       virDomainLifecycleActionTypeToString) < 0)
28340         return -1;
28341     if (virDomainEventActionDefFormat(buf, def->onCrash,
28342                                       "on_crash",
28343                                       virDomainLifecycleActionTypeToString) < 0)
28344         return -1;
28345     if (def->onLockFailure != VIR_DOMAIN_LOCK_FAILURE_DEFAULT &&
28346         virDomainEventActionDefFormat(buf, def->onLockFailure,
28347                                       "on_lockfailure",
28348                                       virDomainLockFailureTypeToString) < 0)
28349         return -1;
28350 
28351     if (def->pm.s3 || def->pm.s4) {
28352         virBufferAddLit(buf, "<pm>\n");
28353         virBufferAdjustIndent(buf, 2);
28354         if (def->pm.s3) {
28355             virBufferAsprintf(buf, "<suspend-to-mem enabled='%s'/>\n",
28356                               virTristateBoolTypeToString(def->pm.s3));
28357         }
28358         if (def->pm.s4) {
28359             virBufferAsprintf(buf, "<suspend-to-disk enabled='%s'/>\n",
28360                               virTristateBoolTypeToString(def->pm.s4));
28361         }
28362         virBufferAdjustIndent(buf, -2);
28363         virBufferAddLit(buf, "</pm>\n");
28364     }
28365 
28366     virDomainPerfDefFormat(buf, &def->perf);
28367 
28368     virBufferAddLit(buf, "<devices>\n");
28369     virBufferAdjustIndent(buf, 2);
28370 
28371     virBufferEscapeString(buf, "<emulator>%s</emulator>\n",
28372                           def->emulator);
28373 
28374     for (n = 0; n < def->ndisks; n++)
28375         if (virDomainDiskDefFormat(buf, def->disks[n], flags, xmlopt) < 0)
28376             return -1;
28377 
28378     for (n = 0; n < def->ncontrollers; n++)
28379         if (virDomainControllerDefFormat(buf, def->controllers[n], flags) < 0)
28380             return -1;
28381 
28382     for (n = 0; n < def->nleases; n++)
28383         virDomainLeaseDefFormat(buf, def->leases[n]);
28384 
28385     for (n = 0; n < def->nfss; n++)
28386         if (virDomainFSDefFormat(buf, def->fss[n], flags) < 0)
28387             return -1;
28388 
28389     for (n = 0; n < def->nnets; n++)
28390         if (virDomainNetDefFormat(buf, def->nets[n], xmlopt, flags) < 0)
28391             return -1;
28392 
28393     for (n = 0; n < def->nsmartcards; n++)
28394         if (virDomainSmartcardDefFormat(buf, def->smartcards[n], flags) < 0)
28395             return -1;
28396 
28397     for (n = 0; n < def->nserials; n++)
28398         if (virDomainChrDefFormat(buf, def->serials[n], flags) < 0)
28399             return -1;
28400 
28401     for (n = 0; n < def->nparallels; n++)
28402         if (virDomainChrDefFormat(buf, def->parallels[n], flags) < 0)
28403             return -1;
28404 
28405     for (n = 0; n < def->nconsoles; n++) {
28406         virDomainChrDef console;
28407         /* Back compat, ignore the console element for hvm guests
28408          * if it is type == serial
28409          */
28410         if (def->os.type == VIR_DOMAIN_OSTYPE_HVM &&
28411             (def->consoles[n]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL ||
28412              def->consoles[n]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE) &&
28413             (n < def->nserials)) {
28414             memcpy(&console, def->serials[n], sizeof(console));
28415             console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
28416             console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
28417         } else {
28418             memcpy(&console, def->consoles[n], sizeof(console));
28419         }
28420         if (virDomainChrDefFormat(buf, &console, flags) < 0)
28421             return -1;
28422     }
28423 
28424     for (n = 0; n < def->nchannels; n++)
28425         if (virDomainChrDefFormat(buf, def->channels[n], flags) < 0)
28426             return -1;
28427 
28428     for (n = 0; n < def->ninputs; n++) {
28429         if (virDomainInputDefFormat(buf, def->inputs[n], flags) < 0)
28430             return -1;
28431     }
28432 
28433     for (n = 0; n < def->ntpms; n++) {
28434         if (virDomainTPMDefFormat(buf, def->tpms[n], flags) < 0)
28435             return -1;
28436     }
28437 
28438     for (n = 0; n < def->ngraphics; n++) {
28439         if (virDomainGraphicsDefFormat(buf, def->graphics[n], flags) < 0)
28440             return -1;
28441     }
28442 
28443     for (n = 0; n < def->nsounds; n++) {
28444         if (virDomainSoundDefFormat(buf, def->sounds[n], flags) < 0)
28445             return -1;
28446     }
28447 
28448     for (n = 0; n < def->naudios; n++) {
28449         if (virDomainAudioDefFormat(buf, def->audios[n]) < 0)
28450             return -1;
28451     }
28452 
28453     for (n = 0; n < def->nvideos; n++) {
28454         if (virDomainVideoDefFormat(buf, def->videos[n], flags) < 0)
28455             return -1;
28456     }
28457 
28458     for (n = 0; n < def->nhostdevs; n++) {
28459         /* If parentnet != NONE, this is just a pointer to the
28460          * hostdev in a higher-level device (e.g. virDomainNetDef),
28461          * and will have already been formatted there.
28462          */
28463         if (!def->hostdevs[n]->parentnet &&
28464             virDomainHostdevDefFormat(buf, def->hostdevs[n], flags, xmlopt) < 0) {
28465             return -1;
28466         }
28467     }
28468 
28469     for (n = 0; n < def->nredirdevs; n++) {
28470         if (virDomainRedirdevDefFormat(buf, def->redirdevs[n], flags) < 0)
28471             return -1;
28472     }
28473 
28474     if (def->redirfilter)
28475         virDomainRedirFilterDefFormat(buf, def->redirfilter);
28476 
28477     for (n = 0; n < def->nhubs; n++) {
28478         if (virDomainHubDefFormat(buf, def->hubs[n], flags) < 0)
28479             return -1;
28480     }
28481 
28482     if (def->watchdog)
28483         virDomainWatchdogDefFormat(buf, def->watchdog, flags);
28484 
28485     if (def->memballoon)
28486         virDomainMemballoonDefFormat(buf, def->memballoon, flags);
28487 
28488     for (n = 0; n < def->nrngs; n++) {
28489         if (virDomainRNGDefFormat(buf, def->rngs[n], flags))
28490             return -1;
28491     }
28492 
28493     if (def->nvram)
28494         virDomainNVRAMDefFormat(buf, def->nvram, flags);
28495 
28496     for (n = 0; n < def->npanics; n++)
28497         virDomainPanicDefFormat(buf, def->panics[n]);
28498 
28499     for (n = 0; n < def->nshmems; n++)
28500         virDomainShmemDefFormat(buf, def->shmems[n], flags);
28501 
28502     for (n = 0; n < def->nmems; n++) {
28503         if (virDomainMemoryDefFormat(buf, def->mems[n], flags) < 0)
28504             return -1;
28505     }
28506 
28507     if (def->iommu)
28508         virDomainIOMMUDefFormat(buf, def->iommu);
28509 
28510     if (def->vsock)
28511         virDomainVsockDefFormat(buf, def->vsock);
28512 
28513     virBufferAdjustIndent(buf, -2);
28514     virBufferAddLit(buf, "</devices>\n");
28515 
28516     for (n = 0; n < def->nseclabels; n++)
28517         virSecurityLabelDefFormat(buf, def->seclabels[n], flags);
28518 
28519     if (def->keywrap)
28520         virDomainKeyWrapDefFormat(buf, def->keywrap);
28521 
28522     virDomainSecDefFormat(buf, def->sec);
28523 
28524     if (def->namespaceData && def->ns.format) {
28525         if ((def->ns.format)(buf, def->namespaceData) < 0)
28526             return -1;
28527     }
28528 
28529     virBufferAdjustIndent(buf, -2);
28530     virBufferAsprintf(buf, "</%s>\n", rootname);
28531 
28532     return 0;
28533 }
28534 
28535 
28536 /* Converts VIR_DOMAIN_XML_COMMON_FLAGS into VIR_DOMAIN_DEF_FORMAT_*
28537  * flags, and silently ignores any other flags.  Note that the caller
28538  * should validate the set of flags it is willing to accept; see also
28539  * the comment on VIR_DOMAIN_XML_COMMON_FLAGS about security
28540  * considerations with adding new flags. */
virDomainDefFormatConvertXMLFlags(unsigned int flags)28541 unsigned int virDomainDefFormatConvertXMLFlags(unsigned int flags)
28542 {
28543     unsigned int formatFlags = 0;
28544 
28545     if (flags & VIR_DOMAIN_XML_SECURE)
28546         formatFlags |= VIR_DOMAIN_DEF_FORMAT_SECURE;
28547     if (flags & VIR_DOMAIN_XML_INACTIVE)
28548         formatFlags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE;
28549     if (flags & VIR_DOMAIN_XML_MIGRATABLE)
28550         formatFlags |= VIR_DOMAIN_DEF_FORMAT_MIGRATABLE;
28551 
28552     return formatFlags;
28553 }
28554 
28555 
28556 char *
virDomainDefFormat(virDomainDef * def,virDomainXMLOption * xmlopt,unsigned int flags)28557 virDomainDefFormat(virDomainDef *def,
28558                    virDomainXMLOption *xmlopt,
28559                    unsigned int flags)
28560 {
28561     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
28562 
28563     virCheckFlags(VIR_DOMAIN_DEF_FORMAT_COMMON_FLAGS, NULL);
28564     if (virDomainDefFormatInternal(def, xmlopt, &buf, flags) < 0)
28565         return NULL;
28566 
28567     return virBufferContentAndReset(&buf);
28568 }
28569 
28570 
28571 char *
virDomainObjFormat(virDomainObj * obj,virDomainXMLOption * xmlopt,unsigned int flags)28572 virDomainObjFormat(virDomainObj *obj,
28573                    virDomainXMLOption *xmlopt,
28574                    unsigned int flags)
28575 {
28576     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
28577     int state;
28578     int reason;
28579     size_t i;
28580 
28581     state = virDomainObjGetState(obj, &reason);
28582     virBufferAsprintf(&buf, "<domstatus state='%s' reason='%s' pid='%lld'>\n",
28583                       virDomainStateTypeToString(state),
28584                       virDomainStateReasonToString(state, reason),
28585                       (long long)obj->pid);
28586     virBufferAdjustIndent(&buf, 2);
28587 
28588     for (i = 0; i < VIR_DOMAIN_TAINT_LAST; i++) {
28589         if (obj->taint & (1 << i))
28590             virBufferAsprintf(&buf, "<taint flag='%s'/>\n",
28591                               virDomainTaintTypeToString(i));
28592     }
28593 
28594     for (i = 0; i < obj->ndeprecations; i++) {
28595         virBufferEscapeString(&buf, "<deprecation>%s</deprecation>\n",
28596                               obj->deprecations[i]);
28597     }
28598 
28599     if (xmlopt->privateData.format &&
28600         xmlopt->privateData.format(&buf, obj) < 0)
28601         return NULL;
28602 
28603     if (virDomainDefFormatInternal(obj->def, xmlopt, &buf, flags) < 0)
28604         return NULL;
28605 
28606     virBufferAdjustIndent(&buf, -2);
28607     virBufferAddLit(&buf, "</domstatus>\n");
28608 
28609     return virBufferContentAndReset(&buf);
28610 }
28611 
28612 static bool
virDomainDeviceIsUSB(virDomainDeviceDef * dev)28613 virDomainDeviceIsUSB(virDomainDeviceDef *dev)
28614 {
28615     int t = dev->type;
28616     if ((t == VIR_DOMAIN_DEVICE_DISK &&
28617          dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) ||
28618         (t == VIR_DOMAIN_DEVICE_INPUT &&
28619          dev->data.input->bus == VIR_DOMAIN_INPUT_BUS_USB) ||
28620         (t == VIR_DOMAIN_DEVICE_HOSTDEV &&
28621          dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
28622          dev->data.hostdev->source.subsys.type ==
28623          VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) ||
28624         (t == VIR_DOMAIN_DEVICE_HUB &&
28625          dev->data.hub->type == VIR_DOMAIN_HUB_TYPE_USB) ||
28626         (t == VIR_DOMAIN_DEVICE_REDIRDEV &&
28627          dev->data.redirdev->bus == VIR_DOMAIN_REDIRDEV_BUS_USB))
28628         return true;
28629 
28630     return false;
28631 }
28632 
28633 
28634 typedef struct _virDomainCompatibleDeviceData virDomainCompatibleDeviceData;
28635 struct _virDomainCompatibleDeviceData {
28636     virDomainDeviceInfo *newInfo;
28637     virDomainDeviceInfo *oldInfo;
28638 };
28639 
28640 static int
virDomainDeviceInfoCheckBootIndex(virDomainDef * def G_GNUC_UNUSED,virDomainDeviceDef * device G_GNUC_UNUSED,virDomainDeviceInfo * info,void * opaque)28641 virDomainDeviceInfoCheckBootIndex(virDomainDef *def G_GNUC_UNUSED,
28642                                   virDomainDeviceDef *device G_GNUC_UNUSED,
28643                                   virDomainDeviceInfo *info,
28644                                   void *opaque)
28645 {
28646     virDomainCompatibleDeviceData *data = opaque;
28647 
28648     /* Ignore the device we're about to update */
28649     if (data->oldInfo == info)
28650         return 0;
28651 
28652     if (info->bootIndex == data->newInfo->bootIndex) {
28653         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
28654                        _("boot order %u is already used by another device"),
28655                        data->newInfo->bootIndex);
28656         return -1;
28657     }
28658     return 0;
28659 }
28660 
28661 int
virDomainDefCompatibleDevice(virDomainDef * def,virDomainDeviceDef * dev,virDomainDeviceDef * oldDev,virDomainDeviceAction action,bool live)28662 virDomainDefCompatibleDevice(virDomainDef *def,
28663                              virDomainDeviceDef *dev,
28664                              virDomainDeviceDef *oldDev,
28665                              virDomainDeviceAction action,
28666                              bool live)
28667 {
28668     virDomainCompatibleDeviceData data = {
28669         .newInfo = virDomainDeviceGetInfo(dev),
28670         .oldInfo = NULL,
28671     };
28672 
28673     if (oldDev)
28674         data.oldInfo = virDomainDeviceGetInfo(oldDev);
28675 
28676     if (action == VIR_DOMAIN_DEVICE_ACTION_UPDATE &&
28677         live && data.newInfo && data.oldInfo) {
28678 
28679         if (data.newInfo->alias && data.oldInfo->alias &&
28680             STRNEQ(data.newInfo->alias, data.oldInfo->alias)) {
28681             virReportError(VIR_ERR_OPERATION_DENIED, "%s",
28682                            _("changing device alias is not allowed"));
28683             return -1;
28684         }
28685 
28686         if (data.newInfo->acpiIndex != data.oldInfo->acpiIndex) {
28687             virReportError(VIR_ERR_OPERATION_DENIED, "%s",
28688                            _("changing device 'acpi index' is not allowed"));
28689             return -1;
28690         }
28691     }
28692 
28693     if (!virDomainDefHasUSB(def) &&
28694         def->os.type != VIR_DOMAIN_OSTYPE_EXE &&
28695         virDomainDeviceIsUSB(dev)) {
28696         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
28697                        _("Device configuration is not compatible: "
28698                          "Domain has no USB bus support"));
28699         return -1;
28700     }
28701 
28702     if (data.newInfo && data.newInfo->bootIndex > 0) {
28703         if (def->os.nBootDevs > 0) {
28704             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
28705                            _("per-device boot elements cannot be used"
28706                              " together with os/boot elements"));
28707             return -1;
28708         }
28709         if (virDomainDeviceInfoIterate(def,
28710                                        virDomainDeviceInfoCheckBootIndex,
28711                                        &data) < 0)
28712             return -1;
28713     }
28714 
28715     if (dev->type == VIR_DOMAIN_DEVICE_MEMORY) {
28716         unsigned long long sz = dev->data.memory->size;
28717 
28718         if (!virDomainDefHasMemoryHotplug(def)) {
28719             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
28720                            _("cannot use/hotplug a memory device when domain "
28721                              "'maxMemory' is not defined"));
28722             return -1;
28723         }
28724 
28725         if (action == VIR_DOMAIN_DEVICE_ACTION_ATTACH &&
28726             (virDomainDefGetMemoryTotal(def) + sz) > def->mem.max_memory) {
28727             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
28728                            _("Attaching memory device with size '%llu' would "
28729                              "exceed domain's maxMemory config size '%llu'"),
28730                            sz, def->mem.max_memory);
28731             return -1;
28732         }
28733     }
28734 
28735     return 0;
28736 }
28737 
28738 static int
virDomainDefSaveXML(virDomainDef * def,const char * configDir,const char * xml)28739 virDomainDefSaveXML(virDomainDef *def,
28740                     const char *configDir,
28741                     const char *xml)
28742 {
28743     char uuidstr[VIR_UUID_STRING_BUFLEN];
28744     g_autofree char *configFile = NULL;
28745 
28746     if (!configDir)
28747         return 0;
28748 
28749     if ((configFile = virDomainConfigFile(configDir, def->name)) == NULL)
28750         return -1;
28751 
28752     if (g_mkdir_with_parents(configDir, 0777) < 0) {
28753         virReportSystemError(errno,
28754                              _("cannot create config directory '%s'"),
28755                              configDir);
28756         return -1;
28757     }
28758 
28759     virUUIDFormat(def->uuid, uuidstr);
28760     return virXMLSaveFile(configFile,
28761                            virXMLPickShellSafeComment(def->name, uuidstr), "edit",
28762                            xml);
28763 }
28764 
28765 int
virDomainDefSave(virDomainDef * def,virDomainXMLOption * xmlopt,const char * configDir)28766 virDomainDefSave(virDomainDef *def,
28767                  virDomainXMLOption *xmlopt,
28768                  const char *configDir)
28769 {
28770     g_autofree char *xml = NULL;
28771 
28772     if (!(xml = virDomainDefFormat(def, xmlopt, VIR_DOMAIN_DEF_FORMAT_SECURE)))
28773         return -1;
28774 
28775     return virDomainDefSaveXML(def, configDir, xml);
28776 }
28777 
28778 int
virDomainObjSave(virDomainObj * obj,virDomainXMLOption * xmlopt,const char * statusDir)28779 virDomainObjSave(virDomainObj *obj,
28780                  virDomainXMLOption *xmlopt,
28781                  const char *statusDir)
28782 {
28783     unsigned int flags = (VIR_DOMAIN_DEF_FORMAT_SECURE |
28784                           VIR_DOMAIN_DEF_FORMAT_STATUS |
28785                           VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET |
28786                           VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES |
28787                           VIR_DOMAIN_DEF_FORMAT_CLOCK_ADJUST);
28788 
28789     g_autofree char *xml = NULL;
28790 
28791     if (!(xml = virDomainObjFormat(obj, xmlopt, flags)))
28792         return -1;
28793 
28794     return virDomainDefSaveXML(obj->def, statusDir, xml);
28795 }
28796 
28797 
28798 int
virDomainDeleteConfig(const char * configDir,const char * autostartDir,virDomainObj * dom)28799 virDomainDeleteConfig(const char *configDir,
28800                       const char *autostartDir,
28801                       virDomainObj *dom)
28802 {
28803     g_autofree char *configFile = NULL;
28804     g_autofree char *autostartLink = NULL;
28805 
28806     if ((configFile = virDomainConfigFile(configDir, dom->def->name)) == NULL)
28807         return -1;
28808     if ((autostartLink = virDomainConfigFile(autostartDir,
28809                                              dom->def->name)) == NULL)
28810         return -1;
28811 
28812     /* Not fatal if this doesn't work */
28813     unlink(autostartLink);
28814     dom->autostart = 0;
28815 
28816     if (unlink(configFile) < 0 &&
28817         errno != ENOENT) {
28818         virReportSystemError(errno,
28819                              _("cannot remove config %s"),
28820                              configFile);
28821         return -1;
28822     }
28823 
28824     return 0;
28825 }
28826 
28827 char
virDomainConfigFile(const char * dir,const char * name)28828 *virDomainConfigFile(const char *dir,
28829                      const char *name)
28830 {
28831     return g_strdup_printf("%s/%s.xml", dir, name);
28832 }
28833 
28834 /* Translates a device name of the form (regex) "[fhv]d[a-z]+" into
28835  * the corresponding bus,index combination (e.g. sda => (0,0), sdi (1,1),
28836  *                                               hdd => (1,1), vdaa => (0,26))
28837  * @param disk The disk device
28838  * @param busIdx parsed bus number
28839  * @param devIdx parsed device number
28840  * @return 0 on success, -1 on failure
28841  */
28842 int
virDiskNameToBusDeviceIndex(virDomainDiskDef * disk,int * busIdx,int * devIdx)28843 virDiskNameToBusDeviceIndex(virDomainDiskDef *disk,
28844                             int *busIdx,
28845                             int *devIdx)
28846 {
28847     int idx = virDiskNameToIndex(disk->dst);
28848     if (idx < 0)
28849         return -1;
28850 
28851     switch (disk->bus) {
28852         case VIR_DOMAIN_DISK_BUS_IDE:
28853             *busIdx = idx / 2;
28854             *devIdx = idx % 2;
28855             break;
28856         case VIR_DOMAIN_DISK_BUS_SCSI:
28857             *busIdx = idx / 7;
28858             *devIdx = idx % 7;
28859             break;
28860         case VIR_DOMAIN_DISK_BUS_FDC:
28861         case VIR_DOMAIN_DISK_BUS_USB:
28862         case VIR_DOMAIN_DISK_BUS_VIRTIO:
28863         case VIR_DOMAIN_DISK_BUS_XEN:
28864         case VIR_DOMAIN_DISK_BUS_SD:
28865         case VIR_DOMAIN_DISK_BUS_NONE:
28866         case VIR_DOMAIN_DISK_BUS_SATA:
28867         case VIR_DOMAIN_DISK_BUS_UML:
28868         case VIR_DOMAIN_DISK_BUS_LAST:
28869         default:
28870             *busIdx = 0;
28871             *devIdx = idx;
28872             break;
28873     }
28874 
28875     return 0;
28876 }
28877 
28878 int
virDomainFSInsert(virDomainDef * def,virDomainFSDef * fs)28879 virDomainFSInsert(virDomainDef *def, virDomainFSDef *fs)
28880 {
28881     VIR_APPEND_ELEMENT(def->fss, def->nfss, fs);
28882 
28883     return 0;
28884 }
28885 
28886 virDomainFSDef *
virDomainFSRemove(virDomainDef * def,size_t i)28887 virDomainFSRemove(virDomainDef *def, size_t i)
28888 {
28889     virDomainFSDef *fs = def->fss[i];
28890 
28891     VIR_DELETE_ELEMENT(def->fss, i, def->nfss);
28892     return fs;
28893 }
28894 
28895 ssize_t
virDomainFSDefFind(virDomainDef * def,virDomainFSDef * fs)28896 virDomainFSDefFind(virDomainDef *def,
28897                    virDomainFSDef *fs)
28898 {
28899     size_t i = 0;
28900 
28901     for (i = 0; i < def->nfss; i++) {
28902         virDomainFSDef *tmp = def->fss[i];
28903 
28904         if (fs->dst && STRNEQ_NULLABLE(fs->dst, tmp->dst))
28905             continue;
28906 
28907         if (fs->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
28908             !virDomainDeviceInfoAddressIsEqual(&fs->info, &tmp->info))
28909             continue;
28910 
28911         if (fs->info.alias && STRNEQ_NULLABLE(fs->info.alias, tmp->info.alias))
28912             continue;
28913 
28914         return i;
28915     }
28916     return -1;
28917 }
28918 
28919 virDomainFSDef *
virDomainGetFilesystemForTarget(virDomainDef * def,const char * target)28920 virDomainGetFilesystemForTarget(virDomainDef *def,
28921                                 const char *target)
28922 {
28923     size_t i;
28924 
28925     for (i = 0; i < def->nfss; i++) {
28926         if (STREQ(def->fss[i]->dst, target))
28927             return def->fss[i];
28928     }
28929 
28930     return NULL;
28931 }
28932 
28933 
28934 int
virDomainChrDefForeach(virDomainDef * def,bool abortOnError,virDomainChrDefIterator iter,void * opaque)28935 virDomainChrDefForeach(virDomainDef *def,
28936                        bool abortOnError,
28937                        virDomainChrDefIterator iter,
28938                        void *opaque)
28939 {
28940     size_t i;
28941     int rc = 0;
28942 
28943     for (i = 0; i < def->nserials; i++) {
28944         if ((iter)(def,
28945                    def->serials[i],
28946                    opaque) < 0)
28947             rc = -1;
28948 
28949         if (abortOnError && rc != 0)
28950             return rc;
28951     }
28952 
28953     for (i = 0; i < def->nparallels; i++) {
28954         if ((iter)(def,
28955                    def->parallels[i],
28956                    opaque) < 0)
28957             rc = -1;
28958 
28959         if (abortOnError && rc != 0)
28960             return rc;
28961     }
28962 
28963     for (i = 0; i < def->nchannels; i++) {
28964         if ((iter)(def,
28965                    def->channels[i],
28966                    opaque) < 0)
28967             rc = -1;
28968 
28969         if (abortOnError && rc != 0)
28970             return rc;
28971     }
28972     for (i = 0; i < def->nconsoles; i++) {
28973         if (virDomainSkipBackcompatConsole(def, i, false))
28974             continue;
28975         if ((iter)(def,
28976                    def->consoles[i],
28977                    opaque) < 0)
28978             rc = -1;
28979 
28980         if (abortOnError && rc != 0)
28981             return rc;
28982     }
28983 
28984     return rc;
28985 }
28986 
28987 
28988 int
virDomainSmartcardDefForeach(virDomainDef * def,bool abortOnError,virDomainSmartcardDefIterator iter,void * opaque)28989 virDomainSmartcardDefForeach(virDomainDef *def,
28990                              bool abortOnError,
28991                              virDomainSmartcardDefIterator iter,
28992                              void *opaque)
28993 {
28994     size_t i;
28995     int rc = 0;
28996 
28997     for (i = 0; i < def->nsmartcards; i++) {
28998         if ((iter)(def,
28999                    def->smartcards[i],
29000                    opaque) < 0)
29001             rc = -1;
29002 
29003         if (abortOnError && rc != 0)
29004             return rc;
29005     }
29006 
29007     return rc;
29008 }
29009 
29010 
29011 int
virDomainUSBDeviceDefForeach(virDomainDef * def,virDomainUSBDeviceDefIterator iter,void * opaque,bool skipHubs)29012 virDomainUSBDeviceDefForeach(virDomainDef *def,
29013                              virDomainUSBDeviceDefIterator iter,
29014                              void *opaque,
29015                              bool skipHubs)
29016 {
29017     size_t i;
29018 
29019     /* usb-hub */
29020     if (!skipHubs) {
29021         for (i = 0; i < def->nhubs; i++) {
29022             virDomainHubDef *hub = def->hubs[i];
29023             if (hub->type == VIR_DOMAIN_HUB_TYPE_USB) {
29024                 if (iter(&hub->info, opaque) < 0)
29025                     return -1;
29026             }
29027         }
29028     }
29029 
29030     /* usb-host */
29031     for (i = 0; i < def->nhostdevs; i++) {
29032         virDomainHostdevDef *hostdev = def->hostdevs[i];
29033         if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
29034             if (iter(hostdev->info, opaque) < 0)
29035                 return -1;
29036         }
29037     }
29038 
29039     /* usb-storage */
29040     for (i = 0; i < def->ndisks; i++) {
29041         virDomainDiskDef *disk = def->disks[i];
29042         if (disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
29043             if (iter(&disk->info, opaque) < 0)
29044                 return -1;
29045         }
29046     }
29047 
29048     /* TODO: add def->nets here when libvirt starts supporting usb-net */
29049 
29050     /* usb-ccid */
29051     for (i = 0; i < def->ncontrollers; i++) {
29052         virDomainControllerDef *cont = def->controllers[i];
29053         if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID) {
29054             if (iter(&cont->info, opaque) < 0)
29055                 return -1;
29056         }
29057     }
29058 
29059     /* usb-kbd, usb-mouse, usb-tablet */
29060     for (i = 0; i < def->ninputs; i++) {
29061         virDomainInputDef *input = def->inputs[i];
29062 
29063         if (input->bus == VIR_DOMAIN_INPUT_BUS_USB) {
29064             if (iter(&input->info, opaque) < 0)
29065                 return -1;
29066         }
29067     }
29068 
29069     /* usb-serial */
29070     for (i = 0; i < def->nserials; i++) {
29071         virDomainChrDef *serial = def->serials[i];
29072         if (serial->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB) {
29073             if (iter(&serial->info, opaque) < 0)
29074                 return -1;
29075         }
29076     }
29077 
29078     /* usb-audio model=usb */
29079     for (i = 0; i < def->nsounds; i++) {
29080         virDomainSoundDef *sound = def->sounds[i];
29081         if (sound->model == VIR_DOMAIN_SOUND_MODEL_USB) {
29082             if (iter(&sound->info, opaque) < 0)
29083                 return -1;
29084         }
29085     }
29086 
29087     /* usb-redir */
29088     for (i = 0; i < def->nredirdevs; i++) {
29089         virDomainRedirdevDef *redirdev = def->redirdevs[i];
29090         if (redirdev->bus == VIR_DOMAIN_REDIRDEV_BUS_USB) {
29091             if (iter(&redirdev->info, opaque) < 0)
29092                 return -1;
29093         }
29094     }
29095 
29096     return 0;
29097 }
29098 
29099 
29100 /* Copy src into a new definition; with the quality of the copy
29101  * depending on the migratable flag (false for transitions between
29102  * persistent and active, true for transitions across save files or
29103  * snapshots).  */
29104 virDomainDef *
virDomainDefCopy(virDomainDef * src,virDomainXMLOption * xmlopt,void * parseOpaque,bool migratable)29105 virDomainDefCopy(virDomainDef *src,
29106                  virDomainXMLOption *xmlopt,
29107                  void *parseOpaque,
29108                  bool migratable)
29109 {
29110     unsigned int format_flags = VIR_DOMAIN_DEF_FORMAT_SECURE;
29111     unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE |
29112                                VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE;
29113     g_autofree char *xml = NULL;
29114 
29115     if (migratable)
29116         format_flags |= VIR_DOMAIN_DEF_FORMAT_INACTIVE | VIR_DOMAIN_DEF_FORMAT_MIGRATABLE;
29117 
29118     /* Easiest to clone via a round-trip through XML.  */
29119     if (!(xml = virDomainDefFormat(src, xmlopt, format_flags)))
29120         return NULL;
29121 
29122     return virDomainDefParseString(xml, xmlopt, parseOpaque, parse_flags);
29123 }
29124 
29125 virDomainDef *
virDomainObjCopyPersistentDef(virDomainObj * dom,virDomainXMLOption * xmlopt,void * parseOpaque)29126 virDomainObjCopyPersistentDef(virDomainObj *dom,
29127                               virDomainXMLOption *xmlopt,
29128                               void *parseOpaque)
29129 {
29130     virDomainDef *cur;
29131 
29132     cur = virDomainObjGetPersistentDef(xmlopt, dom, parseOpaque);
29133     if (!cur) {
29134         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
29135                        _("failed to get persistent definition object"));
29136         return NULL;
29137     }
29138 
29139     return virDomainDefCopy(cur, xmlopt, parseOpaque, false);
29140 }
29141 
29142 
29143 virDomainState
virDomainObjGetState(virDomainObj * dom,int * reason)29144 virDomainObjGetState(virDomainObj *dom, int *reason)
29145 {
29146     if (reason)
29147         *reason = dom->state.reason;
29148 
29149     return dom->state.state;
29150 }
29151 
29152 
29153 void
virDomainObjSetState(virDomainObj * dom,virDomainState state,int reason)29154 virDomainObjSetState(virDomainObj *dom, virDomainState state, int reason)
29155 {
29156     int last;
29157 
29158     switch (state) {
29159     case VIR_DOMAIN_NOSTATE:
29160         last = VIR_DOMAIN_NOSTATE_LAST;
29161         break;
29162     case VIR_DOMAIN_RUNNING:
29163         last = VIR_DOMAIN_RUNNING_LAST;
29164         break;
29165     case VIR_DOMAIN_BLOCKED:
29166         last = VIR_DOMAIN_BLOCKED_LAST;
29167         break;
29168     case VIR_DOMAIN_PAUSED:
29169         last = VIR_DOMAIN_PAUSED_LAST;
29170         break;
29171     case VIR_DOMAIN_SHUTDOWN:
29172         last = VIR_DOMAIN_SHUTDOWN_LAST;
29173         break;
29174     case VIR_DOMAIN_SHUTOFF:
29175         last = VIR_DOMAIN_SHUTOFF_LAST;
29176         break;
29177     case VIR_DOMAIN_CRASHED:
29178         last = VIR_DOMAIN_CRASHED_LAST;
29179         break;
29180     case VIR_DOMAIN_PMSUSPENDED:
29181         last = VIR_DOMAIN_PMSUSPENDED_LAST;
29182         break;
29183     case VIR_DOMAIN_LAST:
29184     default:
29185         VIR_ERROR(_("invalid domain state: %d"), state);
29186         return;
29187     }
29188 
29189     dom->state.state = state;
29190     if (reason > 0 && reason < last)
29191         dom->state.reason = reason;
29192     else
29193         dom->state.reason = 0;
29194 }
29195 
29196 
29197 const char *
virDomainStateReasonToString(virDomainState state,int reason)29198 virDomainStateReasonToString(virDomainState state, int reason)
29199 {
29200     switch (state) {
29201     case VIR_DOMAIN_NOSTATE:
29202         return virDomainNostateReasonTypeToString(reason);
29203     case VIR_DOMAIN_RUNNING:
29204         return virDomainRunningReasonTypeToString(reason);
29205     case VIR_DOMAIN_BLOCKED:
29206         return virDomainBlockedReasonTypeToString(reason);
29207     case VIR_DOMAIN_PAUSED:
29208         return virDomainPausedReasonTypeToString(reason);
29209     case VIR_DOMAIN_SHUTDOWN:
29210         return virDomainShutdownReasonTypeToString(reason);
29211     case VIR_DOMAIN_SHUTOFF:
29212         return virDomainShutoffReasonTypeToString(reason);
29213     case VIR_DOMAIN_CRASHED:
29214         return virDomainCrashedReasonTypeToString(reason);
29215     case VIR_DOMAIN_PMSUSPENDED:
29216         return virDomainPMSuspendedReasonTypeToString(reason);
29217     case VIR_DOMAIN_LAST:
29218         break;
29219     }
29220     VIR_WARN("Unexpected domain state: %d", state);
29221     return NULL;
29222 }
29223 
29224 
29225 int
virDomainStateReasonFromString(virDomainState state,const char * reason)29226 virDomainStateReasonFromString(virDomainState state, const char *reason)
29227 {
29228     switch (state) {
29229     case VIR_DOMAIN_NOSTATE:
29230         return virDomainNostateReasonTypeFromString(reason);
29231     case VIR_DOMAIN_RUNNING:
29232         return virDomainRunningReasonTypeFromString(reason);
29233     case VIR_DOMAIN_BLOCKED:
29234         return virDomainBlockedReasonTypeFromString(reason);
29235     case VIR_DOMAIN_PAUSED:
29236         return virDomainPausedReasonTypeFromString(reason);
29237     case VIR_DOMAIN_SHUTDOWN:
29238         return virDomainShutdownReasonTypeFromString(reason);
29239     case VIR_DOMAIN_SHUTOFF:
29240         return virDomainShutoffReasonTypeFromString(reason);
29241     case VIR_DOMAIN_CRASHED:
29242         return virDomainCrashedReasonTypeFromString(reason);
29243     case VIR_DOMAIN_PMSUSPENDED:
29244         return virDomainPMSuspendedReasonTypeFromString(reason);
29245     case VIR_DOMAIN_LAST:
29246         break;
29247     }
29248     VIR_WARN("Unexpected domain state: %d", state);
29249     return -1;
29250 }
29251 
29252 
29253 /* Some access functions to gloss over the difference between NetDef
29254  * (<interface>) and ActualNetDef (<actual>). If the NetDef has an
29255  * ActualNetDef, return the requested value from the ActualNetDef,
29256  * otherwise return the value from the NetDef.
29257  */
29258 
29259 virDomainNetType
virDomainNetGetActualType(const virDomainNetDef * iface)29260 virDomainNetGetActualType(const virDomainNetDef *iface)
29261 {
29262     if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
29263         return iface->type;
29264     if (!iface->data.network.actual)
29265         return iface->type;
29266     return iface->data.network.actual->type;
29267 }
29268 
29269 const char *
virDomainNetGetActualBridgeName(const virDomainNetDef * iface)29270 virDomainNetGetActualBridgeName(const virDomainNetDef *iface)
29271 {
29272     if (iface->type == VIR_DOMAIN_NET_TYPE_BRIDGE)
29273         return iface->data.bridge.brname;
29274     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29275         iface->data.network.actual &&
29276         (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
29277          iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_NETWORK))
29278         return iface->data.network.actual->data.bridge.brname;
29279     return NULL;
29280 }
29281 
29282 int
virDomainNetGetActualBridgeMACTableManager(const virDomainNetDef * iface)29283 virDomainNetGetActualBridgeMACTableManager(const virDomainNetDef *iface)
29284 {
29285     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29286         iface->data.network.actual &&
29287         (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
29288          iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_NETWORK))
29289         return iface->data.network.actual->data.bridge.macTableManager;
29290     return 0;
29291 }
29292 
29293 const char *
virDomainNetGetActualDirectDev(const virDomainNetDef * iface)29294 virDomainNetGetActualDirectDev(const virDomainNetDef *iface)
29295 {
29296     if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
29297         return iface->data.direct.linkdev;
29298     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29299         iface->data.network.actual &&
29300         iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_DIRECT)
29301         return iface->data.network.actual->data.direct.linkdev;
29302     return NULL;
29303 }
29304 
29305 int
virDomainNetGetActualDirectMode(const virDomainNetDef * iface)29306 virDomainNetGetActualDirectMode(const virDomainNetDef *iface)
29307 {
29308     if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
29309         return iface->data.direct.mode;
29310     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29311         iface->data.network.actual &&
29312         iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_DIRECT)
29313         return iface->data.network.actual->data.direct.mode;
29314     return 0;
29315 }
29316 
29317 virDomainHostdevDef *
virDomainNetGetActualHostdev(virDomainNetDef * iface)29318 virDomainNetGetActualHostdev(virDomainNetDef *iface)
29319 {
29320     if (iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
29321         return &iface->data.hostdev.def;
29322     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29323         iface->data.network.actual &&
29324         iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
29325         return &iface->data.network.actual->data.hostdev.def;
29326     return NULL;
29327 }
29328 
29329 const virNetDevVPortProfile *
virDomainNetGetActualVirtPortProfile(const virDomainNetDef * iface)29330 virDomainNetGetActualVirtPortProfile(const virDomainNetDef *iface)
29331 {
29332     switch (iface->type) {
29333     case VIR_DOMAIN_NET_TYPE_DIRECT:
29334     case VIR_DOMAIN_NET_TYPE_BRIDGE:
29335     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
29336         return iface->virtPortProfile;
29337     case VIR_DOMAIN_NET_TYPE_NETWORK:
29338         if (!iface->data.network.actual)
29339             return NULL;
29340         switch (iface->data.network.actual->type) {
29341         case VIR_DOMAIN_NET_TYPE_DIRECT:
29342         case VIR_DOMAIN_NET_TYPE_BRIDGE:
29343         case VIR_DOMAIN_NET_TYPE_HOSTDEV:
29344             return iface->data.network.actual->virtPortProfile;
29345         case VIR_DOMAIN_NET_TYPE_USER:
29346         case VIR_DOMAIN_NET_TYPE_ETHERNET:
29347         case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
29348         case VIR_DOMAIN_NET_TYPE_SERVER:
29349         case VIR_DOMAIN_NET_TYPE_CLIENT:
29350         case VIR_DOMAIN_NET_TYPE_MCAST:
29351         case VIR_DOMAIN_NET_TYPE_NETWORK:
29352         case VIR_DOMAIN_NET_TYPE_INTERNAL:
29353         case VIR_DOMAIN_NET_TYPE_UDP:
29354         case VIR_DOMAIN_NET_TYPE_VDPA:
29355         case VIR_DOMAIN_NET_TYPE_LAST:
29356             break;
29357         }
29358         return NULL;
29359     case VIR_DOMAIN_NET_TYPE_USER:
29360     case VIR_DOMAIN_NET_TYPE_ETHERNET:
29361     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
29362     case VIR_DOMAIN_NET_TYPE_SERVER:
29363     case VIR_DOMAIN_NET_TYPE_CLIENT:
29364     case VIR_DOMAIN_NET_TYPE_MCAST:
29365     case VIR_DOMAIN_NET_TYPE_INTERNAL:
29366     case VIR_DOMAIN_NET_TYPE_UDP:
29367     case VIR_DOMAIN_NET_TYPE_VDPA:
29368     case VIR_DOMAIN_NET_TYPE_LAST:
29369     default:
29370         return NULL;
29371     }
29372 }
29373 
29374 /* Check whether the port is an ovs managed port */
29375 bool
virDomainNetDefIsOvsport(const virDomainNetDef * net)29376 virDomainNetDefIsOvsport(const virDomainNetDef *net)
29377 {
29378     const virNetDevVPortProfile *vport = virDomainNetGetActualVirtPortProfile(net);
29379     virDomainNetType actualType = virDomainNetGetActualType(net);
29380 
29381     return (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) && vport &&
29382         vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH;
29383 }
29384 
29385 const virNetDevBandwidth *
virDomainNetGetActualBandwidth(const virDomainNetDef * iface)29386 virDomainNetGetActualBandwidth(const virDomainNetDef *iface)
29387 {
29388     /* if there is an ActualNetDef, *always* return
29389      * its bandwidth rather than the NetDef's bandwidth.
29390      */
29391     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29392         iface->data.network.actual)
29393         return iface->data.network.actual->bandwidth;
29394     return iface->bandwidth;
29395 }
29396 
29397 const virNetDevVlan *
virDomainNetGetActualVlan(const virDomainNetDef * iface)29398 virDomainNetGetActualVlan(const virDomainNetDef *iface)
29399 {
29400     const virNetDevVlan *vlan = &iface->vlan;
29401 
29402     /* if there is an ActualNetDef, *always* return
29403      * its vlan rather than the NetDef's vlan.
29404      */
29405     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29406         iface->data.network.actual)
29407         vlan = &iface->data.network.actual->vlan;
29408 
29409     if (vlan->nTags > 0)
29410         return vlan;
29411     return NULL;
29412 }
29413 
29414 
29415 virTristateBool
virDomainNetGetActualPortOptionsIsolated(const virDomainNetDef * iface)29416 virDomainNetGetActualPortOptionsIsolated(const virDomainNetDef *iface)
29417 {
29418     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29419         iface->data.network.actual) {
29420         return iface->data.network.actual->isolatedPort;
29421     }
29422     return iface->isolatedPort;
29423 }
29424 
29425 
29426 bool
virDomainNetGetActualTrustGuestRxFilters(const virDomainNetDef * iface)29427 virDomainNetGetActualTrustGuestRxFilters(const virDomainNetDef *iface)
29428 {
29429     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
29430         iface->data.network.actual)
29431         return (iface->data.network.actual->trustGuestRxFilters
29432                 == VIR_TRISTATE_BOOL_YES);
29433     return iface->trustGuestRxFilters == VIR_TRISTATE_BOOL_YES;
29434 }
29435 
29436 const char *
virDomainNetGetModelString(const virDomainNetDef * net)29437 virDomainNetGetModelString(const virDomainNetDef *net)
29438 {
29439     if (net->model)
29440         return virDomainNetModelTypeToString(net->model);
29441     return net->modelstr;
29442 }
29443 
29444 int
virDomainNetSetModelString(virDomainNetDef * net,const char * model)29445 virDomainNetSetModelString(virDomainNetDef *net,
29446                            const char *model)
29447 {
29448     size_t i;
29449 
29450     VIR_FREE(net->modelstr);
29451     net->model = VIR_DOMAIN_NET_MODEL_UNKNOWN;
29452     if (!model)
29453         return 0;
29454 
29455     for (i = 0; i < G_N_ELEMENTS(virDomainNetModelTypeList); i++) {
29456         if (STRCASEEQ(virDomainNetModelTypeList[i], model)) {
29457             net->model = i;
29458             return 0;
29459         }
29460     }
29461 
29462     if (strspn(model, NET_MODEL_CHARS) < strlen(model)) {
29463         virReportError(VIR_ERR_INVALID_ARG, "%s",
29464                        _("Model name contains invalid characters"));
29465         return -1;
29466     }
29467 
29468     net->modelstr = g_strdup(model);
29469     return 0;
29470 }
29471 
29472 bool
virDomainNetIsVirtioModel(const virDomainNetDef * net)29473 virDomainNetIsVirtioModel(const virDomainNetDef *net)
29474 {
29475     return (net->model == VIR_DOMAIN_NET_MODEL_VIRTIO ||
29476             net->model == VIR_DOMAIN_NET_MODEL_VIRTIO_TRANSITIONAL ||
29477             net->model == VIR_DOMAIN_NET_MODEL_VIRTIO_NON_TRANSITIONAL);
29478 }
29479 
29480 
29481 /* Return listens[i] from the appropriate union for the graphics
29482  * type, or NULL if this is an unsuitable type, or the index is out of
29483  * bounds. If force0 is TRUE, i == 0, and there is no listen array,
29484  * allocate one with a single item. */
29485 virDomainGraphicsListenDef *
virDomainGraphicsGetListen(virDomainGraphicsDef * def,size_t i)29486 virDomainGraphicsGetListen(virDomainGraphicsDef *def, size_t i)
29487 {
29488     if (!def->listens || (def->nListens <= i))
29489         return NULL;
29490 
29491     return &def->listens[i];
29492 }
29493 
29494 
29495 int
virDomainGraphicsListenAppendAddress(virDomainGraphicsDef * def,const char * address)29496 virDomainGraphicsListenAppendAddress(virDomainGraphicsDef *def,
29497                                      const char *address)
29498 {
29499     virDomainGraphicsListenDef glisten;
29500 
29501     memset(&glisten, 0, sizeof(glisten));
29502 
29503     glisten.type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_ADDRESS;
29504 
29505     glisten.address = g_strdup(address);
29506 
29507     VIR_APPEND_ELEMENT_COPY(def->listens, def->nListens, glisten);
29508 
29509     return 0;
29510 }
29511 
29512 
29513 int
virDomainGraphicsListenAppendSocket(virDomainGraphicsDef * def,const char * socketPath)29514 virDomainGraphicsListenAppendSocket(virDomainGraphicsDef *def,
29515                                     const char *socketPath)
29516 {
29517     virDomainGraphicsListenDef glisten;
29518 
29519     memset(&glisten, 0, sizeof(glisten));
29520 
29521     glisten.type = VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_SOCKET;
29522 
29523     glisten.socket = g_strdup(socketPath);
29524 
29525     VIR_APPEND_ELEMENT_COPY(def->listens, def->nListens, glisten);
29526 
29527     return 0;
29528 }
29529 
29530 
29531 /**
29532  * virDomainNetFind:
29533  * @def: domain's def
29534  * @device: could be the interface name or MAC address
29535  *
29536  * Finds a domain's net def, given the interface name or MAC address
29537  *
29538  * Returns a pointer to the net def or NULL if not found (error is reported).
29539  */
29540 virDomainNetDef *
virDomainNetFind(virDomainDef * def,const char * device)29541 virDomainNetFind(virDomainDef *def, const char *device)
29542 {
29543     bool isMac = false;
29544     virMacAddr mac;
29545     size_t i;
29546 
29547     if (virMacAddrParse(device, &mac) == 0)
29548         isMac = true;
29549 
29550     if (isMac) {
29551         for (i = 0; i < def->nnets; i++) {
29552             if (virMacAddrCmp(&mac, &def->nets[i]->mac) == 0)
29553                 return def->nets[i];
29554         }
29555     } else { /* ifname */
29556         virDomainNetDef *net = NULL;
29557 
29558         if ((net = virDomainNetFindByName(def, device)))
29559             return net;
29560     }
29561 
29562     virReportError(VIR_ERR_INVALID_ARG,
29563                    _("'%s' is not a known interface"), device);
29564     return NULL;
29565 }
29566 
29567 
29568 /**
29569  * virDomainNetFindByName:
29570  * @def: domain's def
29571  * @ifname: interface name
29572  *
29573  * Finds a domain's net def given the interface name.
29574  *
29575  * Returns a pointer to the net def or NULL if not found.
29576  */
29577 virDomainNetDef *
virDomainNetFindByName(virDomainDef * def,const char * ifname)29578 virDomainNetFindByName(virDomainDef *def,
29579                        const char *ifname)
29580 {
29581     size_t i;
29582 
29583     for (i = 0; i < def->nnets; i++) {
29584         if (STREQ_NULLABLE(ifname, def->nets[i]->ifname))
29585             return def->nets[i];
29586     }
29587 
29588     return NULL;
29589 }
29590 
29591 
29592 /**
29593  * virDomainDeviceDefCopy:
29594  * @caps: Capabilities
29595  * @def: Domain definition to which @src belongs
29596  * @src: source to be copied
29597  *
29598  * virDomainDeviceDefCopy does a deep copy of only the parts of a
29599  * DeviceDef that are valid when just the flag VIR_DOMAIN_DEF_PARSE_INACTIVE is
29600  * set. This means that any part of the device xml that is conditionally
29601  * parsed/formatted based on some other flag being set (or on the INACTIVE
29602  * flag being reset) *will not* be copied to the destination. Caveat emptor.
29603  *
29604  * Returns a pointer to copied @src or NULL in case of error.
29605  */
29606 virDomainDeviceDef *
virDomainDeviceDefCopy(virDomainDeviceDef * src,const virDomainDef * def,virDomainXMLOption * xmlopt,void * parseOpaque)29607 virDomainDeviceDefCopy(virDomainDeviceDef *src,
29608                        const virDomainDef *def,
29609                        virDomainXMLOption *xmlopt,
29610                        void *parseOpaque)
29611 {
29612     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
29613     int flags = VIR_DOMAIN_DEF_FORMAT_INACTIVE | VIR_DOMAIN_DEF_FORMAT_SECURE;
29614     int rc = -1;
29615     g_autofree char *xmlStr = NULL;
29616 
29617     switch ((virDomainDeviceType) src->type) {
29618     case VIR_DOMAIN_DEVICE_DISK:
29619         rc = virDomainDiskDefFormat(&buf, src->data.disk, flags, xmlopt);
29620         break;
29621     case VIR_DOMAIN_DEVICE_LEASE:
29622         virDomainLeaseDefFormat(&buf, src->data.lease);
29623         rc = 0;
29624         break;
29625     case VIR_DOMAIN_DEVICE_FS:
29626         rc = virDomainFSDefFormat(&buf, src->data.fs, flags);
29627         break;
29628     case VIR_DOMAIN_DEVICE_NET:
29629         rc = virDomainNetDefFormat(&buf, src->data.net, xmlopt, flags);
29630         break;
29631     case VIR_DOMAIN_DEVICE_INPUT:
29632         rc = virDomainInputDefFormat(&buf, src->data.input, flags);
29633         break;
29634     case VIR_DOMAIN_DEVICE_SOUND:
29635         rc = virDomainSoundDefFormat(&buf, src->data.sound, flags);
29636         break;
29637     case VIR_DOMAIN_DEVICE_VIDEO:
29638         rc = virDomainVideoDefFormat(&buf, src->data.video, flags);
29639         break;
29640     case VIR_DOMAIN_DEVICE_HOSTDEV:
29641         rc = virDomainHostdevDefFormat(&buf, src->data.hostdev, flags, xmlopt);
29642         break;
29643     case VIR_DOMAIN_DEVICE_WATCHDOG:
29644         rc = virDomainWatchdogDefFormat(&buf, src->data.watchdog, flags);
29645         break;
29646     case VIR_DOMAIN_DEVICE_CONTROLLER:
29647         rc = virDomainControllerDefFormat(&buf, src->data.controller, flags);
29648         break;
29649     case VIR_DOMAIN_DEVICE_GRAPHICS:
29650         rc = virDomainGraphicsDefFormat(&buf, src->data.graphics, flags);
29651         break;
29652     case VIR_DOMAIN_DEVICE_HUB:
29653         rc = virDomainHubDefFormat(&buf, src->data.hub, flags);
29654         break;
29655     case VIR_DOMAIN_DEVICE_REDIRDEV:
29656         rc = virDomainRedirdevDefFormat(&buf, src->data.redirdev, flags);
29657         break;
29658     case VIR_DOMAIN_DEVICE_RNG:
29659         rc = virDomainRNGDefFormat(&buf, src->data.rng, flags);
29660         break;
29661     case VIR_DOMAIN_DEVICE_CHR:
29662         rc = virDomainChrDefFormat(&buf, src->data.chr, flags);
29663         break;
29664     case VIR_DOMAIN_DEVICE_TPM:
29665         rc = virDomainTPMDefFormat(&buf, src->data.tpm, flags);
29666         break;
29667     case VIR_DOMAIN_DEVICE_PANIC:
29668         virDomainPanicDefFormat(&buf, src->data.panic);
29669         rc = 0;
29670         break;
29671     case VIR_DOMAIN_DEVICE_MEMORY:
29672         rc = virDomainMemoryDefFormat(&buf, src->data.memory, flags);
29673         break;
29674     case VIR_DOMAIN_DEVICE_SHMEM:
29675         virDomainShmemDefFormat(&buf, src->data.shmem, flags);
29676         rc = 0;
29677         break;
29678     case VIR_DOMAIN_DEVICE_IOMMU:
29679         virDomainIOMMUDefFormat(&buf, src->data.iommu);
29680         rc = 0;
29681         break;
29682     case VIR_DOMAIN_DEVICE_VSOCK:
29683         virDomainVsockDefFormat(&buf, src->data.vsock);
29684         rc = 0;
29685         break;
29686     case VIR_DOMAIN_DEVICE_AUDIO:
29687         rc = virDomainAudioDefFormat(&buf, src->data.audio);
29688         break;
29689 
29690     case VIR_DOMAIN_DEVICE_NONE:
29691     case VIR_DOMAIN_DEVICE_SMARTCARD:
29692     case VIR_DOMAIN_DEVICE_MEMBALLOON:
29693     case VIR_DOMAIN_DEVICE_NVRAM:
29694     case VIR_DOMAIN_DEVICE_LAST:
29695         virReportError(VIR_ERR_INTERNAL_ERROR,
29696                        _("Copying definition of '%d' type "
29697                          "is not implemented yet."),
29698                        src->type);
29699         return NULL;
29700     }
29701 
29702     if (rc < 0)
29703         return NULL;
29704 
29705     xmlStr = virBufferContentAndReset(&buf);
29706     return virDomainDeviceDefParse(xmlStr, def, xmlopt, parseOpaque,
29707                                    VIR_DOMAIN_DEF_PARSE_INACTIVE |
29708                                    VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE);
29709 }
29710 
29711 
29712 virSecurityLabelDef *
virDomainDefGetSecurityLabelDef(const virDomainDef * def,const char * model)29713 virDomainDefGetSecurityLabelDef(const virDomainDef *def, const char *model)
29714 {
29715     size_t i;
29716     virSecurityLabelDef *seclabel = NULL;
29717 
29718     if (def == NULL || model == NULL)
29719         return NULL;
29720 
29721     for (i = 0; i < def->nseclabels; i++) {
29722         if (def->seclabels[i]->model == NULL)
29723             continue;
29724         if (STREQ(def->seclabels[i]->model, model))
29725             return def->seclabels[i];
29726     }
29727 
29728     return seclabel;
29729 }
29730 
29731 
29732 virSecurityDeviceLabelDef *
virDomainChrSourceDefGetSecurityLabelDef(virDomainChrSourceDef * def,const char * model)29733 virDomainChrSourceDefGetSecurityLabelDef(virDomainChrSourceDef *def,
29734                                          const char *model)
29735 {
29736     size_t i;
29737 
29738     if (def == NULL)
29739         return NULL;
29740 
29741     for (i = 0; i < def->nseclabels; i++) {
29742         if (STREQ_NULLABLE(def->seclabels[i]->model, model))
29743             return def->seclabels[i];
29744     }
29745     return NULL;
29746 }
29747 
29748 
29749 typedef struct {
29750     const char *devAlias;
29751     virDomainDeviceDef *dev;
29752 } virDomainDefFindDeviceCallbackData;
29753 
29754 static int
virDomainDefFindDeviceCallback(virDomainDef * def G_GNUC_UNUSED,virDomainDeviceDef * dev,virDomainDeviceInfo * info,void * opaque)29755 virDomainDefFindDeviceCallback(virDomainDef *def G_GNUC_UNUSED,
29756                                virDomainDeviceDef *dev,
29757                                virDomainDeviceInfo *info,
29758                                void *opaque)
29759 {
29760     virDomainDefFindDeviceCallbackData *data = opaque;
29761 
29762     if (STREQ_NULLABLE(info->alias, data->devAlias)) {
29763         *data->dev = *dev;
29764         return -1;
29765     }
29766     return 0;
29767 }
29768 
29769 int
virDomainDefFindDevice(virDomainDef * def,const char * devAlias,virDomainDeviceDef * dev,bool reportError)29770 virDomainDefFindDevice(virDomainDef *def,
29771                        const char *devAlias,
29772                        virDomainDeviceDef *dev,
29773                        bool reportError)
29774 {
29775     virDomainDefFindDeviceCallbackData data = { devAlias, dev };
29776 
29777     dev->type = VIR_DOMAIN_DEVICE_NONE;
29778     virDomainDeviceInfoIterateFlags(def, virDomainDefFindDeviceCallback,
29779                                     DOMAIN_DEVICE_ITERATE_ALL_CONSOLES,
29780                                     &data);
29781 
29782     if (dev->type == VIR_DOMAIN_DEVICE_NONE) {
29783         if (reportError) {
29784             virReportError(VIR_ERR_INTERNAL_ERROR,
29785                            _("no device found with alias %s"), devAlias);
29786         } else {
29787             VIR_DEBUG("no device found with alias %s", devAlias);
29788         }
29789         return -1;
29790     }
29791 
29792     return 0;
29793 }
29794 
29795 
29796 virDomainAudioDef *
virDomainDefFindAudioByID(const virDomainDef * def,int id)29797 virDomainDefFindAudioByID(const virDomainDef *def,
29798                           int id)
29799 {
29800     size_t i;
29801     if (id != 0) {
29802         for (i = 0; i < def->naudios; i++)
29803             if (def->audios[i]->id == id)
29804                 return def->audios[i];
29805     } else if (def->naudios) {
29806         return def->audios[0];
29807     }
29808 
29809     return NULL;
29810 }
29811 
29812 
29813 bool
virDomainSoundModelSupportsCodecs(virDomainSoundDef * def)29814 virDomainSoundModelSupportsCodecs(virDomainSoundDef *def)
29815 {
29816     return def->model == VIR_DOMAIN_SOUND_MODEL_ICH6 ||
29817         def->model == VIR_DOMAIN_SOUND_MODEL_ICH9;
29818 }
29819 
29820 bool
virDomainAudioIOCommonIsSet(virDomainAudioIOCommon * common)29821 virDomainAudioIOCommonIsSet(virDomainAudioIOCommon *common)
29822 {
29823     return common->mixingEngine ||
29824         common->fixedSettings ||
29825         common->frequency ||
29826         common->channels ||
29827         common->voices ||
29828         common->format ||
29829         common->bufferLength;
29830 }
29831 
29832 char *
virDomainObjGetMetadata(virDomainObj * vm,int type,const char * uri,unsigned int flags)29833 virDomainObjGetMetadata(virDomainObj *vm,
29834                         int type,
29835                         const char *uri,
29836                         unsigned int flags)
29837 {
29838     virDomainDef *def;
29839     char *ret = NULL;
29840 
29841     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
29842                   VIR_DOMAIN_AFFECT_CONFIG, NULL);
29843 
29844     if (type >= VIR_DOMAIN_METADATA_LAST) {
29845         virReportError(VIR_ERR_INVALID_ARG,
29846                        _("unknown metadata type '%d'"), type);
29847         return NULL;
29848     }
29849 
29850     if (!(def = virDomainObjGetOneDef(vm, flags)))
29851         return NULL;
29852 
29853     switch ((virDomainMetadataType) type) {
29854     case VIR_DOMAIN_METADATA_DESCRIPTION:
29855         ret = g_strdup(def->description);
29856         break;
29857 
29858     case VIR_DOMAIN_METADATA_TITLE:
29859         ret = g_strdup(def->title);
29860         break;
29861 
29862     case VIR_DOMAIN_METADATA_ELEMENT:
29863         if (!def->metadata)
29864             break;
29865 
29866         if (virXMLExtractNamespaceXML(def->metadata, uri, &ret) < 0)
29867             return NULL;
29868         break;
29869 
29870     case VIR_DOMAIN_METADATA_LAST:
29871         break;
29872     }
29873 
29874     if (!ret)
29875         virReportError(VIR_ERR_NO_DOMAIN_METADATA, "%s",
29876                        _("Requested metadata element is not present"));
29877 
29878     return ret;
29879 }
29880 
29881 
29882 static int
virDomainDefSetMetadata(virDomainDef * def,int type,const char * metadata,const char * key,const char * uri)29883 virDomainDefSetMetadata(virDomainDef *def,
29884                         int type,
29885                         const char *metadata,
29886                         const char *key,
29887                         const char *uri)
29888 {
29889     g_autoptr(xmlDoc) doc = NULL;
29890     xmlNodePtr old;
29891     g_autoptr(xmlNode) new = NULL;
29892 
29893     if (type >= VIR_DOMAIN_METADATA_LAST) {
29894         virReportError(VIR_ERR_INVALID_ARG,
29895                        _("unknown metadata type '%d'"), type);
29896         return -1;
29897     }
29898 
29899     switch ((virDomainMetadataType) type) {
29900     case VIR_DOMAIN_METADATA_DESCRIPTION:
29901         g_clear_pointer(&def->description, g_free);
29902 
29903         if (STRNEQ_NULLABLE(metadata, ""))
29904             def->description = g_strdup(metadata);
29905         break;
29906 
29907     case VIR_DOMAIN_METADATA_TITLE:
29908         g_clear_pointer(&def->title, g_free);
29909 
29910         if (STRNEQ_NULLABLE(metadata, ""))
29911             def->title = g_strdup(metadata);
29912         break;
29913 
29914     case VIR_DOMAIN_METADATA_ELEMENT:
29915         if (metadata) {
29916 
29917             /* parse and modify the xml from the user */
29918             if (!(doc = virXMLParseString(metadata, _("(metadata_xml)"))))
29919                 return -1;
29920 
29921             if (virXMLInjectNamespace(doc->children, uri, key) < 0)
29922                 return -1;
29923 
29924             /* create the root node if needed */
29925             if (!def->metadata)
29926                 def->metadata = virXMLNewNode(NULL, "metadata");
29927 
29928             if (!(new = xmlCopyNode(doc->children, 1))) {
29929                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
29930                                _("Failed to copy XML node"));
29931                 return -1;
29932             }
29933         }
29934 
29935         /* remove possible other nodes sharing the namespace */
29936         while ((old = virXMLFindChildNodeByNs(def->metadata, uri))) {
29937             xmlUnlinkNode(old);
29938             xmlFreeNode(old);
29939         }
29940 
29941         if (new) {
29942             if (!(xmlAddChild(def->metadata, new))) {
29943                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
29944                                _("failed to add metadata to XML document"));
29945                 return -1;
29946             }
29947             new = NULL;
29948         }
29949         break;
29950 
29951     case VIR_DOMAIN_METADATA_LAST:
29952         break;
29953     }
29954 
29955     return 0;
29956 }
29957 
29958 
29959 int
virDomainObjSetMetadata(virDomainObj * vm,int type,const char * metadata,const char * key,const char * uri,virDomainXMLOption * xmlopt,const char * stateDir,const char * configDir,unsigned int flags)29960 virDomainObjSetMetadata(virDomainObj *vm,
29961                         int type,
29962                         const char *metadata,
29963                         const char *key,
29964                         const char *uri,
29965                         virDomainXMLOption *xmlopt,
29966                         const char *stateDir,
29967                         const char *configDir,
29968                         unsigned int flags)
29969 {
29970     virDomainDef *def;
29971     virDomainDef *persistentDef;
29972 
29973     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
29974                   VIR_DOMAIN_AFFECT_CONFIG, -1);
29975 
29976     if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
29977         return -1;
29978 
29979     if (def) {
29980         if (virDomainDefSetMetadata(def, type, metadata, key, uri) < 0)
29981             return -1;
29982 
29983         if (virDomainObjSave(vm, xmlopt, stateDir) < 0)
29984             return -1;
29985     }
29986 
29987     if (persistentDef) {
29988         if (virDomainDefSetMetadata(persistentDef, type, metadata, key,
29989                                     uri) < 0)
29990             return -1;
29991 
29992         if (virDomainDefSave(persistentDef, xmlopt, configDir) < 0)
29993             return -1;
29994     }
29995 
29996     return 0;
29997 }
29998 
29999 
30000 bool
virDomainDefNeedsPlacementAdvice(virDomainDef * def)30001 virDomainDefNeedsPlacementAdvice(virDomainDef *def)
30002 {
30003     if (def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO)
30004         return true;
30005 
30006     if (virDomainNumatuneHasPlacementAuto(def->numa))
30007         return true;
30008 
30009     return false;
30010 }
30011 
30012 
30013 int
virDomainDiskDefCheckDuplicateInfo(const virDomainDiskDef * a,const virDomainDiskDef * b)30014 virDomainDiskDefCheckDuplicateInfo(const virDomainDiskDef *a,
30015                                    const virDomainDiskDef *b)
30016 {
30017     if (STREQ(a->dst, b->dst)) {
30018         virReportError(VIR_ERR_XML_ERROR,
30019                        _("target '%s' duplicated for disk sources '%s' and '%s'"),
30020                        a->dst,
30021                        NULLSTR(virDomainDiskGetSource(a)),
30022                        NULLSTR(virDomainDiskGetSource(b)));
30023         return -1;
30024     }
30025 
30026     /* Duplicate WWN/serial isn't usually problematic for the OS and
30027      * forbidding it would possibly inhibit using multipath configurations */
30028 
30029     return 0;
30030 }
30031 
30032 
30033 /**
30034  * virDomainDefHasMemballoon:
30035  * @def: domain definition
30036  *
30037  * Returns true if domain has a memory ballooning device configured.
30038  */
30039 bool
virDomainDefHasMemballoon(const virDomainDef * def)30040 virDomainDefHasMemballoon(const virDomainDef *def)
30041 {
30042     return def->memballoon &&
30043            def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE;
30044 }
30045 
30046 
30047 #define VIR_DOMAIN_SHORT_NAME_MAX 20
30048 
30049 /**
30050  * virDomainDefGetShortName:
30051  * @vm: Machine for which to get a name
30052  * @unique: Make sure the name is unique (use id as well)
30053  *
30054  * Shorten domain name to avoid possible path length limitations.
30055  */
30056 char *
virDomainDefGetShortName(const virDomainDef * def)30057 virDomainDefGetShortName(const virDomainDef *def)
30058 {
30059     wchar_t wshortname[VIR_DOMAIN_SHORT_NAME_MAX + 1] = {0};
30060     size_t len = 0;
30061     g_autofree char *shortname = NULL;
30062 
30063     /* No need to do the whole conversion thing when there are no multibyte
30064      * characters.  The same applies for illegal sequences as they can occur
30065      * with incompatible locales. */
30066     len = mbstowcs(NULL, def->name, 0);
30067     if ((len == (size_t) -1 && errno == EILSEQ) ||
30068         len == strlen(def->name)) {
30069         return g_strdup_printf("%d-%.*s", def->id, VIR_DOMAIN_SHORT_NAME_MAX,
30070                                def->name);
30071     }
30072 
30073     if (len == (size_t) -1) {
30074         virReportSystemError(errno, "%s",
30075                              _("Cannot convert domain name to "
30076                                "wide character string"));
30077         return NULL;
30078     }
30079 
30080     if (mbstowcs(wshortname, def->name, VIR_DOMAIN_SHORT_NAME_MAX) == (size_t) -1) {
30081         virReportSystemError(errno, "%s",
30082                              _("Cannot convert domain name to "
30083                                "wide character string"));
30084         return NULL;
30085     }
30086 
30087     len = wcstombs(NULL, wshortname, 0);
30088     if (len == (size_t) -1) {
30089         virReportSystemError(errno, "%s",
30090                              _("Cannot convert wide character string "
30091                                "back to multi-byte domain name"));
30092         return NULL;
30093     }
30094 
30095     shortname = g_new0(char, len + 1);
30096 
30097     if (wcstombs(shortname, wshortname, len) == (size_t) -1) {
30098         virReportSystemError(errno, "%s",
30099                              _("Cannot convert wide character string "
30100                                "back to multi-byte domain name"));
30101         return NULL;
30102     }
30103 
30104     return g_strdup_printf("%d-%s", def->id, shortname);
30105 }
30106 
30107 #undef VIR_DOMAIN_SHORT_NAME_MAX
30108 
30109 int
virDomainGetBlkioParametersAssignFromDef(virDomainDef * def,virTypedParameterPtr params,int * nparams,int maxparams)30110 virDomainGetBlkioParametersAssignFromDef(virDomainDef *def,
30111                                          virTypedParameterPtr params,
30112                                          int *nparams,
30113                                          int maxparams)
30114 {
30115     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
30116     char *data = NULL;
30117     size_t i;
30118 
30119 #define VIR_BLKIO_ASSIGN(param, format, name) \
30120     if (*nparams < maxparams) { \
30121         for (i = 0; i < def->blkio.ndevices; i++) { \
30122             if (!def->blkio.devices[i].param) \
30123                 continue; \
30124             virBufferAsprintf(&buf, "%s," format ",", \
30125                               def->blkio.devices[i].path, \
30126                               def->blkio.devices[i].param); \
30127         } \
30128         virBufferTrim(&buf, ","); \
30129         data = virBufferContentAndReset(&buf); \
30130         if (virTypedParameterAssign(&(params[(*nparams)++]), name, \
30131                                     VIR_TYPED_PARAM_STRING, data) < 0) \
30132             goto error; \
30133         data = NULL; \
30134     }
30135 
30136     /* blkiotune.device_weight */
30137     VIR_BLKIO_ASSIGN(weight, "%u", VIR_DOMAIN_BLKIO_DEVICE_WEIGHT);
30138     /* blkiotune.device_read_iops */
30139     VIR_BLKIO_ASSIGN(riops, "%u", VIR_DOMAIN_BLKIO_DEVICE_READ_IOPS);
30140     /* blkiotune.device_write_iops */
30141     VIR_BLKIO_ASSIGN(wiops, "%u", VIR_DOMAIN_BLKIO_DEVICE_WRITE_IOPS);
30142     /* blkiotune.device_read_bps */
30143     VIR_BLKIO_ASSIGN(rbps, "%llu", VIR_DOMAIN_BLKIO_DEVICE_READ_BPS);
30144     /* blkiotune.device_write_bps */
30145     VIR_BLKIO_ASSIGN(wbps, "%llu", VIR_DOMAIN_BLKIO_DEVICE_WRITE_BPS);
30146 
30147 #undef VIR_BLKIO_ASSIGN
30148 
30149     return 0;
30150 
30151  error:
30152     VIR_FREE(data);
30153     return -1;
30154 }
30155 
30156 
30157 void
virDomainDefVcpuOrderClear(virDomainDef * def)30158 virDomainDefVcpuOrderClear(virDomainDef *def)
30159 {
30160     size_t i;
30161 
30162     for (i = 0; i < def->maxvcpus; i++)
30163         def->vcpus[i]->order = 0;
30164 }
30165 
30166 
30167 /**
30168  * virDomainDiskSetBlockIOTune:
30169  * @disk: The disk to set block I/O tuning on
30170  * @info: The BlockIoTuneInfo to be set on the @disk
30171  *
30172  * Set the block I/O tune settings from @info on the @disk, but error out early
30173  * in case of any error.  That is to make sure nothing will fail half-way.
30174  */
30175 void
virDomainDiskSetBlockIOTune(virDomainDiskDef * disk,virDomainBlockIoTuneInfo * info)30176 virDomainDiskSetBlockIOTune(virDomainDiskDef *disk,
30177                             virDomainBlockIoTuneInfo *info)
30178 {
30179     char *tmp_group = NULL;
30180 
30181     tmp_group = g_strdup(info->group_name);
30182 
30183     VIR_FREE(disk->blkdeviotune.group_name);
30184     disk->blkdeviotune = *info;
30185     disk->blkdeviotune.group_name = g_steal_pointer(&tmp_group);
30186 }
30187 
30188 
30189 /**
30190  * virDomainNetTypeSharesHostView:
30191  * @net: interface
30192  *
30193  * Some types of interfaces "share" the host view. For instance,
30194  * for macvtap interface, every domain RX is the host RX too. And
30195  * every domain TX is host TX too. IOW, for some types of
30196  * interfaces guest and host are on the same side of RX/TX
30197  * barrier. This is important so that we set up QoS correctly and
30198  * report proper stats.
30199  */
30200 bool
virDomainNetTypeSharesHostView(const virDomainNetDef * net)30201 virDomainNetTypeSharesHostView(const virDomainNetDef *net)
30202 {
30203     virDomainNetType actualType = virDomainNetGetActualType(net);
30204     switch (actualType) {
30205     case VIR_DOMAIN_NET_TYPE_DIRECT:
30206     case VIR_DOMAIN_NET_TYPE_ETHERNET:
30207         return true;
30208     case VIR_DOMAIN_NET_TYPE_USER:
30209     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
30210     case VIR_DOMAIN_NET_TYPE_SERVER:
30211     case VIR_DOMAIN_NET_TYPE_CLIENT:
30212     case VIR_DOMAIN_NET_TYPE_MCAST:
30213     case VIR_DOMAIN_NET_TYPE_NETWORK:
30214     case VIR_DOMAIN_NET_TYPE_BRIDGE:
30215     case VIR_DOMAIN_NET_TYPE_INTERNAL:
30216     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
30217     case VIR_DOMAIN_NET_TYPE_UDP:
30218     case VIR_DOMAIN_NET_TYPE_VDPA:
30219     case VIR_DOMAIN_NET_TYPE_LAST:
30220         break;
30221     }
30222     return false;
30223 }
30224 
30225 virNetworkPortDef *
virDomainNetDefToNetworkPort(virDomainDef * dom,virDomainNetDef * iface)30226 virDomainNetDefToNetworkPort(virDomainDef *dom,
30227                              virDomainNetDef *iface)
30228 {
30229     g_autoptr(virNetworkPortDef) port = NULL;
30230 
30231     if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
30232         virReportError(VIR_ERR_INTERNAL_ERROR,
30233                        _("Expected an interface of type 'network' not '%s'"),
30234                        virDomainNetTypeToString(iface->type));
30235         return NULL;
30236     }
30237 
30238     port = g_new0(virNetworkPortDef, 1);
30239 
30240     if (virUUIDGenerate(port->uuid) < 0) {
30241         virReportError(VIR_ERR_INTERNAL_ERROR,
30242                        "%s", _("Failed to generate UUID"));
30243         return NULL;
30244     }
30245 
30246     memcpy(port->owneruuid, dom->uuid, VIR_UUID_BUFLEN);
30247     port->ownername = g_strdup(dom->name);
30248 
30249     port->group = g_strdup(iface->data.network.portgroup);
30250 
30251     memcpy(&port->mac, &iface->mac, VIR_MAC_BUFLEN);
30252 
30253     if (virNetDevVPortProfileCopy(&port->virtPortProfile, iface->virtPortProfile) < 0)
30254         return NULL;
30255 
30256     if (virNetDevBandwidthCopy(&port->bandwidth, iface->bandwidth) < 0)
30257         return NULL;
30258 
30259     if (virNetDevVlanCopy(&port->vlan, &iface->vlan) < 0)
30260         return NULL;
30261 
30262     port->isolatedPort = iface->isolatedPort;
30263     port->trustGuestRxFilters = iface->trustGuestRxFilters;
30264 
30265     return g_steal_pointer(&port);
30266 }
30267 
30268 int
virDomainNetDefActualFromNetworkPort(virDomainNetDef * iface,virNetworkPortDef * port)30269 virDomainNetDefActualFromNetworkPort(virDomainNetDef *iface,
30270                                      virNetworkPortDef *port)
30271 {
30272     virDomainActualNetDef *actual = NULL;
30273 
30274     if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
30275         virReportError(VIR_ERR_INTERNAL_ERROR,
30276                        _("Expected an interface of type 'network' not '%s'"),
30277                        virDomainNetTypeToString(iface->type));
30278         return -1;
30279     }
30280 
30281     actual = g_new0(virDomainActualNetDef, 1);
30282 
30283     switch ((virNetworkPortPlugType)port->plugtype) {
30284     case VIR_NETWORK_PORT_PLUG_TYPE_NONE:
30285         break;
30286 
30287     case VIR_NETWORK_PORT_PLUG_TYPE_NETWORK:
30288         actual->type = VIR_DOMAIN_NET_TYPE_NETWORK;
30289         actual->data.bridge.brname = g_strdup(port->plug.bridge.brname);
30290         actual->data.bridge.macTableManager = port->plug.bridge.macTableManager;
30291         break;
30292 
30293     case VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE:
30294         actual->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
30295         actual->data.bridge.brname = g_strdup(port->plug.bridge.brname);
30296         actual->data.bridge.macTableManager = port->plug.bridge.macTableManager;
30297         break;
30298 
30299     case VIR_NETWORK_PORT_PLUG_TYPE_DIRECT:
30300         actual->type = VIR_DOMAIN_NET_TYPE_DIRECT;
30301         actual->data.direct.linkdev = g_strdup(port->plug.direct.linkdev);
30302         actual->data.direct.mode = port->plug.direct.mode;
30303         break;
30304 
30305     case VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI:
30306         actual->type = VIR_DOMAIN_NET_TYPE_HOSTDEV;
30307         actual->data.hostdev.def.parentnet = iface;
30308         actual->data.hostdev.def.info = &iface->info;
30309         actual->data.hostdev.def.mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
30310         switch (port->plug.hostdevpci.managed) {
30311         case VIR_TRISTATE_BOOL_YES:
30312             actual->data.hostdev.def.managed = true;
30313             break;
30314         case VIR_TRISTATE_BOOL_ABSENT:
30315         case VIR_TRISTATE_BOOL_NO:
30316             actual->data.hostdev.def.managed = false;
30317             break;
30318         }
30319         actual->data.hostdev.def.source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
30320         actual->data.hostdev.def.source.subsys.u.pci.addr = port->plug.hostdevpci.addr;
30321         switch ((virNetworkForwardDriverNameType)port->plug.hostdevpci.driver) {
30322         case VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT:
30323             actual->data.hostdev.def.source.subsys.u.pci.backend =
30324                 VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT;
30325             break;
30326 
30327         case VIR_NETWORK_FORWARD_DRIVER_NAME_KVM:
30328             actual->data.hostdev.def.source.subsys.u.pci.backend =
30329                 VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM;
30330             break;
30331 
30332         case VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO:
30333             actual->data.hostdev.def.source.subsys.u.pci.backend =
30334                 VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
30335             break;
30336 
30337         case VIR_NETWORK_FORWARD_DRIVER_NAME_LAST:
30338         default:
30339             virReportEnumRangeError(virNetworkForwardDriverNameType,
30340                                     port->plug.hostdevpci.driver);
30341             goto error;
30342         }
30343 
30344         break;
30345 
30346     case VIR_NETWORK_PORT_PLUG_TYPE_LAST:
30347     default:
30348         virReportEnumRangeError(virNetworkPortPlugType, port->plugtype);
30349         goto error;
30350     }
30351 
30352     if (virNetDevVPortProfileCopy(&actual->virtPortProfile, port->virtPortProfile) < 0)
30353         goto error;
30354 
30355     if (virNetDevBandwidthCopy(&actual->bandwidth, port->bandwidth) < 0)
30356         goto error;
30357 
30358     if (virNetDevVlanCopy(&actual->vlan, &port->vlan) < 0)
30359         goto error;
30360 
30361     actual->isolatedPort = port->isolatedPort;
30362     actual->class_id = port->class_id;
30363     actual->trustGuestRxFilters = port->trustGuestRxFilters;
30364 
30365     virDomainActualNetDefFree(iface->data.network.actual);
30366     iface->data.network.actual = actual;
30367 
30368     return 0;
30369 
30370  error:
30371     virDomainActualNetDefFree(actual);
30372     return -1;
30373 }
30374 
30375 virNetworkPortDef *
virDomainNetDefActualToNetworkPort(virDomainDef * dom,virDomainNetDef * iface)30376 virDomainNetDefActualToNetworkPort(virDomainDef *dom,
30377                                    virDomainNetDef *iface)
30378 {
30379     virDomainActualNetDef *actual;
30380     g_autoptr(virNetworkPortDef) port = NULL;
30381 
30382     if (!iface->data.network.actual) {
30383         virReportError(VIR_ERR_INTERNAL_ERROR,
30384                        _("Missing actual data for interface '%s'"),
30385                        iface->ifname);
30386         return NULL;
30387     }
30388 
30389     actual = iface->data.network.actual;
30390 
30391     if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
30392         virReportError(VIR_ERR_INTERNAL_ERROR,
30393                        _("Expected an interface of type 'network' not '%s'"),
30394                        virDomainNetTypeToString(iface->type));
30395         return NULL;
30396     }
30397 
30398     port = g_new0(virNetworkPortDef, 1);
30399 
30400     if (virUUIDIsValid(iface->data.network.portid)) {
30401         memcpy(port->uuid, iface->data.network.portid, VIR_UUID_BUFLEN);
30402     } else if (virUUIDGenerate(port->uuid) < 0) {
30403         virReportError(VIR_ERR_INTERNAL_ERROR,
30404                        "%s", _("Failed to generate UUID"));
30405         return NULL;
30406     }
30407 
30408     memcpy(port->owneruuid, dom->uuid, VIR_UUID_BUFLEN);
30409     port->ownername = g_strdup(dom->name);
30410 
30411     port->group = g_strdup(iface->data.network.portgroup);
30412 
30413     memcpy(&port->mac, &iface->mac, VIR_MAC_BUFLEN);
30414 
30415     switch (virDomainNetGetActualType(iface)) {
30416     case VIR_DOMAIN_NET_TYPE_NETWORK:
30417         port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_NETWORK;
30418         port->plug.bridge.brname = g_strdup(actual->data.bridge.brname);
30419         port->plug.bridge.macTableManager = actual->data.bridge.macTableManager;
30420         break;
30421 
30422     case VIR_DOMAIN_NET_TYPE_BRIDGE:
30423         port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_BRIDGE;
30424         port->plug.bridge.brname = g_strdup(actual->data.bridge.brname);
30425         port->plug.bridge.macTableManager = actual->data.bridge.macTableManager;
30426         break;
30427 
30428     case VIR_DOMAIN_NET_TYPE_DIRECT:
30429         port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_DIRECT;
30430         port->plug.direct.linkdev = g_strdup(actual->data.direct.linkdev);
30431         port->plug.direct.mode = actual->data.direct.mode;
30432         break;
30433 
30434     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
30435         port->plugtype = VIR_NETWORK_PORT_PLUG_TYPE_HOSTDEV_PCI;
30436         if (actual->data.hostdev.def.mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
30437             actual->data.hostdev.def.source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
30438             virReportError(VIR_ERR_INTERNAL_ERROR,
30439                            _("Actual interface '%s' hostdev was not a PCI device"),
30440                            iface->ifname);
30441             return NULL;
30442         }
30443         port->plug.hostdevpci.managed = virTristateBoolFromBool(actual->data.hostdev.def.managed);
30444         port->plug.hostdevpci.addr = actual->data.hostdev.def.source.subsys.u.pci.addr;
30445         switch ((virDomainHostdevSubsysPCIBackendType)actual->data.hostdev.def.source.subsys.u.pci.backend) {
30446         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT:
30447             port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_DEFAULT;
30448             break;
30449 
30450         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM:
30451             port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_KVM;
30452             break;
30453 
30454         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO:
30455             port->plug.hostdevpci.driver = VIR_NETWORK_FORWARD_DRIVER_NAME_VFIO;
30456             break;
30457 
30458         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN:
30459             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
30460                            _("Unexpected PCI backend 'xen'"));
30461             break;
30462 
30463         case VIR_DOMAIN_HOSTDEV_PCI_BACKEND_TYPE_LAST:
30464         default:
30465             virReportEnumRangeError(virDomainHostdevSubsysPCIBackendType,
30466                                     actual->data.hostdev.def.source.subsys.u.pci.backend);
30467             return NULL;
30468         }
30469 
30470         break;
30471 
30472     case VIR_DOMAIN_NET_TYPE_CLIENT:
30473     case VIR_DOMAIN_NET_TYPE_ETHERNET:
30474     case VIR_DOMAIN_NET_TYPE_INTERNAL:
30475     case VIR_DOMAIN_NET_TYPE_MCAST:
30476     case VIR_DOMAIN_NET_TYPE_SERVER:
30477     case VIR_DOMAIN_NET_TYPE_UDP:
30478     case VIR_DOMAIN_NET_TYPE_USER:
30479     case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
30480     case VIR_DOMAIN_NET_TYPE_VDPA:
30481         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
30482                        _("Unexpected network port type %s"),
30483                        virDomainNetTypeToString(virDomainNetGetActualType(iface)));
30484         return NULL;
30485 
30486     case VIR_DOMAIN_NET_TYPE_LAST:
30487     default:
30488         virReportEnumRangeError(virNetworkPortPlugType, port->plugtype);
30489         return NULL;
30490     }
30491 
30492     if (virNetDevVPortProfileCopy(&port->virtPortProfile, actual->virtPortProfile) < 0)
30493         return NULL;
30494 
30495     if (virNetDevBandwidthCopy(&port->bandwidth, actual->bandwidth) < 0)
30496         return NULL;
30497 
30498     if (virNetDevVlanCopy(&port->vlan, &actual->vlan) < 0)
30499         return NULL;
30500 
30501     port->isolatedPort = actual->isolatedPort;
30502     port->class_id = actual->class_id;
30503     port->trustGuestRxFilters = actual->trustGuestRxFilters;
30504 
30505     return g_steal_pointer(&port);
30506 }
30507 
30508 
30509 static int
virDomainNetCreatePort(virConnectPtr conn,virDomainDef * dom,virDomainNetDef * iface,unsigned int flags)30510 virDomainNetCreatePort(virConnectPtr conn,
30511                        virDomainDef *dom,
30512                        virDomainNetDef *iface,
30513                        unsigned int flags)
30514 {
30515     virErrorPtr save_err;
30516     g_autoptr(virNetwork) net = NULL;
30517     g_autoptr(virNetworkPortDef) portdef = NULL;
30518     g_autoptr(virNetworkPort) port = NULL;
30519     g_autofree char *portxml = NULL;
30520 
30521     if (!(net = virNetworkLookupByName(conn, iface->data.network.name)))
30522         return -1;
30523 
30524     if (flags & VIR_NETWORK_PORT_CREATE_RECLAIM) {
30525         char uuidstr[VIR_UUID_STRING_BUFLEN];
30526         char macstr[VIR_MAC_STRING_BUFLEN];
30527 
30528         virUUIDFormat(iface->data.network.portid, uuidstr);
30529         virMacAddrFormat(&iface->mac, macstr);
30530 
30531         /* if the port is already registered, then we are done */
30532         if (virUUIDIsValid(iface->data.network.portid) &&
30533             (port = virNetworkPortLookupByUUID(net, iface->data.network.portid))) {
30534             VIR_DEBUG("network: %s domain: %s mac: %s port: %s - already registered, skipping",
30535                       iface->data.network.name, dom->name, macstr, uuidstr);
30536             return 0;
30537         }
30538 
30539         /* otherwise we need to create a new port */
30540         VIR_DEBUG("network: %s domain: %s mac: %s port: %s - not found, reclaiming",
30541                   iface->data.network.name, dom->name, macstr, uuidstr);
30542         if (!(portdef = virDomainNetDefActualToNetworkPort(dom, iface)))
30543             return -1;
30544     } else {
30545         if (!(portdef = virDomainNetDefToNetworkPort(dom, iface)))
30546             return -1;
30547     }
30548 
30549     if (!(portxml = virNetworkPortDefFormat(portdef)))
30550         return -1;
30551 
30552     /* prepare to re-use portdef */
30553     virNetworkPortDefFree(portdef);
30554     portdef = NULL;
30555 
30556     if (!(port = virNetworkPortCreateXML(net, portxml, flags)))
30557         return -1;
30558 
30559     /* prepare to re-use portxml */
30560     VIR_FREE(portxml);
30561 
30562     if (!(portxml = virNetworkPortGetXMLDesc(port, 0)) ||
30563         !(portdef = virNetworkPortDefParseString(portxml, 0)) ||
30564         virDomainNetDefActualFromNetworkPort(iface, portdef) < 0) {
30565         virErrorPreserveLast(&save_err);
30566         virNetworkPortDelete(port, 0);
30567         virErrorRestore(&save_err);
30568         return -1;
30569     }
30570 
30571     virNetworkPortGetUUID(port, iface->data.network.portid);
30572     return 0;
30573 }
30574 
30575 int
virDomainNetAllocateActualDevice(virConnectPtr conn,virDomainDef * dom,virDomainNetDef * iface)30576 virDomainNetAllocateActualDevice(virConnectPtr conn,
30577                                  virDomainDef *dom,
30578                                  virDomainNetDef *iface)
30579 {
30580     return virDomainNetCreatePort(conn, dom, iface, 0);
30581 }
30582 
30583 void
virDomainNetNotifyActualDevice(virConnectPtr conn,virDomainDef * dom,virDomainNetDef * iface)30584 virDomainNetNotifyActualDevice(virConnectPtr conn,
30585                                virDomainDef *dom,
30586                                virDomainNetDef *iface)
30587 {
30588     virDomainNetType actualType = virDomainNetGetActualType(iface);
30589 
30590     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK && conn
30591         && virDomainNetCreatePort(conn, dom, iface,
30592                                   VIR_NETWORK_PORT_CREATE_RECLAIM) < 0) {
30593         return;
30594     }
30595 
30596     if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
30597         actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
30598         /*
30599          * NB: we can't notify the guest of any MTU change anyway,
30600          * so there is no point in trying to learn the actualMTU
30601          * (final arg to virNetDevTapReattachBridge())
30602          */
30603         ignore_value(virNetDevTapReattachBridge(iface->ifname,
30604                                                 virDomainNetGetActualBridgeName(iface),
30605                                                 &iface->mac, dom->uuid,
30606                                                 virDomainNetGetActualVirtPortProfile(iface),
30607                                                 virDomainNetGetActualVlan(iface),
30608                                                 virDomainNetGetActualPortOptionsIsolated(iface),
30609                                                 iface->mtu, NULL));
30610     }
30611 }
30612 
30613 
30614 int
virDomainNetReleaseActualDevice(virConnectPtr conn,virDomainDef * dom G_GNUC_UNUSED,virDomainNetDef * iface)30615 virDomainNetReleaseActualDevice(virConnectPtr conn,
30616                                 virDomainDef *dom G_GNUC_UNUSED,
30617                                 virDomainNetDef *iface)
30618 {
30619     virNetworkPtr net = NULL;
30620     virNetworkPortPtr port = NULL;
30621     int ret = -1;
30622 
30623     /* Port might not exist if a failure occurred during VM startup */
30624     if (!virUUIDIsValid(iface->data.network.portid)) {
30625         ret = 0;
30626         goto cleanup;
30627     }
30628 
30629     if (!(net = virNetworkLookupByName(conn, iface->data.network.name)))
30630         goto cleanup;
30631 
30632     if (!(port = virNetworkPortLookupByUUID(net, iface->data.network.portid)))
30633         goto cleanup;
30634 
30635     if (virNetworkPortDelete(port, 0) < 0)
30636         goto cleanup;
30637 
30638  cleanup:
30639     virObjectUnref(port);
30640     virObjectUnref(net);
30641     return ret;
30642 }
30643 
30644 
30645 static int
virDomainNetBandwidthToTypedParams(virNetDevBandwidth * bandwidth,virTypedParameterPtr * params,int * nparams)30646 virDomainNetBandwidthToTypedParams(virNetDevBandwidth *bandwidth,
30647                                    virTypedParameterPtr *params,
30648                                    int *nparams)
30649 {
30650     int maxparams = 0;
30651 
30652     if ((bandwidth->in != NULL) &&
30653         (virTypedParamsAddUInt(params, nparams, &maxparams,
30654                                VIR_NETWORK_PORT_BANDWIDTH_IN_AVERAGE,
30655                                bandwidth->in->average) < 0 ||
30656          virTypedParamsAddUInt(params, nparams, &maxparams,
30657                                VIR_NETWORK_PORT_BANDWIDTH_IN_PEAK,
30658                                bandwidth->in->peak) < 0 ||
30659          virTypedParamsAddUInt(params, nparams, &maxparams,
30660                                VIR_NETWORK_PORT_BANDWIDTH_IN_FLOOR,
30661                                bandwidth->in->floor) < 0 ||
30662          virTypedParamsAddUInt(params, nparams, &maxparams,
30663                                VIR_NETWORK_PORT_BANDWIDTH_IN_BURST,
30664                                bandwidth->in->burst) < 0))
30665         goto error;
30666 
30667     if ((bandwidth->out != NULL) &&
30668         (virTypedParamsAddUInt(params, nparams, &maxparams,
30669                                VIR_NETWORK_PORT_BANDWIDTH_OUT_AVERAGE,
30670                                bandwidth->out->average) < 0 ||
30671          virTypedParamsAddUInt(params, nparams, &maxparams,
30672                                VIR_NETWORK_PORT_BANDWIDTH_OUT_PEAK,
30673                                bandwidth->out->peak) < 0 ||
30674          virTypedParamsAddUInt(params, nparams, &maxparams,
30675                                VIR_NETWORK_PORT_BANDWIDTH_OUT_BURST,
30676                                bandwidth->out->burst) < 0))
30677         goto error;
30678 
30679     return 0;
30680 
30681  error:
30682     virTypedParamsFree(*params, *nparams);
30683     *params = NULL;
30684     *nparams = 0;
30685     return -1;
30686 }
30687 
30688 
30689 int
virDomainNetBandwidthUpdate(virDomainNetDef * iface,virNetDevBandwidth * newBandwidth)30690 virDomainNetBandwidthUpdate(virDomainNetDef *iface,
30691                             virNetDevBandwidth *newBandwidth)
30692 {
30693     virNetworkPtr net = NULL;
30694     virNetworkPortPtr port = NULL;
30695     virTypedParameterPtr params = NULL;
30696     int nparams = 0;
30697     g_autoptr(virConnect) conn = NULL;
30698     int ret = -1;
30699 
30700     if (!(conn = virGetConnectNetwork()))
30701         goto cleanup;
30702 
30703     if (!(net = virNetworkLookupByName(conn, iface->data.network.name)))
30704         goto cleanup;
30705 
30706     if (!(port = virNetworkPortLookupByUUID(net, iface->data.network.portid)))
30707         goto cleanup;
30708 
30709     if (virDomainNetBandwidthToTypedParams(newBandwidth, &params, &nparams) < 0)
30710         goto cleanup;
30711 
30712     if (virNetworkPortSetParameters(port, params, nparams, 0) < 0)
30713         goto cleanup;
30714 
30715     ret = 0;
30716  cleanup:
30717     virTypedParamsFree(params, nparams);
30718     virObjectUnref(port);
30719     virObjectUnref(net);
30720     return ret;
30721 }
30722 
30723 /* virDomainNetResolveActualType:
30724  * @iface: the original NetDef from the domain
30725  *
30726  * Looks up the network reference by iface, and returns the actual
30727  * type of the connection without allocating any resources.
30728  *
30729  * Returns 0 on success, -1 on failure.
30730  */
30731 int
virDomainNetResolveActualType(virDomainNetDef * iface)30732 virDomainNetResolveActualType(virDomainNetDef *iface)
30733 {
30734     virNetworkDef *def = NULL;
30735     int ret = -1;
30736     g_autofree char *xml = NULL;
30737     g_autoptr(virConnect) conn = NULL;
30738     g_autoptr(virNetwork) net = NULL;
30739 
30740     if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
30741         return iface->type;
30742 
30743     if (iface->data.network.actual)
30744         return iface->data.network.actual->type;
30745 
30746     if (!(conn = virGetConnectNetwork()))
30747         return -1;
30748 
30749     if (!(net = virNetworkLookupByName(conn, iface->data.network.name)))
30750         goto cleanup;
30751 
30752     if (!(xml = virNetworkGetXMLDesc(net, 0)))
30753         goto cleanup;
30754 
30755     if (!(def = virNetworkDefParseString(xml, NULL, false)))
30756         goto cleanup;
30757 
30758     switch ((virNetworkForwardType) def->forward.type) {
30759     case VIR_NETWORK_FORWARD_NONE:
30760     case VIR_NETWORK_FORWARD_NAT:
30761     case VIR_NETWORK_FORWARD_ROUTE:
30762     case VIR_NETWORK_FORWARD_OPEN:
30763         /* for these forward types, the actual net type really *is*
30764          * NETWORK; we just keep the info from the portgroup in
30765          * iface->data.network.actual
30766          */
30767         ret = VIR_DOMAIN_NET_TYPE_NETWORK;
30768         break;
30769 
30770     case VIR_NETWORK_FORWARD_HOSTDEV:
30771         ret = VIR_DOMAIN_NET_TYPE_HOSTDEV;
30772         break;
30773 
30774     case VIR_NETWORK_FORWARD_BRIDGE:
30775         if (def->bridge) {
30776             /* <forward type='bridge'/> <bridge name='xxx'/>
30777              * is VIR_DOMAIN_NET_TYPE_BRIDGE
30778              */
30779             ret = VIR_DOMAIN_NET_TYPE_BRIDGE;
30780             break;
30781         }
30782 
30783         /* intentionally fall through to the direct case for
30784          * VIR_NETWORK_FORWARD_BRIDGE with no bridge device defined
30785          */
30786         G_GNUC_FALLTHROUGH;
30787 
30788     case VIR_NETWORK_FORWARD_PRIVATE:
30789     case VIR_NETWORK_FORWARD_VEPA:
30790     case VIR_NETWORK_FORWARD_PASSTHROUGH:
30791         /* <forward type='bridge|private|vepa|passthrough'> are all
30792          * VIR_DOMAIN_NET_TYPE_DIRECT.
30793          */
30794         ret = VIR_DOMAIN_NET_TYPE_DIRECT;
30795         break;
30796 
30797     case VIR_NETWORK_FORWARD_LAST:
30798     default:
30799         virReportEnumRangeError(virNetworkForwardType, def->forward.type);
30800         goto cleanup;
30801     }
30802 
30803  cleanup:
30804     virNetworkDefFree(def);
30805     return ret;
30806 }
30807 
30808 
30809 static int
virDomainDiskAddISCSIPoolSourceHost(virStorageSource * src,virStoragePoolDef * pooldef)30810 virDomainDiskAddISCSIPoolSourceHost(virStorageSource *src,
30811                                     virStoragePoolDef *pooldef)
30812 {
30813     g_auto(GStrv) tokens = NULL;
30814 
30815     /* Only support one host */
30816     if (pooldef->source.nhost != 1) {
30817         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
30818                        _("Expected exactly 1 host for the storage pool"));
30819         return -1;
30820     }
30821 
30822     /* iscsi pool only supports one host */
30823     src->nhosts = 1;
30824     src->hosts = g_new0(virStorageNetHostDef, 1);
30825 
30826     src->hosts[0].name = g_strdup(pooldef->source.hosts[0].name);
30827 
30828     if (pooldef->source.hosts[0].port != 0)
30829         src->hosts[0].port = pooldef->source.hosts[0].port;
30830     else
30831         src->hosts[0].port = 3260;
30832 
30833     /* iscsi volume has name like "unit:0:0:1" */
30834     if (!(tokens = g_strsplit(src->srcpool->volume, ":", 0)))
30835         return -1;
30836 
30837     if (g_strv_length(tokens) != 4) {
30838         virReportError(VIR_ERR_INTERNAL_ERROR,
30839                        _("unexpected iscsi volume name '%s'"),
30840                        src->srcpool->volume);
30841         return -1;
30842     }
30843 
30844     /* iscsi pool has only one source device path */
30845     src->path = g_strdup_printf("%s/%s", pooldef->source.devices[0].path,
30846                                 tokens[3]);
30847 
30848     /* Storage pool have not supported these 2 attributes yet,
30849      * use the defaults.
30850      */
30851     src->hosts[0].transport = VIR_STORAGE_NET_HOST_TRANS_TCP;
30852     src->hosts[0].socket = NULL;
30853 
30854     src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;
30855 
30856     return 0;
30857 }
30858 
30859 
30860 static int
virDomainDiskTranslateSourcePoolAuth(virStorageSource * src,virStoragePoolSource * source)30861 virDomainDiskTranslateSourcePoolAuth(virStorageSource *src,
30862                                      virStoragePoolSource *source)
30863 {
30864     /* Only necessary when authentication set */
30865     if (!source->auth)
30866         return 0;
30867 
30868     src->auth = virStorageAuthDefCopy(source->auth);
30869     if (!src->auth)
30870         return -1;
30871     /* A <disk> doesn't use <auth type='%s', so clear that out for the disk */
30872     src->auth->authType = VIR_STORAGE_AUTH_TYPE_NONE;
30873     return 0;
30874 }
30875 
30876 
30877 static int
virDomainDiskTranslateISCSIDirect(virStorageSource * src,virStoragePoolDef * pooldef)30878 virDomainDiskTranslateISCSIDirect(virStorageSource *src,
30879                                   virStoragePoolDef *pooldef)
30880 {
30881     src->srcpool->actualtype = VIR_STORAGE_TYPE_NETWORK;
30882     src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI;
30883 
30884     if (virDomainDiskTranslateSourcePoolAuth(src,
30885                                              &pooldef->source) < 0)
30886         return -1;
30887 
30888     /* Source pool may not fill in the secrettype field,
30889      * so we need to do so here
30890      */
30891     if (src->auth && !src->auth->secrettype) {
30892         const char *secrettype =
30893             virSecretUsageTypeToString(VIR_SECRET_USAGE_TYPE_ISCSI);
30894         src->auth->secrettype = g_strdup(secrettype);
30895     }
30896 
30897     if (virDomainDiskAddISCSIPoolSourceHost(src, pooldef) < 0)
30898         return -1;
30899 
30900     if (!src->initiator.iqn && pooldef->source.initiator.iqn &&
30901         virStorageSourceInitiatorCopy(&src->initiator,
30902                                       &pooldef->source.initiator) < 0) {
30903         return -1;
30904     }
30905 
30906     return 0;
30907 }
30908 
30909 
30910 static int
virDomainStorageSourceTranslateSourcePool(virStorageSource * src,virConnectPtr conn)30911 virDomainStorageSourceTranslateSourcePool(virStorageSource *src,
30912                                           virConnectPtr conn)
30913 {
30914     virStorageVolInfo info;
30915     g_autoptr(virStoragePoolDef) pooldef = NULL;
30916     g_autofree char *poolxml = NULL;
30917     g_autoptr(virStoragePool) pool = NULL;
30918     g_autoptr(virStorageVol) vol = NULL;
30919 
30920     if (!(pool = virStoragePoolLookupByName(conn, src->srcpool->pool)))
30921         return -1;
30922 
30923     if (virStoragePoolIsActive(pool) != 1) {
30924         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
30925                        _("storage pool '%s' containing volume '%s' "
30926                          "is not active"),
30927                        src->srcpool->pool, src->srcpool->volume);
30928         return -1;
30929     }
30930 
30931     if (!(vol = virStorageVolLookupByName(pool, src->srcpool->volume)))
30932         return -1;
30933 
30934     if (virStorageVolGetInfo(vol, &info) < 0)
30935         return -1;
30936 
30937     if (!(poolxml = virStoragePoolGetXMLDesc(pool, 0)))
30938         return -1;
30939 
30940     if (!(pooldef = virStoragePoolDefParseString(poolxml, 0)))
30941         return -1;
30942 
30943     src->srcpool->pooltype = pooldef->type;
30944     src->srcpool->voltype = info.type;
30945 
30946     if (src->srcpool->mode && pooldef->type != VIR_STORAGE_POOL_ISCSI) {
30947         virReportError(VIR_ERR_XML_ERROR, "%s",
30948                        _("disk source mode is only valid when "
30949                          "storage pool is of iscsi type"));
30950         return -1;
30951     }
30952 
30953     VIR_FREE(src->path);
30954     virStorageNetHostDefFree(src->nhosts, src->hosts);
30955     src->nhosts = 0;
30956     src->hosts = NULL;
30957     virStorageAuthDefFree(src->auth);
30958     src->auth = NULL;
30959 
30960     switch ((virStoragePoolType) pooldef->type) {
30961     case VIR_STORAGE_POOL_DIR:
30962     case VIR_STORAGE_POOL_FS:
30963     case VIR_STORAGE_POOL_NETFS:
30964     case VIR_STORAGE_POOL_LOGICAL:
30965     case VIR_STORAGE_POOL_DISK:
30966     case VIR_STORAGE_POOL_SCSI:
30967     case VIR_STORAGE_POOL_ZFS:
30968     case VIR_STORAGE_POOL_VSTORAGE:
30969         if (!(src->path = virStorageVolGetPath(vol)))
30970             return -1;
30971 
30972         switch (info.type) {
30973         case VIR_STORAGE_VOL_FILE:
30974             src->srcpool->actualtype = VIR_STORAGE_TYPE_FILE;
30975             break;
30976 
30977         case VIR_STORAGE_VOL_DIR:
30978             src->srcpool->actualtype = VIR_STORAGE_TYPE_DIR;
30979             break;
30980 
30981         case VIR_STORAGE_VOL_BLOCK:
30982             src->srcpool->actualtype = VIR_STORAGE_TYPE_BLOCK;
30983             break;
30984 
30985         case VIR_STORAGE_VOL_PLOOP:
30986             src->srcpool->actualtype = VIR_STORAGE_TYPE_FILE;
30987             break;
30988 
30989         case VIR_STORAGE_VOL_NETWORK:
30990         case VIR_STORAGE_VOL_NETDIR:
30991             virReportError(VIR_ERR_INTERNAL_ERROR,
30992                            _("unexpected storage volume type '%s' "
30993                              "for storage pool type '%s'"),
30994                            virStorageVolTypeToString(info.type),
30995                            virStoragePoolTypeToString(pooldef->type));
30996             return -1;
30997         }
30998 
30999         break;
31000 
31001     case VIR_STORAGE_POOL_ISCSI_DIRECT:
31002         if (virDomainDiskTranslateISCSIDirect(src, pooldef) < 0)
31003             return -1;
31004 
31005         break;
31006 
31007     case VIR_STORAGE_POOL_ISCSI:
31008        switch (src->srcpool->mode) {
31009        case VIR_STORAGE_SOURCE_POOL_MODE_DEFAULT:
31010        case VIR_STORAGE_SOURCE_POOL_MODE_LAST:
31011            src->srcpool->mode = VIR_STORAGE_SOURCE_POOL_MODE_HOST;
31012            G_GNUC_FALLTHROUGH;
31013        case VIR_STORAGE_SOURCE_POOL_MODE_HOST:
31014            src->srcpool->actualtype = VIR_STORAGE_TYPE_BLOCK;
31015            if (!(src->path = virStorageVolGetPath(vol)))
31016                return -1;
31017            break;
31018 
31019        case VIR_STORAGE_SOURCE_POOL_MODE_DIRECT:
31020            if (virDomainDiskTranslateISCSIDirect(src, pooldef) < 0)
31021                return -1;
31022            break;
31023        }
31024        break;
31025 
31026     case VIR_STORAGE_POOL_MPATH:
31027     case VIR_STORAGE_POOL_RBD:
31028     case VIR_STORAGE_POOL_SHEEPDOG:
31029     case VIR_STORAGE_POOL_GLUSTER:
31030     case VIR_STORAGE_POOL_LAST:
31031         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
31032                        _("using '%s' pools for backing 'volume' disks "
31033                          "isn't yet supported"),
31034                        virStoragePoolTypeToString(pooldef->type));
31035         return -1;
31036     }
31037 
31038     return 0;
31039 }
31040 
31041 
31042 int
virDomainDiskTranslateSourcePool(virDomainDiskDef * def)31043 virDomainDiskTranslateSourcePool(virDomainDiskDef *def)
31044 {
31045     g_autoptr(virConnect) conn = NULL;
31046     virStorageSource *n;
31047 
31048     for (n = def->src; virStorageSourceIsBacking(n); n = n->backingStore) {
31049         if (n->type != VIR_STORAGE_TYPE_VOLUME || !n->srcpool)
31050             continue;
31051 
31052         if (!conn) {
31053             if (!(conn = virGetConnectStorage()))
31054                 return -1;
31055         }
31056 
31057         if (virDomainStorageSourceTranslateSourcePool(n, conn) < 0)
31058             return -1;
31059     }
31060 
31061     if (def->startupPolicy != 0 &&
31062         virStorageSourceGetActualType(def->src) != VIR_STORAGE_TYPE_FILE) {
31063         virReportError(VIR_ERR_XML_ERROR, "%s",
31064                        _("'startupPolicy' is only valid for 'file' type volume"));
31065         return -1;
31066     }
31067 
31068     return 0;
31069 }
31070 
31071 
31072 /**
31073  * virDomainDiskGetDetectZeroesMode:
31074  * @discard: disk/image sector discard setting
31075  * @detect_zeroes: disk/image zero sector detection mode
31076  *
31077  * As a convenience syntax, if discards are ignored and zero detection is set
31078  * to 'unmap', then simply behave like zero detection is set to 'on'.  But
31079  * don't change it in the XML for easier adjustments.  This behaviour is
31080  * documented.
31081  */
31082 int
virDomainDiskGetDetectZeroesMode(virDomainDiskDiscard discard,virDomainDiskDetectZeroes detect_zeroes)31083 virDomainDiskGetDetectZeroesMode(virDomainDiskDiscard discard,
31084                                  virDomainDiskDetectZeroes detect_zeroes)
31085 {
31086     if (discard != VIR_DOMAIN_DISK_DISCARD_UNMAP &&
31087         detect_zeroes == VIR_DOMAIN_DISK_DETECT_ZEROES_UNMAP)
31088         return VIR_DOMAIN_DISK_DETECT_ZEROES_ON;
31089 
31090     return detect_zeroes;
31091 }
31092 
31093 
31094 /**
31095  * virDomainDefHasManagedPR:
31096  * @def: domain definition
31097  *
31098  * Returns true if any of the domain disks requires the use of the managed
31099  * persistent reservations infrastructure.
31100  */
31101 bool
virDomainDefHasManagedPR(const virDomainDef * def)31102 virDomainDefHasManagedPR(const virDomainDef *def)
31103 {
31104     size_t i;
31105 
31106     for (i = 0; i < def->ndisks; i++) {
31107         if (virStorageSourceChainHasManagedPR(def->disks[i]->src))
31108             return true;
31109     }
31110 
31111     return false;
31112 }
31113 
31114 
31115 bool
virDomainDefHasNVMeDisk(const virDomainDef * def)31116 virDomainDefHasNVMeDisk(const virDomainDef *def)
31117 {
31118     size_t i;
31119 
31120     for (i = 0; i < def->ndisks; i++) {
31121         if (virStorageSourceChainHasNVMe(def->disks[i]->src))
31122             return true;
31123     }
31124 
31125     return false;
31126 }
31127 
31128 
31129 bool
virDomainDefHasVFIOHostdev(const virDomainDef * def)31130 virDomainDefHasVFIOHostdev(const virDomainDef *def)
31131 {
31132     size_t i;
31133 
31134     for (i = 0; i < def->nhostdevs; i++) {
31135         if (virHostdevIsVFIODevice(def->hostdevs[i]))
31136             return true;
31137     }
31138 
31139     return false;
31140 }
31141 
31142 
31143 bool
virDomainDefHasMdevHostdev(const virDomainDef * def)31144 virDomainDefHasMdevHostdev(const virDomainDef *def)
31145 {
31146     size_t i;
31147 
31148     for (i = 0; i < def->nhostdevs; i++) {
31149         if (virHostdevIsMdevDevice(def->hostdevs[i]))
31150             return true;
31151     }
31152 
31153     return false;
31154 }
31155 
31156 
31157 bool
virDomainDefHasVDPANet(const virDomainDef * def)31158 virDomainDefHasVDPANet(const virDomainDef *def)
31159 {
31160     size_t i;
31161 
31162     for (i = 0; i < def->nnets; i++) {
31163         if (virDomainNetGetActualType(def->nets[i]) == VIR_DOMAIN_NET_TYPE_VDPA)
31164             return true;
31165     }
31166 
31167     return false;
31168 }
31169 
31170 
31171 bool
virDomainDefHasOldStyleUEFI(const virDomainDef * def)31172 virDomainDefHasOldStyleUEFI(const virDomainDef *def)
31173 {
31174     return def->os.loader &&
31175            def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH;
31176 }
31177 
31178 
31179 bool
virDomainDefHasOldStyleROUEFI(const virDomainDef * def)31180 virDomainDefHasOldStyleROUEFI(const virDomainDef *def)
31181 {
31182     return virDomainDefHasOldStyleUEFI(def) &&
31183            def->os.loader->readonly == VIR_TRISTATE_BOOL_YES;
31184 }
31185 
31186 
31187 /**
31188  * virDomainGraphicsDefHasOpenGL:
31189  * @def: domain definition
31190  *
31191  * Returns true if a domain config contains at least one <graphics> element
31192  * with OpenGL support enabled, false otherwise.
31193  */
31194 bool
virDomainGraphicsDefHasOpenGL(const virDomainDef * def)31195 virDomainGraphicsDefHasOpenGL(const virDomainDef *def)
31196 {
31197     size_t i;
31198 
31199     for (i = 0; i < def->ngraphics; i++) {
31200         virDomainGraphicsDef *graphics = def->graphics[i];
31201 
31202         /* we only care about OpenGL support for a given type here */
31203         switch (graphics->type) {
31204         case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
31205         case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
31206         case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
31207             continue;
31208         case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
31209             if (graphics->data.sdl.gl == VIR_TRISTATE_BOOL_YES)
31210                 return true;
31211 
31212             continue;
31213         case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
31214             if (graphics->data.spice.gl == VIR_TRISTATE_BOOL_YES)
31215                 return true;
31216 
31217             continue;
31218         case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
31219             return true;
31220 
31221         case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
31222             break;
31223         }
31224     }
31225 
31226     return false;
31227 }
31228 
31229 
31230 bool
virDomainGraphicsSupportsRenderNode(const virDomainGraphicsDef * graphics)31231 virDomainGraphicsSupportsRenderNode(const virDomainGraphicsDef *graphics)
31232 {
31233     bool ret = false;
31234 
31235     if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE ||
31236         graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS)
31237         ret = true;
31238 
31239     return ret;
31240 }
31241 
31242 
31243 const char *
virDomainGraphicsGetRenderNode(const virDomainGraphicsDef * graphics)31244 virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics)
31245 {
31246     const char *ret = NULL;
31247 
31248     switch (graphics->type) {
31249     case VIR_DOMAIN_GRAPHICS_TYPE_SPICE:
31250         ret = graphics->data.spice.rendernode;
31251         break;
31252     case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS:
31253         ret = graphics->data.egl_headless.rendernode;
31254         break;
31255     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
31256     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
31257     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
31258     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
31259     case VIR_DOMAIN_GRAPHICS_TYPE_LAST:
31260         break;
31261     }
31262 
31263     return ret;
31264 }
31265 
31266 
31267 bool
virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef * graphics)31268 virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics)
31269 {
31270     if (!virDomainGraphicsSupportsRenderNode(graphics))
31271         return false;
31272 
31273     if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE &&
31274         graphics->data.spice.gl != VIR_TRISTATE_BOOL_YES)
31275         return false;
31276 
31277     if (virDomainGraphicsGetRenderNode(graphics))
31278         return false;
31279 
31280     return true;
31281 }
31282 
31283 
31284 bool
virDomainBlockIoTuneInfoHasBasic(const virDomainBlockIoTuneInfo * iotune)31285 virDomainBlockIoTuneInfoHasBasic(const virDomainBlockIoTuneInfo *iotune)
31286 {
31287     return iotune->total_bytes_sec ||
31288            iotune->read_bytes_sec ||
31289            iotune->write_bytes_sec ||
31290            iotune->total_iops_sec ||
31291            iotune->read_iops_sec ||
31292            iotune->write_iops_sec;
31293 }
31294 
31295 
31296 bool
virDomainBlockIoTuneInfoHasMax(const virDomainBlockIoTuneInfo * iotune)31297 virDomainBlockIoTuneInfoHasMax(const virDomainBlockIoTuneInfo *iotune)
31298 {
31299     return iotune->total_bytes_sec_max ||
31300            iotune->read_bytes_sec_max ||
31301            iotune->write_bytes_sec_max ||
31302            iotune->total_iops_sec_max ||
31303            iotune->read_iops_sec_max ||
31304            iotune->write_iops_sec_max ||
31305            iotune->size_iops_sec;
31306 }
31307 
31308 
31309 bool
virDomainBlockIoTuneInfoHasMaxLength(const virDomainBlockIoTuneInfo * iotune)31310 virDomainBlockIoTuneInfoHasMaxLength(const virDomainBlockIoTuneInfo *iotune)
31311 {
31312     return iotune->total_bytes_sec_max_length ||
31313            iotune->read_bytes_sec_max_length ||
31314            iotune->write_bytes_sec_max_length ||
31315            iotune->total_iops_sec_max_length ||
31316            iotune->read_iops_sec_max_length ||
31317            iotune->write_iops_sec_max_length;
31318 }
31319 
31320 
31321 bool
virDomainBlockIoTuneInfoHasAny(const virDomainBlockIoTuneInfo * iotune)31322 virDomainBlockIoTuneInfoHasAny(const virDomainBlockIoTuneInfo *iotune)
31323 {
31324     return virDomainBlockIoTuneInfoHasBasic(iotune) ||
31325            virDomainBlockIoTuneInfoHasMax(iotune) ||
31326            virDomainBlockIoTuneInfoHasMaxLength(iotune);
31327 }
31328 
31329 
31330 void
virDomainBlockIoTuneInfoCopy(const virDomainBlockIoTuneInfo * src,virDomainBlockIoTuneInfo * dst)31331 virDomainBlockIoTuneInfoCopy(const virDomainBlockIoTuneInfo *src,
31332                              virDomainBlockIoTuneInfo *dst)
31333 {
31334     *dst = *src;
31335     dst->group_name = g_strdup(src->group_name);
31336 }
31337 
31338 
31339 bool
virDomainBlockIoTuneInfoEqual(const virDomainBlockIoTuneInfo * a,const virDomainBlockIoTuneInfo * b)31340 virDomainBlockIoTuneInfoEqual(const virDomainBlockIoTuneInfo *a,
31341                               const virDomainBlockIoTuneInfo *b)
31342 {
31343     return a->total_bytes_sec == b->total_bytes_sec &&
31344         a->read_bytes_sec == b->read_bytes_sec &&
31345         a->write_bytes_sec == b->write_bytes_sec &&
31346         a->total_iops_sec == b->total_iops_sec &&
31347         a->read_iops_sec == b->read_iops_sec &&
31348         a->write_iops_sec == b->write_iops_sec &&
31349         a->total_bytes_sec_max == b->total_bytes_sec_max &&
31350         a->read_bytes_sec_max == b->read_bytes_sec_max &&
31351         a->write_bytes_sec_max == b->write_bytes_sec_max &&
31352         a->total_iops_sec_max == b->total_iops_sec_max &&
31353         a->read_iops_sec_max == b->read_iops_sec_max &&
31354         a->write_iops_sec_max == b->write_iops_sec_max &&
31355         a->size_iops_sec == b->size_iops_sec &&
31356         a->total_bytes_sec_max_length == b->total_bytes_sec_max_length &&
31357         a->read_bytes_sec_max_length == b->read_bytes_sec_max_length &&
31358         a->write_bytes_sec_max_length == b->write_bytes_sec_max_length &&
31359         a->total_iops_sec_max_length == b->total_iops_sec_max_length &&
31360         a->read_iops_sec_max_length == b->read_iops_sec_max_length &&
31361         a->write_iops_sec_max_length == b->write_iops_sec_max_length;
31362 }
31363 
31364 
31365 /**
31366  * virHostdevIsSCSIDevice:
31367  * @hostdev: host device to check
31368  *
31369  * Returns true if @hostdev is a SCSI device, false otherwise.
31370  */
31371 bool
virHostdevIsSCSIDevice(const virDomainHostdevDef * hostdev)31372 virHostdevIsSCSIDevice(const virDomainHostdevDef *hostdev)
31373 {
31374     return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
31375         hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI;
31376 }
31377 
31378 
31379 /**
31380  * virHostdevIsMdevDevice:
31381  * @hostdev: host device to check
31382  *
31383  * Returns true if @hostdev is a Mediated device, false otherwise.
31384  */
31385 bool
virHostdevIsMdevDevice(const virDomainHostdevDef * hostdev)31386 virHostdevIsMdevDevice(const virDomainHostdevDef *hostdev)
31387 {
31388     return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
31389         hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV;
31390 }
31391 
31392 
31393 /**
31394  * virHostdevIsVFIODevice:
31395  * @hostdev: host device to check
31396  *
31397  * Returns true if @hostdev is a PCI device with VFIO backend, false otherwise.
31398  */
31399 bool
virHostdevIsVFIODevice(const virDomainHostdevDef * hostdev)31400 virHostdevIsVFIODevice(const virDomainHostdevDef *hostdev)
31401 {
31402     return hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
31403         hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
31404         hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
31405 }
31406 
31407 
31408 /**
31409  * virDomainObjGetMessages:
31410  * @vm: domain object
31411  * @msgs: pointer to a variable to store messages
31412  * @flags: zero or more virDomainMessageType flags
31413  *
31414  * Returns number of messages stored in @msgs, -1 otherwise.
31415  */
31416 int
virDomainObjGetMessages(virDomainObj * vm,char *** msgs,unsigned int flags)31417 virDomainObjGetMessages(virDomainObj *vm,
31418                         char ***msgs,
31419                         unsigned int flags)
31420 {
31421     size_t i = 0;
31422     size_t n = 0;
31423     int nmsgs = 0;
31424     int rv = -1;
31425 
31426     *msgs = NULL;
31427 
31428     if (!flags || (flags & VIR_DOMAIN_MESSAGE_TAINTING)) {
31429         nmsgs += __builtin_popcount(vm->taint);
31430         *msgs = g_renew(char *, *msgs, nmsgs+1);
31431 
31432         for (i = 0; i < VIR_DOMAIN_TAINT_LAST; i++) {
31433             if (vm->taint & (1 << i)) {
31434                 (*msgs)[n++] = g_strdup_printf(
31435                     _("tainted: %s"),
31436                     _(virDomainTaintMessageTypeToString(i)));
31437             }
31438         }
31439     }
31440 
31441     if (!flags || (flags & VIR_DOMAIN_MESSAGE_DEPRECATION)) {
31442         nmsgs += vm->ndeprecations;
31443         *msgs = g_renew(char *, *msgs, nmsgs+1);
31444 
31445         for (i = 0; i < vm->ndeprecations; i++) {
31446             (*msgs)[n++] = g_strdup_printf(
31447                 _("deprecated configuration: %s"),
31448                 vm->deprecations[i]);
31449         }
31450     }
31451 
31452     (*msgs)[nmsgs] = NULL;
31453 
31454     rv = nmsgs;
31455 
31456     return rv;
31457 }
31458