[libvirt] [PATCHv3 5/5] smartcard: turn on qemu support

Daniel P. Berrange berrange at redhat.com
Wed Jan 26 12:29:13 UTC 2011


On Tue, Jan 25, 2011 at 05:36:58PM -0700, Eric Blake wrote:
> * 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
> ---
>  src/qemu/qemu_command.c                            |   90 +++++++++++++++++++-
>  .../qemuxml2argv-smartcard-controller.args         |    1 +
>  .../qemuxml2argv-smartcard-host-certificates.args  |    1 +
>  .../qemuxml2argv-smartcard-host.args               |    1 +
>  .../qemuxml2argv-smartcard-passthrough-tcp.args    |    1 +
>  tests/qemuxml2argvtest.c                           |   13 +++
>  6 files changed, 106 insertions(+), 1 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


ACK

> 
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 5b65f26..5197ab6 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;
> @@ -1003,7 +1007,8 @@ 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)
> +        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_FDC ||
> +            def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_CCID)
>              continue;

Worth updating the comment that 'ccid is a USB device'

> 
>          /* First IDE controller lives on the PIIX3 at slot=1, function=1,
> @@ -1505,6 +1510,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:
> @@ -3412,6 +3421,85 @@ 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;
> +
> +        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;
> +                }
> +                virBufferVSprintf(&opt, ",database=%s",
> +                                  smartcard->data.cert.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))

ACK

Daniel




More information about the libvir-list mailing list