From ab297becc150fd1b8b2f314eef855db5945cee2c Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Sun, 11 Nov 2012 19:00:22 -0500 Subject: [PATCH] conf: clear and parse functions for dns host/srv/txt records Since there is only a single virNetworkDNSDef for any virNetworkDef, and it's trivial to determine whether or not it contains any real data, it's much simpler (and fits more uniformly with the parse function calling sequence of the parsers for many other objects that are subordinates of virNetworkDef) if virNetworkDef *contains* an virNetworkDNSDef rather than pointing to one. Since it is now just a part of another object rather than its own object, it no longer makes sense to have a *Free() function, so that is changed to a *Clear() function. More importantly though, ParseXML and Clear functions are needed for the individual items contained in a virNetworkDNSDef (srv, txt, and host records), but none of them have a *Clear(), and only two of the three had *ParseXML() functions (both of which used a non-uniform arglist). Those problems are cleared up by this patch - it splits the higher-level Clear function into separate functions for each of the three, creates a parse for txt records, and cleans up the srv and host parsers, so we now have all the utility functions necessary to implement virNetworkDefUpdateDNS(Host|Srv|Txt). --- src/conf/network_conf.c | 412 +++++++++++++++++++++--------------- src/conf/network_conf.h | 8 +- src/network/bridge_driver.c | 89 ++++---- 3 files changed, 286 insertions(+), 223 deletions(-) diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 259f4f77f4..2bd8b26940 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -133,34 +133,47 @@ static void virNetworkIpDefClear(virNetworkIpDefPtr def) 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); } } @@ -195,7 +208,7 @@ void virNetworkDefFree(virNetworkDefPtr def) } VIR_FREE(def->portGroups); - virNetworkDNSDefFree(def->dns); + virNetworkDNSDefClear(&def->dns); VIR_FREE(def->virtPortProfile); @@ -787,224 +800,279 @@ virNetworkDHCPDefParse(const char *networkName, } 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 element found in 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 element found in 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 element found in 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; } @@ -1320,9 +1388,9 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt) } 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); @@ -1684,7 +1752,7 @@ virNetworkDNSDefFormat(virBufferPtr buf, int result = 0; int i; - if (def == NULL) + if (!(def->nhosts || def->nsrvs || def->ntxts)) goto out; virBufferAddLit(buf, "\n"); @@ -1959,7 +2027,7 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags) if (def->domain) virBufferAsprintf(&buf, "\n", def->domain); - if (virNetworkDNSDefFormat(&buf, def->dns) < 0) + if (virNetworkDNSDefFormat(&buf, &def->dns) < 0) goto error; if (virNetDevVlanFormat(&def->vlan, &buf) < 0) diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 82056c6c2f..60042fcd28 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -90,9 +90,9 @@ struct _virNetworkDNSSrvDef { char *service; char *protocol; char *target; - int port; - int priority; - int weight; + unsigned int port; + unsigned int priority; + unsigned int weight; }; typedef struct _virNetworkDNSHostDef virNetworkDNSHostDef; @@ -206,7 +206,7 @@ struct _virNetworkDef { size_t nips; virNetworkIpDefPtr ips; /* ptr to array of IP addresses on this network */ - virNetworkDNSDefPtr dns; /* ptr to dns related configuration */ + virNetworkDNSDef dns; /* dns related configuration */ virNetDevVPortProfilePtr virtPortProfile; size_t nPortGroups; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 453bb6394f..a5b9182b5e 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -608,6 +608,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, char *recordPort = NULL; char *recordWeight = NULL; char *recordPriority = NULL; + virNetworkDNSDefPtr dns = &network->def->dns; virNetworkIpDefPtr tmpipdef; /* @@ -715,55 +716,50 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, "--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); } } @@ -813,9 +809,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, /* 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 @@ -965,7 +961,7 @@ networkStartDhcpDaemon(struct network_driver *driver, 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; @@ -1040,7 +1036,7 @@ networkRefreshDhcpDaemon(struct network_driver *driver, 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) @@ -2763,8 +2759,7 @@ networkValidate(struct network_driver *driver, 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 element in network %s " "with forward mode='%s'"), -- GitLab