virDomainChrDefParseTargetXML(virDomainChrDefPtr def,
                              xmlNodePtr cur,
                              unsigned int flags)
{
    xmlNodePtr child;
    unsigned int port;
    g_autofree char *targetType = virXMLPropString(cur, "type");
    g_autofree char *targetModel = NULL;
    g_autofree char *addrStr = NULL;
    g_autofree char *portStr = NULL;
    g_autofree char *stateStr = NULL;

    if ((def->targetType =
         virDomainChrTargetTypeFromString(def->deviceType,
                                          targetType)) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unknown target type '%s' specified for character device"),
                       targetType);
        return -1;
    }

    child = cur->children;
    while (child != NULL) {
        if (child->type == XML_ELEMENT_NODE &&
            virXMLNodeNameEqual(child, "model")) {
            targetModel = virXMLPropString(child, "name");
        }
        child = child->next;
    }

    if ((def->targetModel =
         virDomainChrTargetModelFromString(def->deviceType,
                                           targetModel)) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unknown target model '%s' specified for character device"),
                       targetModel);
        return -1;
    }

    switch (def->deviceType) {
    case VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL:
        switch (def->targetType) {
        case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
            addrStr = virXMLPropString(cur, "address");
            portStr = virXMLPropString(cur, "port");

            if (VIR_ALLOC(def->target.addr) < 0)
                return -1;

            if (addrStr == NULL) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("guestfwd channel does not "
                                 "define a target address"));
                return -1;
            }

            if (virSocketAddrParse(def->target.addr, addrStr, AF_UNSPEC) < 0)
                return -1;

            if (def->target.addr->data.stor.ss_family != AF_INET) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               "%s", _("guestfwd channel only supports "
                                       "IPv4 addresses"));
                return -1;
            }

            if (portStr == NULL) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("guestfwd channel does "
                                 "not define a target port"));
                return -1;
            }

            if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("Invalid port number: %s"),
                               portStr);
                return -1;
            }

            virSocketAddrSetPort(def->target.addr, port);
            break;

        case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
        case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
            def->target.name = virXMLPropString(cur, "name");

            if (def->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
                !(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE) &&
                (stateStr = virXMLPropString(cur, "state"))) {
                int tmp;

                if ((tmp = virDomainChrDeviceStateTypeFromString(stateStr)) <= 0) {
                    virReportError(VIR_ERR_XML_ERROR,
                                   _("invalid channel state value '%s'"),
                                   stateStr);
                    return -1;
                }

                def->state = tmp;
            }
            break;
        }
        break;

    default:
        portStr = virXMLPropString(cur, "port");
        if (portStr == NULL) {
            /* Set to negative value to indicate we should set it later */
            def->target.port = -1;
            break;
        }

        if (virStrToLong_ui(portStr, NULL, 10, &port) < 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Invalid port number: %s"),
                           portStr);
            return -1;
        }
        def->target.port = port;
        break;
    }

    return 0;
}