VIR_FREE(def->bootfile);
}
-static void virNetworkDNSDefFree(virNetworkDNSDefPtr def)
+static void
+virNetworkDNSTxtDefClear(virNetworkDNSTxtDefPtr def)
{
- if (def) {
- if (def->txts) {
- while (def->ntxts--) {
- VIR_FREE(def->txts[def->ntxts].name);
- VIR_FREE(def->txts[def->ntxts].value);
- }
- }
+ VIR_FREE(def->name);
+ VIR_FREE(def->value);
+}
+
+static void
+virNetworkDNSHostDefClear(virNetworkDNSHostDefPtr def)
+{
+ while (def->nnames--)
+ VIR_FREE(def->names[def->nnames]);
+ VIR_FREE(def->names);
+}
+
+static void
+virNetworkDNSSrvDefClear(virNetworkDNSSrvDefPtr def)
+{
+ VIR_FREE(def->domain);
+ VIR_FREE(def->service);
+ VIR_FREE(def->protocol);
+ VIR_FREE(def->target);
+}
+
+static void
+virNetworkDNSDefClear(virNetworkDNSDefPtr def)
+{
+ if (def->txts) {
+ while (def->ntxts--)
+ virNetworkDNSTxtDefClear(&def->txts[def->ntxts]);
VIR_FREE(def->txts);
- if (def->nhosts) {
- while (def->nhosts--) {
- while (def->hosts[def->nhosts].nnames--)
- VIR_FREE(def->hosts[def->nhosts].names[def->hosts[def->nhosts].nnames]);
- VIR_FREE(def->hosts[def->nhosts].names);
- }
- }
+ }
+ if (def->hosts) {
+ while (def->nhosts--)
+ virNetworkDNSHostDefClear(&def->hosts[def->nhosts]);
VIR_FREE(def->hosts);
- if (def->nsrvs) {
- while (def->nsrvs--) {
- VIR_FREE(def->srvs[def->nsrvs].domain);
- VIR_FREE(def->srvs[def->nsrvs].service);
- VIR_FREE(def->srvs[def->nsrvs].protocol);
- VIR_FREE(def->srvs[def->nsrvs].target);
- }
- }
+ }
+ if (def->srvs) {
+ while (def->nsrvs--)
+ virNetworkDNSSrvDefClear(&def->srvs[def->nsrvs]);
VIR_FREE(def->srvs);
- VIR_FREE(def);
}
}
}
VIR_FREE(def->portGroups);
- virNetworkDNSDefFree(def->dns);
+ virNetworkDNSDefClear(&def->dns);
VIR_FREE(def->virtPortProfile);
}
static int
-virNetworkDNSHostsDefParseXML(virNetworkDNSDefPtr def,
- xmlNodePtr node)
+virNetworkDNSHostDefParseXML(const char *networkName,
+ xmlNodePtr node,
+ virNetworkDNSHostDefPtr def,
+ bool partialOkay)
{
xmlNodePtr cur;
char *ip;
- virSocketAddr inaddr;
- int ret = -1;
- if (!(ip = virXMLPropString(node, "ip")) ||
- (virSocketAddrParse(&inaddr, ip, AF_UNSPEC) < 0)) {
- virReportError(VIR_ERR_XML_DETAIL, "%s",
- _("Missing IP address in DNS host definition"));
+ if (!(ip = virXMLPropString(node, "ip")) && !partialOkay) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing IP address in network '%s' DNS HOST record"),
+ networkName);
VIR_FREE(ip);
goto error;
}
- VIR_FREE(ip);
-
- if (VIR_REALLOC_N(def->hosts, def->nhosts + 1) < 0) {
- virReportOOMError();
- goto error;
- }
-
- def->hosts[def->nhosts].ip = inaddr;
- def->hosts[def->nhosts].nnames = 0;
- if (VIR_ALLOC(def->hosts[def->nhosts].names) < 0) {
- virReportOOMError();
+ if (ip && (virSocketAddrParse(&def->ip, ip, AF_UNSPEC) < 0)) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Invalid IP address in network '%s' DNS HOST record"),
+ networkName);
+ VIR_FREE(ip);
goto error;
}
+ VIR_FREE(ip);
cur = node->children;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "hostname")) {
if (cur->children != NULL) {
- if (VIR_REALLOC_N(def->hosts[def->nhosts].names, def->hosts[def->nhosts].nnames + 1) < 0) {
+ if (VIR_REALLOC_N(def->names, def->nnames + 1) < 0) {
virReportOOMError();
goto error;
}
-
- def->hosts[def->nhosts].names[def->hosts[def->nhosts].nnames] = strdup((char *)cur->children->content);
- def->hosts[def->nhosts].nnames++;
+ def->names[def->nnames++] = (char *)xmlNodeGetContent(cur);
+ if (!def->names[def->nnames - 1]) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing hostname in network '%s' DNS HOST record"),
+ networkName);
+ }
}
}
-
cur = cur->next;
}
+ if (def->nnames == 0 && !partialOkay) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing hostname in network '%s' DNS HOST record"),
+ networkName);
+ goto error;
+ }
- def->nhosts++;
+ if (!VIR_SOCKET_ADDR_VALID(&def->ip) && def->nnames == 0) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing ip and hostname in network '%s' DNS HOST record"),
+ networkName);
+ goto error;
+ }
- ret = 0;
+ return 0;
error:
- return ret;
+ virNetworkDNSHostDefClear(def);
+ return -1;
}
static int
-virNetworkDNSSrvDefParseXML(virNetworkDNSDefPtr def,
- xmlNodePtr cur,
- xmlXPathContextPtr ctxt)
+virNetworkDNSSrvDefParseXML(const char *networkName,
+ xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ virNetworkDNSSrvDefPtr def,
+ bool partialOkay)
{
- char *domain = NULL;
- char *service = NULL;
- char *protocol = NULL;
- char *target = NULL;
- int port;
- int priority;
- int weight;
- int ret = 0;
-
- if (!(service = virXMLPropString(cur, "service"))) {
+ if (!(def->service = virXMLPropString(node, "service")) && !partialOkay) {
virReportError(VIR_ERR_XML_DETAIL,
- "%s", _("Missing required service attribute in dns srv record"));
+ _("Missing required service attribute in DNS SRV record "
+ " of network %s"), networkName);
goto error;
}
-
- if (strlen(service) > DNS_RECORD_LENGTH_SRV) {
+ if (strlen(def->service) > DNS_RECORD_LENGTH_SRV) {
virReportError(VIR_ERR_XML_DETAIL,
- _("Service name is too long, limit is %d bytes"),
- DNS_RECORD_LENGTH_SRV);
+ _("Service name '%s' in network %s is too long, limit is %d bytes"),
+ def->service, networkName, DNS_RECORD_LENGTH_SRV);
goto error;
}
- if (!(protocol = virXMLPropString(cur, "protocol"))) {
+ if (!(def->protocol = virXMLPropString(node, "protocol")) && !partialOkay) {
virReportError(VIR_ERR_XML_DETAIL,
- _("Missing required protocol attribute in dns srv record '%s'"), service);
+ _("Missing required protocol attribute "
+ "in dns srv record '%s' of network %s"),
+ def->service, networkName);
goto error;
}
/* Check whether protocol value is the supported one */
- if (STRNEQ(protocol, "tcp") && (STRNEQ(protocol, "udp"))) {
+ if (STRNEQ(def->protocol, "tcp") && (STRNEQ(def->protocol, "udp"))) {
virReportError(VIR_ERR_XML_DETAIL,
- _("Invalid protocol attribute value '%s'"), protocol);
+ _("Invalid protocol attribute value '%s' "
+ " in DNS SRV record of network %s"),
+ def->protocol, networkName);
goto error;
}
- if (VIR_REALLOC_N(def->srvs, def->nsrvs + 1) < 0) {
- virReportOOMError();
- goto error;
- }
-
- def->srvs[def->nsrvs].service = service;
- def->srvs[def->nsrvs].protocol = protocol;
- def->srvs[def->nsrvs].domain = NULL;
- def->srvs[def->nsrvs].target = NULL;
- def->srvs[def->nsrvs].port = 0;
- def->srvs[def->nsrvs].priority = 0;
- def->srvs[def->nsrvs].weight = 0;
-
- /* Following attributes are optional but we had to make sure they're NULL above */
- if ((target = virXMLPropString(cur, "target")) && (domain = virXMLPropString(cur, "domain"))) {
+ /* Following attributes are optional */
+ if ((def->target = virXMLPropString(node, "target")) &&
+ (def->domain = virXMLPropString(node, "domain"))) {
xmlNodePtr save_ctxt = ctxt->node;
- ctxt->node = cur;
- if (virXPathInt("string(./@port)", ctxt, &port))
- def->srvs[def->nsrvs].port = port;
+ ctxt->node = node;
+ if (virXPathUInt("string(./@port)", ctxt, &def->port) < 0 ||
+ def->port > 65535) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing or invalid port attribute "
+ "in network %s"), networkName);
+ goto error;
+ }
- if (virXPathInt("string(./@priority)", ctxt, &priority))
- def->srvs[def->nsrvs].priority = priority;
+ if (virXPathUInt("string(./@priority)", ctxt, &def->priority) < 0 ||
+ def->priority > 65535) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing or invalid priority attribute "
+ "in network %s"), networkName);
+ goto error;
+ }
- if (virXPathInt("string(./@weight)", ctxt, &weight))
- def->srvs[def->nsrvs].weight = weight;
- ctxt->node = save_ctxt;
+ if (virXPathUInt("string(./@weight)", ctxt, &def->weight) < 0 ||
+ def->weight > 65535) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing or invalid weight attribute "
+ "in network %s"), networkName);
+ goto error;
+ }
- def->srvs[def->nsrvs].domain = domain;
- def->srvs[def->nsrvs].target = target;
- def->srvs[def->nsrvs].port = port;
- def->srvs[def->nsrvs].priority = priority;
- def->srvs[def->nsrvs].weight = weight;
+ ctxt->node = save_ctxt;
}
- def->nsrvs++;
-
- goto cleanup;
+ if (!(def->service || def->protocol)) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing required service attribute or protocol "
+ "in DNS SRV record of network %s"), networkName);
+ goto error;
+ }
+ return 0;
error:
- VIR_FREE(domain);
- VIR_FREE(service);
- VIR_FREE(protocol);
- VIR_FREE(target);
+ virNetworkDNSSrvDefClear(def);
+ return -1;
+}
- ret = -1;
+static int
+virNetworkDNSTxtDefParseXML(const char *networkName,
+ xmlNodePtr node,
+ virNetworkDNSTxtDefPtr def,
+ bool partialOkay)
+{
+ if (!(def->name = virXMLPropString(node, "name"))) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("missing required name attribute in DNS TXT record "
+ "of network %s"), networkName);
+ goto error;
+ }
+ if (strchr(def->name, ' ') != NULL) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("prohibited space character in DNS TXT record "
+ "name '%s' of network %s"), def->name, networkName);
+ goto error;
+ }
+ if (!(def->value = virXMLPropString(node, "value")) && !partialOkay) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("missing required value attribute in DNS TXT record "
+ "named '%s' of network %s"), def->name, networkName);
+ goto error;
+ }
-cleanup:
- return ret;
+ if (!(def->name || def->value)) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("Missing required name or value "
+ "in DNS TXT record of network %s"), networkName);
+ goto error;
+ }
+ return 0;
+
+error:
+ virNetworkDNSTxtDefClear(def);
+ return -1;
}
static int
-virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef,
+virNetworkDNSDefParseXML(const char *networkName,
xmlNodePtr node,
- xmlXPathContextPtr ctxt)
+ xmlXPathContextPtr ctxt,
+ virNetworkDNSDefPtr def)
{
- xmlNodePtr cur;
- int ret = -1;
- char *name = NULL;
- char *value = NULL;
- virNetworkDNSDefPtr def = NULL;
+ xmlNodePtr *hostNodes = NULL;
+ xmlNodePtr *srvNodes = NULL;
+ xmlNodePtr *txtNodes = NULL;
+ int nhosts, nsrvs, ntxts;
+ int ii, ret = -1;
+ xmlNodePtr save = ctxt->node;
- if (VIR_ALLOC(def) < 0) {
- virReportOOMError();
- goto error;
+ ctxt->node = node;
+
+ nhosts = virXPathNodeSet("./host", ctxt, &hostNodes);
+ if (nhosts < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid <host> element found in <dns> of network %s"),
+ networkName);
+ goto cleanup;
}
+ if (nhosts > 0) {
+ if (VIR_ALLOC_N(def->hosts, nhosts) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
- cur = node->children;
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE &&
- xmlStrEqual(cur->name, BAD_CAST "txt")) {
- if (!(name = virXMLPropString(cur, "name"))) {
- virReportError(VIR_ERR_XML_DETAIL,
- "%s", _("Missing required name attribute in dns txt record"));
- goto error;
- }
- if (!(value = virXMLPropString(cur, "value"))) {
- virReportError(VIR_ERR_XML_DETAIL,
- _("Missing required value attribute in dns txt record '%s'"), name);
- goto error;
+ for (ii = 0; ii < nhosts; ii++) {
+ if (virNetworkDNSHostDefParseXML(networkName, hostNodes[ii],
+ &def->hosts[def->nhosts], false) < 0) {
+ goto cleanup;
}
+ def->nhosts++;
+ }
+ }
- if (strchr(name, ' ') != NULL) {
- virReportError(VIR_ERR_XML_DETAIL,
- _("spaces are not allowed in DNS TXT record names (name is '%s')"), name);
- goto error;
- }
+ nsrvs = virXPathNodeSet("./srv", ctxt, &srvNodes);
+ if (nsrvs < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid <srv> element found in <dns> of network %s"),
+ networkName);
+ goto cleanup;
+ }
+ if (nsrvs > 0) {
+ if (VIR_ALLOC_N(def->srvs, nsrvs) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
- if (VIR_REALLOC_N(def->txts, def->ntxts + 1) < 0) {
- virReportOOMError();
- goto error;
+ for (ii = 0; ii < nsrvs; ii++) {
+ if (virNetworkDNSSrvDefParseXML(networkName, srvNodes[ii], ctxt,
+ &def->srvs[def->nsrvs], false) < 0) {
+ goto cleanup;
}
+ def->nsrvs++;
+ }
+ }
- def->txts[def->ntxts].name = name;
- def->txts[def->ntxts].value = value;
- def->ntxts++;
- name = NULL;
- value = NULL;
- } else if (cur->type == XML_ELEMENT_NODE &&
- xmlStrEqual(cur->name, BAD_CAST "srv")) {
- ret = virNetworkDNSSrvDefParseXML(def, cur, ctxt);
- if (ret < 0)
- goto error;
- } else if (cur->type == XML_ELEMENT_NODE &&
- xmlStrEqual(cur->name, BAD_CAST "host")) {
- ret = virNetworkDNSHostsDefParseXML(def, cur);
- if (ret < 0)
- goto error;
+ ntxts = virXPathNodeSet("./txt", ctxt, &txtNodes);
+ if (ntxts < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid <txt> element found in <dns> of network %s"),
+ networkName);
+ goto cleanup;
+ }
+ if (ntxts > 0) {
+ if (VIR_ALLOC_N(def->txts, ntxts) < 0) {
+ virReportOOMError();
+ goto cleanup;
}
- cur = cur->next;
+ for (ii = 0; ii < ntxts; ii++) {
+ if (virNetworkDNSTxtDefParseXML(networkName, txtNodes[ii],
+ &def->txts[def->ntxts], false) < 0) {
+ goto cleanup;
+ }
+ def->ntxts++;
+ }
}
ret = 0;
-error:
- if (ret < 0) {
- VIR_FREE(name);
- VIR_FREE(value);
- virNetworkDNSDefFree(def);
- } else {
- *dnsdef = def;
- }
+cleanup:
+ VIR_FREE(hostNodes);
+ VIR_FREE(srvNodes);
+ VIR_FREE(txtNodes);
+ ctxt->node = save;
return ret;
}
}
dnsNode = virXPathNode("./dns", ctxt);
- if (dnsNode != NULL) {
- if (virNetworkDNSDefParseXML(&def->dns, dnsNode, ctxt) < 0)
- goto error;
+ if (dnsNode != NULL &&
+ virNetworkDNSDefParseXML(def->name, dnsNode, ctxt, &def->dns) < 0) {
+ goto error;
}
virtPortNode = virXPathNode("./virtualport", ctxt);
int result = 0;
int i;
- if (def == NULL)
+ if (!(def->nhosts || def->nsrvs || def->ntxts))
goto out;
virBufferAddLit(buf, "<dns>\n");
if (def->domain)
virBufferAsprintf(&buf, "<domain name='%s'/>\n", def->domain);
- if (virNetworkDNSDefFormat(&buf, def->dns) < 0)
+ if (virNetworkDNSDefFormat(&buf, &def->dns) < 0)
goto error;
if (virNetDevVlanFormat(&def->vlan, &buf) < 0)
char *recordPort = NULL;
char *recordWeight = NULL;
char *recordPriority = NULL;
+ virNetworkDNSDefPtr dns = &network->def->dns;
virNetworkIpDefPtr tmpipdef;
/*
"--no-resolv", NULL);
}
- if (network->def->dns != NULL) {
- virNetworkDNSDefPtr dns = network->def->dns;
- int i;
-
- for (i = 0; i < dns->ntxts; i++) {
- virCommandAddArgFormat(cmd, "--txt-record=%s,%s",
- dns->txts[i].name,
- dns->txts[i].value);
- }
+ for (ii = 0; ii < dns->ntxts; ii++) {
+ virCommandAddArgFormat(cmd, "--txt-record=%s,%s",
+ dns->txts[ii].name,
+ dns->txts[ii].value);
+ }
- for (i = 0; i < dns->nsrvs; i++) {
- if (dns->srvs[i].service && dns->srvs[i].protocol) {
- if (dns->srvs[i].port) {
- if (virAsprintf(&recordPort, "%d", dns->srvs[i].port) < 0) {
- virReportOOMError();
- goto cleanup;
- }
- }
- if (dns->srvs[i].priority) {
- if (virAsprintf(&recordPriority, "%d", dns->srvs[i].priority) < 0) {
- virReportOOMError();
- goto cleanup;
- }
+ for (ii = 0; ii < dns->nsrvs; ii++) {
+ if (dns->srvs[ii].service && dns->srvs[ii].protocol) {
+ if (dns->srvs[ii].port) {
+ if (virAsprintf(&recordPort, "%d", dns->srvs[ii].port) < 0) {
+ virReportOOMError();
+ goto cleanup;
}
- if (dns->srvs[i].weight) {
- if (virAsprintf(&recordWeight, "%d", dns->srvs[i].weight) < 0) {
- virReportOOMError();
- goto cleanup;
- }
+ }
+ if (dns->srvs[ii].priority) {
+ if (virAsprintf(&recordPriority, "%d", dns->srvs[ii].priority) < 0) {
+ virReportOOMError();
+ goto cleanup;
}
-
- if (virAsprintf(&record, "%s.%s.%s,%s,%s,%s,%s",
- dns->srvs[i].service,
- dns->srvs[i].protocol,
- dns->srvs[i].domain ? dns->srvs[i].domain : "",
- dns->srvs[i].target ? dns->srvs[i].target : "",
- recordPort ? recordPort : "",
- recordPriority ? recordPriority : "",
- recordWeight ? recordWeight : "") < 0) {
+ }
+ if (dns->srvs[ii].weight) {
+ if (virAsprintf(&recordWeight, "%d", dns->srvs[ii].weight) < 0) {
virReportOOMError();
goto cleanup;
}
+ }
- virCommandAddArgPair(cmd, "--srv-host", record);
- VIR_FREE(record);
- VIR_FREE(recordPort);
- VIR_FREE(recordWeight);
- VIR_FREE(recordPriority);
+ if (virAsprintf(&record, "%s.%s.%s,%s,%s,%s,%s",
+ dns->srvs[ii].service,
+ dns->srvs[ii].protocol,
+ dns->srvs[ii].domain ? dns->srvs[ii].domain : "",
+ dns->srvs[ii].target ? dns->srvs[ii].target : "",
+ recordPort ? recordPort : "",
+ recordPriority ? recordPriority : "",
+ recordWeight ? recordWeight : "") < 0) {
+ virReportOOMError();
+ goto cleanup;
}
+
+ virCommandAddArgPair(cmd, "--srv-host", record);
+ VIR_FREE(record);
+ VIR_FREE(recordPort);
+ VIR_FREE(recordWeight);
+ VIR_FREE(recordPriority);
}
}
/* add domain to any non-qualified hostnames in /etc/hosts or addn-hosts */
if (network->def->domain)
- virCommandAddArg(cmd, "--expand-hosts");
+ virCommandAddArg(cmd, "--expand-hosts");
- if (networkBuildDnsmasqHostsfile(dctx, ipdef, network->def->dns) < 0)
+ if (networkBuildDnsmasqHostsfile(dctx, ipdef, &network->def->dns) < 0)
goto cleanup;
/* Even if there are currently no static hosts, if we're
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET) &&
(ipdef->nranges || ipdef->nhosts)) {
if (networkBuildDnsmasqHostsfile(dctx, ipdef,
- network->def->dns) < 0)
+ &network->def->dns) < 0)
goto cleanup;
break;
if (!(dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR)))
goto cleanup;
- if (networkBuildDnsmasqHostsfile(dctx, ipdef, network->def->dns) < 0)
+ if (networkBuildDnsmasqHostsfile(dctx, ipdef, &network->def->dns) < 0)
goto cleanup;
if ((ret = dnsmasqSave(dctx)) < 0)
virNetworkForwardTypeToString(def->forwardType));
return -1;
}
- if (def->dns &&
- (def->dns->ntxts || def->dns->nhosts || def->dns->nsrvs)) {
+ if (def->dns.ntxts || def->dns.nhosts || def->dns.nsrvs) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Unsupported <dns> element in network %s "
"with forward mode='%s'"),