virDomainDiskSourceNetworkParse(xmlNodePtr node,
                                xmlXPathContextPtr ctxt,
                                virStorageSourcePtr src,
                                unsigned int flags)
{
    int tlsCfgVal;
    g_autofree char *protocol = NULL;
    g_autofree char *haveTLS = NULL;
    g_autofree char *tlsCfg = NULL;
    g_autofree char *sslverifystr = NULL;
    xmlNodePtr tmpnode;

    if (!(protocol = virXMLPropString(node, "protocol"))) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing network source protocol type"));
        return -1;
    }

    if ((src->protocol = virStorageNetProtocolTypeFromString(protocol)) <= 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unknown protocol type '%s'"), protocol);
        return -1;
    }

    if (!(src->path = virXMLPropString(node, "name")) &&
        src->protocol != VIR_STORAGE_NET_PROTOCOL_NBD) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing name for disk source"));
        return -1;
    }

    if ((haveTLS = virXMLPropString(node, "tls")) &&
        (src->haveTLS = virTristateBoolTypeFromString(haveTLS)) <= 0) {
        virReportError(VIR_ERR_XML_ERROR,
                   _("unknown disk source 'tls' setting '%s'"), haveTLS);
            return -1;
    }

    if ((flags & VIR_DOMAIN_DEF_PARSE_STATUS) &&
        (tlsCfg = virXMLPropString(node, "tlsFromConfig"))) {
        if (virStrToLong_i(tlsCfg, NULL, 10, &tlsCfgVal) < 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Invalid tlsFromConfig value: %s"),
                           tlsCfg);
            return -1;
        }
        src->tlsFromConfig = !!tlsCfgVal;
    }

    /* for historical reasons we store the volume and image name in one XML
     * element although it complicates thing when attempting to access them. */
    if (src->path &&
        (src->protocol == VIR_STORAGE_NET_PROTOCOL_GLUSTER ||
         src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD)) {
        char *tmp;
        if (!(tmp = strchr(src->path, '/')) ||
            tmp == src->path) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("can't split path '%s' into pool name and image "
                             "name"), src->path);
            return -1;
        }

        src->volume = src->path;

        src->path = g_strdup(tmp + 1);

        tmp[0] = '\0';
    }

    /* snapshot currently works only for remote disks */
    src->snapshot = virXPathString("string(./snapshot/@name)", ctxt);

    /* config file currently only works with remote disks */
    src->configFile = virXPathString("string(./config/@file)", ctxt);

    if (src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
        src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS)
        src->query = virXMLPropString(node, "query");

    if (virDomainStorageNetworkParseHosts(node, &src->hosts, &src->nhosts) < 0)
        return -1;

    virStorageSourceNetworkAssignDefaultPorts(src);

    virStorageSourceInitiatorParseXML(ctxt, &src->initiator);

    if ((src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS ||
         src->protocol == VIR_STORAGE_NET_PROTOCOL_FTPS) &&
        (sslverifystr = virXPathString("string(./ssl/@verify)", ctxt))) {
        int verify;
        if ((verify = virTristateBoolTypeFromString(sslverifystr)) < 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("invalid ssl verify mode '%s'"), sslverifystr);
            return -1;
        }

        src->sslverify = verify;
    }

    if ((src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
         src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS) &&
        (tmpnode = virXPathNode("./cookies", ctxt))) {
        if (virDomainStorageNetCookiesParse(tmpnode, ctxt, src) < 0)
            return -1;
    }

    if (src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTP ||
        src->protocol == VIR_STORAGE_NET_PROTOCOL_HTTPS ||
        src->protocol == VIR_STORAGE_NET_PROTOCOL_FTP ||
        src->protocol == VIR_STORAGE_NET_PROTOCOL_FTPS) {

        if (virXPathULongLong("string(./readahead/@size)", ctxt, &src->readahead) == -2 ||
            virXPathULongLong("string(./timeout/@seconds)", ctxt, &src->timeout) == -2) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                          _("invalid readahead size or timeout"));
            return -1;
        }
    }

    return 0;
}