Signed-off-by: Shi Lei <shi_lei@xxxxxxxxxxxxxx> --- src/conf/network_conf.c | 107 +++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 24 deletions(-) diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index bb976a78..20128af0 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -768,23 +768,26 @@ virNetworkDNSHostDefParseXML(const char *networkName, "_-+/*" static int -virNetworkDNSSrvDefParseXML(const char *networkName, - xmlNodePtr node, - xmlXPathContextPtr ctxt, - virNetworkDNSSrvDef *def, - bool partialOkay) +virNetworkDNSSrvDefParseHook(xmlNodePtr node G_GNUC_UNUSED, + virNetworkDNSSrvDef *def, + const char *networkName, + void *parent G_GNUC_UNUSED, + void *opaque, + const char *portStr, + const char *priorityStr, + const char *weightStr) { - int ret; - VIR_XPATH_NODE_AUTORESTORE(ctxt) - - ctxt->node = node; + bool partialOkay = false; + if (opaque) + partialOkay = *((bool *) opaque); - if (!(def->service = virXMLPropString(node, "service")) && !partialOkay) { + if (!def->service && !partialOkay) { virReportError(VIR_ERR_XML_DETAIL, _("missing required service attribute in DNS SRV record " "of network '%s'"), networkName); goto error; } + if (def->service) { if (strlen(def->service) > DNS_RECORD_LENGTH_SRV) { virReportError(VIR_ERR_XML_DETAIL, @@ -802,13 +805,14 @@ virNetworkDNSSrvDefParseXML(const char *networkName, } } - if (!(def->protocol = virXMLPropString(node, "protocol")) && !partialOkay) { + if (!def->protocol && !partialOkay) { virReportError(VIR_ERR_XML_DETAIL, _("missing required protocol attribute " "in DNS SRV record '%s' of network '%s'"), def->service, networkName); goto error; } + if (def->protocol && strspn(def->protocol, PROTOCOL_CHARS) < strlen(def->protocol)) { virReportError(VIR_ERR_XML_DETAIL, @@ -818,19 +822,14 @@ virNetworkDNSSrvDefParseXML(const char *networkName, goto error; } - /* Following attributes are optional */ - def->domain = virXMLPropString(node, "domain"); - def->target = virXMLPropString(node, "target"); - - ret = virXPathUInt("string(./@port)", ctxt, &def->port); - if (ret >= 0 && !def->target) { + if (portStr && !def->target) { virReportError(VIR_ERR_XML_DETAIL, _("DNS SRV port attribute not permitted without " "target for service '%s' in network '%s'"), def->service, networkName); goto error; } - if (ret == -2 || (ret >= 0 && (def->port < 1 || def->port > 65535))) { + if (portStr && (def->port < 1 || def->port > 65535)) { virReportError(VIR_ERR_XML_DETAIL, _("invalid DNS SRV port attribute " "for service '%s' in network '%s'"), @@ -838,15 +837,14 @@ virNetworkDNSSrvDefParseXML(const char *networkName, goto error; } - ret = virXPathUInt("string(./@priority)", ctxt, &def->priority); - if (ret >= 0 && !def->target) { + if (priorityStr && !def->target) { virReportError(VIR_ERR_XML_DETAIL, _("DNS SRV priority attribute not permitted without " "target for service '%s' in network '%s'"), def->service, networkName); goto error; } - if (ret == -2 || (ret >= 0 && def->priority > 65535)) { + if (priorityStr && def->priority > 65535) { virReportError(VIR_ERR_XML_DETAIL, _("Invalid DNS SRV priority attribute " "for service '%s' in network '%s'"), @@ -854,15 +852,14 @@ virNetworkDNSSrvDefParseXML(const char *networkName, goto error; } - ret = virXPathUInt("string(./@weight)", ctxt, &def->weight); - if (ret >= 0 && !def->target) { + if (weightStr && !def->target) { virReportError(VIR_ERR_XML_DETAIL, _("DNS SRV weight attribute not permitted without " "target for service '%s' in network '%s'"), def->service, networkName); goto error; } - if (ret == -2 || (ret >= 0 && def->weight > 65535)) { + if (weightStr && def->weight > 65535) { virReportError(VIR_ERR_XML_DETAIL, _("invalid DNS SRV weight attribute " "for service '%s' in network '%s'"), @@ -872,6 +869,68 @@ virNetworkDNSSrvDefParseXML(const char *networkName, return 0; + error: + return -1; +} + + +static int +virNetworkDNSSrvDefParseXML(const char *networkName, + xmlNodePtr node, + xmlXPathContextPtr ctxt G_GNUC_UNUSED, + virNetworkDNSSrvDef *def, + bool partialOkay) +{ + g_autofree char *portStr = NULL; + g_autofree char *priorityStr = NULL; + g_autofree char *weightStr = NULL; + + def->service = virXMLPropString(node, "service"); + def->protocol = virXMLPropString(node, "protocol"); + + /* Following attributes are optional */ + def->domain = virXMLPropString(node, "domain"); + def->target = virXMLPropString(node, "target"); + + portStr = virXMLPropString(node, "port"); + if (portStr) { + if (virStrToLong_uip(portStr, NULL, 0, &def->port) < 0) { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid DNS SRV port attribute " + "for service '%s' in network '%s'"), + def->service, networkName); + goto error; + } + } + + priorityStr = virXMLPropString(node, "priority"); + if (priorityStr) { + if (virStrToLong_uip(priorityStr, NULL, 0, &def->priority) < 0) { + virReportError(VIR_ERR_XML_DETAIL, + _("Invalid DNS SRV priority attribute " + "for service '%s' in network '%s'"), + def->service, networkName); + goto error; + } + } + + weightStr = virXMLPropString(node, "weight"); + if (weightStr) { + if (virStrToLong_uip(weightStr, NULL, 0, &def->weight) < 0) { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid DNS SRV weight attribute " + "for service '%s' in network '%s'"), + def->service, networkName); + goto error; + } + } + + if (virNetworkDNSSrvDefParseHook(node, def, networkName, def, &partialOkay, + portStr, priorityStr, weightStr) < 0) + goto error; + + return 0; + error: virNetworkDNSSrvDefClear(def); return -1; -- 2.25.1