These three functions are very similar - none allow a MODIFY
operation; you can only add or delete.
The biggest difference between them (other than the data itself) is in
the criteria for determining a match, and whether or not multiple
matches are possible:
1) for HOST records, it's considered a match if the IP address or any
of the hostnames of an existing record matches.
2) for SRV records, it's a match if all of
domain+service+protocol+target *which have been specified* are
matched.
3) for TXT records, there is only a single field to match - name
(value can be the same for multiple records, and isn't considered a
search term), so by definition there can be no ambiguous matches.
In all three cases, if any matches are found, ADD will fail; if
multiple matches are found, it means the search term was ambiguous,
and a DELETE will fail.
The upper level code in bridge_driver.c is already implemented for
these functions - appropriate conf files will be re-written, and
dnsmasq will be SIGHUPed or restarted as appropriate.
---
src/conf/network_conf.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 232 insertions(+), 8 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index f45de26..0edf0ee 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2915,32 +2915,256 @@ virNetworkDefUpdateDNSHost(virNetworkDefPtr def,
/* virNetworkUpdateFlags */
unsigned int fflags ATTRIBUTE_UNUSED)
{
- virNetworkDefUpdateNoSupport(def, "dns host");
- return -1;
+ int ii, jj, kk, foundIdx, ret = -1;
+ virNetworkDNSDefPtr dns = &def->dns;
+ virNetworkDNSHostDef host;
+ bool isAdd = (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST ||
+ command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST);
+ bool foundCt = 0;
+
+ memset(&host, 0, sizeof(host));
+
+ if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("DNS HOST records cannot be modified, "
+ "only added or deleted"));
+ goto cleanup;
+ }
+
+ if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "host") <
0)
+ goto cleanup;
+
+ if (virNetworkDNSHostDefParseXML(def->name, ctxt->node, &host, !isAdd) <
0)
+ goto cleanup;
+
+ for (ii = 0; ii < dns->nhosts; ii++) {
+ bool foundThisTime = false;
+
+ if (virSocketAddrEqual(&host.ip, &dns->hosts[ii].ip))
+ foundThisTime = true;
+
+ for (jj = 0; jj < host.nnames && !foundThisTime; jj++) {
+ for (kk = 0; kk < dns->hosts[ii].nnames && !foundThisTime;
kk++) {
+ if (STREQ(host.names[jj], dns->hosts[ii].names[kk]))
+ foundThisTime = true;
+ }
+ }
+ if (foundThisTime) {
+ foundCt++;
+ foundIdx = ii;
+ }
+ }
+
+ if (isAdd) {
+
+ if (foundCt > 0) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("there is already at least one DNS HOST "
+ "record with a matching field in network %s"),
+ def->name);
+ goto cleanup;
+ }
+
+ /* add to beginning/end of list */
+ if (VIR_INSERT_ELEMENT(dns->hosts,
+ command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST
+ ? 0 : dns->nhosts, dns->nhosts, host) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
+
+ if (foundCt == 0) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("couldn't locate a matching DNS HOST "
+ "record in network %s"), def->name);
+ goto cleanup;
+ }
+ if (foundCt > 1) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("multiple matching DNS HOST records were "
+ "found in network %s"), def->name);
+ goto cleanup;
+ }
+
+ /* remove it */
+ virNetworkDNSHostDefClear(&dns->hosts[foundIdx]);
+ VIR_DELETE_ELEMENT(dns->hosts, foundIdx, dns->nhosts);
+
+ } else {
+ virNetworkDefUpdateUnknownCommand(command);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ virNetworkDNSHostDefClear(&host);
+ return ret;
}
static int
-virNetworkDefUpdateDNSTxt(virNetworkDefPtr def,
+virNetworkDefUpdateDNSSrv(virNetworkDefPtr def,
unsigned int command ATTRIBUTE_UNUSED,
int parentIndex ATTRIBUTE_UNUSED,
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
/* virNetworkUpdateFlags */
unsigned int fflags ATTRIBUTE_UNUSED)
{
- virNetworkDefUpdateNoSupport(def, "dns txt");
- return -1;
+ int ii, foundIdx, ret = -1;
+ virNetworkDNSDefPtr dns = &def->dns;
+ virNetworkDNSSrvDef srv;
+ bool isAdd = (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST ||
+ command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST);
+ bool foundCt = 0;
+
+ memset(&srv, 0, sizeof(srv));
+
+ if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("DNS SRV records cannot be modified, "
+ "only added or deleted"));
+ goto cleanup;
+ }
+
+ if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "srv") < 0)
+ goto cleanup;
+
+ if (virNetworkDNSSrvDefParseXML(def->name, ctxt->node, ctxt, &srv, !isAdd)
< 0)
+ goto cleanup;
+
+ for (ii = 0; ii < dns->nsrvs; ii++) {
+ if ((!srv.domain || STREQ_NULLABLE(srv.domain, dns->srvs[ii].domain))
&&
+ (!srv.service || STREQ_NULLABLE(srv.service, dns->srvs[ii].service))
&&
+ (!srv.protocol || STREQ_NULLABLE(srv.protocol, dns->srvs[ii].protocol))
&&
+ (!srv.target || STREQ_NULLABLE(srv.target, dns->srvs[ii].target))) {
+ foundCt++;
+ foundIdx = ii;
+ }
+ }
+
+ if (isAdd) {
+
+ if (foundCt > 0) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("there is already at least one DNS SRV "
+ "record matching all specified fields in network
%s"),
+ def->name);
+ goto cleanup;
+ }
+
+ /* add to beginning/end of list */
+ if (VIR_INSERT_ELEMENT(dns->srvs,
+ command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST
+ ? 0 : dns->nsrvs, dns->nsrvs, srv) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
+
+ if (foundCt == 0) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("couldn't locate a matching DNS SRV "
+ "record in network %s"), def->name);
+ goto cleanup;
+ }
+ if (foundCt > 1) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("multiple DNS SRV records matching all specified
"
+ "fields were found in network %s"),
def->name);
+ goto cleanup;
+ }
+
+ /* remove it */
+ virNetworkDNSSrvDefClear(&dns->srvs[foundIdx]);
+ VIR_DELETE_ELEMENT(dns->srvs, foundIdx, dns->nsrvs);
+
+ } else {
+ virNetworkDefUpdateUnknownCommand(command);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ virNetworkDNSSrvDefClear(&srv);
+ return ret;
}
static int
-virNetworkDefUpdateDNSSrv(virNetworkDefPtr def,
+virNetworkDefUpdateDNSTxt(virNetworkDefPtr def,
unsigned int command ATTRIBUTE_UNUSED,
int parentIndex ATTRIBUTE_UNUSED,
xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
/* virNetworkUpdateFlags */
unsigned int fflags ATTRIBUTE_UNUSED)
{
- virNetworkDefUpdateNoSupport(def, "dns txt");
- return -1;
+ int foundIdx, ret = -1;
+ virNetworkDNSDefPtr dns = &def->dns;
+ virNetworkDNSTxtDef txt;
+ bool isAdd = (command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST ||
+ command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST);
+
+ memset(&txt, 0, sizeof(txt));
+
+ if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("DNS TXT records cannot be modified, "
+ "only added or deleted"));
+ goto cleanup;
+ }
+
+ if (virNetworkDefUpdateCheckElementName(def, ctxt->node, "txt") < 0)
+ goto cleanup;
+
+ if (virNetworkDNSTxtDefParseXML(def->name, ctxt->node, &txt, !isAdd) <
0)
+ goto cleanup;
+
+ for (foundIdx = 0; foundIdx < dns->ntxts; foundIdx++) {
+ if (STREQ(txt.name, dns->txts[foundIdx].name))
+ break;
+ }
+
+ if (isAdd) {
+
+ if (foundIdx < dns->ntxts) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("there is already a DNS TXT record "
+ "with name '%s' in network %s"),
+ txt.name, def->name);
+ goto cleanup;
+ }
+
+ /* add to beginning/end of list */
+ if (VIR_INSERT_ELEMENT(dns->txts,
+ command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST
+ ? 0 : dns->ntxts, dns->ntxts, txt) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) {
+
+ if (foundIdx == dns->ntxts) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("couldn't locate a matching DNS TXT "
+ "record in network %s"), def->name);
+ goto cleanup;
+ }
+
+ /* remove it */
+ virNetworkDNSTxtDefClear(&dns->txts[foundIdx]);
+ VIR_DELETE_ELEMENT(dns->txts, foundIdx, dns->ntxts);
+
+ } else {
+ virNetworkDefUpdateUnknownCommand(command);
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ virNetworkDNSTxtDefClear(&txt);
+ return ret;
}
static int
--
1.7.11.7