Signed-off-by: Shi Lei <shi_lei@xxxxxxxxxxxxxx> --- docs/schemas/network.rng | 13 ++- src/conf/network_conf.c | 218 +++++++++++++++++++++++++-------------- 2 files changed, 152 insertions(+), 79 deletions(-) diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index c902f7e..14561d9 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -302,7 +302,18 @@ <zeroOrMore> <!-- VIRT:DIRECTIVE { "structure": {"output": "src/conf/network_conf"}, - "clearfunc": {"output": "src/conf/network_conf"} + "clearfunc": {"output": "src/conf/network_conf"}, + "parsefunc": { + "post": true, + "args.instname": true, + "args": [ + {"name": "partialOkay", "type": "Bool"} + ] + }, + "members": [ + {"id": "service", "opt": true}, + {"id": "protocol", "opt": true} + ] } --> <element name="srv"> <attribute name="service"><text/></attribute> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 6f0722a..3913cb4 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -214,6 +214,123 @@ virNetworkDefFree(virNetworkDefPtr def) } +/* This includes all characters used in the names of current + * /etc/services and /etc/protocols files (on Fedora 20), except ".", + * which we can't allow because it would conflict with the use of "." + * as a field separator in the SRV record, there appears to be no way + * to escape it in, and the protocols/services that use "." in the + * name are obscure and unlikely to be used anyway. + */ +#define PROTOCOL_CHARS \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" \ + "-+/" + +#define SERVICE_CHARS \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" \ + "_-+/*" + +static int +virNetworkDNSSrvDefParseXMLPost(xmlNodePtr curnode G_GNUC_UNUSED, + virNetworkDNSSrvDefPtr def, + xmlXPathContextPtr ctxt G_GNUC_UNUSED, + const char *networkName, + bool partialOkay, + const char *serviceStr G_GNUC_UNUSED, + const char *protocolStr G_GNUC_UNUSED, + const char *domainStr G_GNUC_UNUSED, + const char *targetStr G_GNUC_UNUSED, + bool has_port, + bool has_priority, + bool has_weight) +{ + if (!def->service && !partialOkay) { + virReportError(VIR_ERR_XML_DETAIL, + _("missing required service attribute in DNS SRV record " + "of network '%s'"), networkName); + return -1; + } + if (def->service) { + if (strlen(def->service) > DNS_RECORD_LENGTH_SRV) { + virReportError(VIR_ERR_XML_DETAIL, + _("service attribute '%s' in network '%s' is too long, " + "limit is %d bytes"), + def->service, networkName, DNS_RECORD_LENGTH_SRV); + return -1; + } + if (strspn(def->service, SERVICE_CHARS) < strlen(def->service)) { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid character in service attribute '%s' " + "in DNS SRV record of network '%s'"), + def->service, networkName); + return -1; + } + } + + if (!def->protocol && !partialOkay) { + virReportError(VIR_ERR_XML_DETAIL, + _("missing required protocol attribute " + "in DNS SRV record '%s' of network '%s'"), + def->service, networkName); + return -1; + } + if (def->protocol && + strspn(def->protocol, PROTOCOL_CHARS) < strlen(def->protocol)) { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid character in protocol attribute '%s' " + "in DNS SRV record of network '%s'"), + def->protocol, networkName); + return -1; + } + + if (has_port && !def->target) { + virReportError(VIR_ERR_XML_DETAIL, + _("DNS SRV port attribute not permitted without " + "target for service '%s' in network '%s'"), + def->service, networkName); + return -1; + } + if (has_port && (def->port < 1 || def->port > 65535)) { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid DNS SRV port attribute " + "for service '%s' in network '%s'"), + def->service, networkName); + return -1; + } + + if (has_priority && !def->target) { + virReportError(VIR_ERR_XML_DETAIL, + _("DNS SRV priority attribute not permitted without " + "target for service '%s' in network '%s'"), + def->service, networkName); + return -1; + } + if (has_priority && def->priority > 65535) { + virReportError(VIR_ERR_XML_DETAIL, + _("Invalid DNS SRV priority attribute " + "for service '%s' in network '%s'"), + def->service, networkName); + return -1; + } + + if (has_weight && !def->target) { + virReportError(VIR_ERR_XML_DETAIL, + _("DNS SRV weight attribute not permitted without " + "target for service '%s' in network '%s'"), + def->service, networkName); + return -1; + } + if (has_weight && def->weight > 65535) { + virReportError(VIR_ERR_XML_DETAIL, + _("invalid DNS SRV weight attribute " + "for service '%s' in network '%s'"), + def->service, networkName); + return -1; + } + + return 0; +} + + /* * virNetworkDefCopy: * @def: NetworkDef to copy @@ -594,21 +711,7 @@ virNetworkDNSHostDefParseXMLPost(xmlNodePtr curnode G_GNUC_UNUSED, } -/* This includes all characters used in the names of current - * /etc/services and /etc/protocols files (on Fedora 20), except ".", - * which we can't allow because it would conflict with the use of "." - * as a field separator in the SRV record, there appears to be no way - * to escape it in, and the protocols/services that use "." in the - * name are obscure and unlikely to be used anyway. - */ -#define PROTOCOL_CHARS \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" \ - "-+/" - -#define SERVICE_CHARS \ - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" \ - "_-+/*" - +/* virNetworkDNSSrvDefParseXML will be replaced by generated namesake */ static int virNetworkDNSSrvDefParseXML(const char *networkName, xmlNodePtr node, @@ -617,62 +720,23 @@ virNetworkDNSSrvDefParseXML(const char *networkName, bool partialOkay) { int ret; + bool has_port = false; + bool has_priority = false; + bool has_weight = false; xmlNodePtr save_ctxt = ctxt->node; - ctxt->node = node; - if (!(def->service = virXMLPropString(node, "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, - _("service attribute '%s' in network '%s' is too long, " - "limit is %d bytes"), - def->service, networkName, DNS_RECORD_LENGTH_SRV); - goto error; - } - if (strspn(def->service, SERVICE_CHARS) < strlen(def->service)) { - virReportError(VIR_ERR_XML_DETAIL, - _("invalid character in service attribute '%s' " - "in DNS SRV record of network '%s'"), - def->service, networkName); - goto error; - } - } - - if (!(def->protocol = virXMLPropString(node, "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, - _("invalid character in protocol attribute '%s' " - "in DNS SRV record of network '%s'"), - def->protocol, networkName); - goto error; - } + def->service = virXMLPropString(node, "service"); + def->protocol = virXMLPropString(node, "protocol"); /* 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) { - 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 (ret >= 0) { + has_port = true; + } else if (ret == -2) { virReportError(VIR_ERR_XML_DETAIL, _("invalid DNS SRV port attribute " "for service '%s' in network '%s'"), @@ -681,14 +745,9 @@ virNetworkDNSSrvDefParseXML(const char *networkName, } ret = virXPathUInt("string(./@priority)", ctxt, &def->priority); - if (ret >= 0 && !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 (ret >= 0) { + has_priority = true; + } else if (ret == -2) { virReportError(VIR_ERR_XML_DETAIL, _("Invalid DNS SRV priority attribute " "for service '%s' in network '%s'"), @@ -697,14 +756,9 @@ virNetworkDNSSrvDefParseXML(const char *networkName, } ret = virXPathUInt("string(./@weight)", ctxt, &def->weight); - if (ret >= 0 && !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 (ret >= 0) { + has_weight = true; + } else if (ret == -2) { virReportError(VIR_ERR_XML_DETAIL, _("invalid DNS SRV weight attribute " "for service '%s' in network '%s'"), @@ -712,6 +766,14 @@ virNetworkDNSSrvDefParseXML(const char *networkName, goto error; } + if (virNetworkDNSSrvDefParseXMLPost(node, def, ctxt, + networkName, partialOkay, + def->service, def->protocol, + def->domain, def->target, + has_port, has_priority, + has_weight) < 0) + goto error; + ctxt->node = save_ctxt; return 0; -- 2.17.1