* src/qemu/qemu_command.c (qemuBuildCommandLine): Emit smartcard options. (qemuAssignDeviceAliases): Assign an alias for smartcards. (qemuBuildControllerDevStr): Manage the usb-ccid controller. * tests/qemuxml2argvtest.c (mymain): Add new tests. * tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args: New file. * tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args: Likewise. * tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough.args: Likewise. * tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args: Likewise. --- Notes: v2: new patch v3: reject ',' in cert name, alias for host smartcard use, output usb-ccid controller separate from rest of command line, enforce at most one smartcard for now v4: update to new XML, add comment, rebase on recent changes to testsuite src/qemu/qemu_command.c | 95 +++++++++++++++++++- .../qemuxml2argv-smartcard-controller.args | 7 ++ .../qemuxml2argv-smartcard-host-certificates.args | 8 ++ .../qemuxml2argv-smartcard-host.args | 7 ++ .../qemuxml2argv-smartcard-passthrough-tcp.args | 7 ++ tests/qemuxml2argvtest.c | 13 +++ 6 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index a283314..4a36ef6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -638,6 +638,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long qemuCmdFlags) if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0) goto no_memory; } + for (i = 0; i < def->nsmartcards ; i++) { + if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0) + goto no_memory; + } if (def->console) { if (virAsprintf(&def->console->info.alias, "console%d", i) < 0) goto no_memory; @@ -1031,8 +1035,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs) /* Disk controllers (SCSI only for now) */ for (i = 0; i < def->ncontrollers ; i++) { - /* FDC lives behind the ISA bridge */ - if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC) + /* FDC lives behind the ISA bridge; CCID is a usb device */ + if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC || + def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID) continue; /* First IDE controller lives on the PIIX3 at slot=1, function=1, @@ -1534,6 +1539,10 @@ qemuBuildControllerDevStr(virDomainControllerDefPtr def) } break; + case VIR_DOMAIN_CONTROLLER_TYPE_CCID: + virBufferVSprintf(&buf, "usb-ccid,id=ccid%d", def->idx); + break; + /* We always get an IDE controller, whether we want it or not. */ case VIR_DOMAIN_CONTROLLER_TYPE_IDE: default: @@ -3444,6 +3453,88 @@ qemuBuildCommandLine(virConnectPtr conn, } } + if (def->nsmartcards) { + /* -device usb-ccid was already emitted along with other + * controllers. For now, qemu handles only one smartcard. */ + virDomainSmartcardDefPtr smartcard = def->smartcards[0]; + char *devstr; + virBuffer opt = VIR_BUFFER_INITIALIZER; + int j; + const char *database; + + if (!(qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) || + !(qemuCmdFlags & QEMUD_CMD_FLAG_USB_CCID)) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this QEMU binary lacks smartcard support")); + goto error; + } + if (def->nsmartcards > 1 || + smartcard->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID || + smartcard->info.addr.ccid.controller != 0 || + smartcard->info.addr.ccid.slot != 0) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("this QEMU binary lacks multiple smartcard " + "support")); + virBufferFreeAndReset(&opt); + goto error; + } + + switch (smartcard->type) { + case VIR_DOMAIN_SMARTCARD_TYPE_HOST: + virBufferAddLit(&opt, "ccid-card-emulated,backend=nss-emulated"); + break; + case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES: + virBufferAddLit(&opt, "ccid-card-emulated,backend=certificates"); + for (j = 0; j < VIR_DOMAIN_SMARTCARD_NUM_CERTIFICATES; j++) { + if (strchr(smartcard->data.cert.file[j], ',')) { + virBufferFreeAndReset(&opt); + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid certificate name: %s"), + smartcard->data.cert.file[j]); + goto error; + } + virBufferVSprintf(&opt, ",cert%d=%s", j + 1, + smartcard->data.cert.file[j]); + } + if (smartcard->data.cert.database) { + if (strchr(smartcard->data.cert.database, ',')) { + virBufferFreeAndReset(&opt); + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid database name: %s"), + smartcard->data.cert.database); + goto error; + } + database = smartcard->data.cert.database; + } else { + database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE; + } + virBufferVSprintf(&opt, ",database=%s", database); + break; + case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH: + virCommandAddArg(cmd, "-chardev"); + if (!(devstr = qemuBuildChrChardevStr(&smartcard->data.passthru, + smartcard->info.alias))) { + virBufferFreeAndReset(&opt); + goto error; + } + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + + virBufferVSprintf(&opt, "ccid-card-passthru,chardev=char%s", + smartcard->info.alias); + break; + default: + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected smartcard type %d"), + smartcard->type); + virBufferFreeAndReset(&opt); + goto error; + } + virCommandAddArg(cmd, "-device"); + virBufferVSprintf(&opt, ",id=%s,bus=ccid0.0", smartcard->info.alias); + virCommandAddArgBuffer(cmd, &opt); + } + if (!def->nserials) { /* If we have -device, then we set -nodefault already */ if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args new file mode 100644 index 0000000..359696e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-controller.args @@ -0,0 +1,7 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 215 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ +usb-ccid,id=ccid0 -device \ +ccid-card-emulated,backend=nss-emulated,id=smartcard0,bus=ccid0.0 -usb \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args new file mode 100644 index 0000000..f18ce19 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host-certificates.args @@ -0,0 +1,8 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 215 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ +usb-ccid,id=ccid0 -device \ +ccid-card-emulated,backend=certificates,cert1=cert1,cert2=cert2,cert3=cert3\ +,database=/etc/pki/nssdb,id=smartcard0,bus=ccid0.0 -usb -device \ +virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args new file mode 100644 index 0000000..359696e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-host.args @@ -0,0 +1,7 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 215 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ +usb-ccid,id=ccid0 -device \ +ccid-card-emulated,backend=nss-emulated,id=smartcard0,bus=ccid0.0 -usb \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args new file mode 100644 index 0000000..a2da4f5 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-smartcard-passthrough-tcp.args @@ -0,0 +1,7 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 215 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ +usb-ccid,id=ccid0 -chardev socket,id=charsmartcard0,host=127.0.0.1,port=2001 \ +-device ccid-card-passthru,chardev=charsmartcard0,id=smartcard0,bus=ccid0.0 \ +-usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 0a39791..483916c 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -408,6 +408,19 @@ mymain(int argc, char **argv) DO_TEST("console-virtio", QEMUD_CMD_FLAG_DEVICE | QEMUD_CMD_FLAG_NODEFCONFIG, false); + DO_TEST("smartcard-host", + QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE | + QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false); + DO_TEST("smartcard-host-certificates", + QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE | + QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false); + DO_TEST("smartcard-passthrough-tcp", + QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE | + QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false); + DO_TEST("smartcard-controller", + QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE | + QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_USB_CCID, false); + DO_TEST("smbios", QEMUD_CMD_FLAG_SMBIOS_TYPE, false); DO_TEST("watchdog", 0, false); -- 1.7.3.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list