From 9d4e2845d498edcf46fe339537fe473f24d75f66 Mon Sep 17 00:00:00 2001 From: Michal Novotny Date: Fri, 24 Jun 2011 12:04:40 +0200 Subject: [PATCH] Network: Add support for DNS hosts definition to the network XML This commit introduces names definition for the DNS hosts file using the following syntax: alias1 alias2 Some of the improvements and fixes were done by Laine Stump so I'm putting him into the SOB clause again ;-) Signed-off-by: Michal Novotny Signed-off-by: Laine Stump --- docs/formatnetwork.html.in | 8 ++ docs/schemas/network.rng | 8 ++ src/conf/network_conf.c | 94 +++++++++++++++++++ src/conf/network_conf.h | 10 ++ src/network/bridge_driver.c | 28 ++++-- .../nat-network-dns-hosts.argv | 1 + .../nat-network-dns-hosts.xml | 14 +++ tests/networkxml2argvtest.c | 1 + .../nat-network-dns-hosts.xml | 14 +++ .../nat-network-dns-hosts.xml | 14 +++ tests/networkxml2xmltest.c | 1 + 11 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.xml create mode 100644 tests/networkxml2xmlin/nat-network-dns-hosts.xml create mode 100644 tests/networkxml2xmlout/nat-network-dns-hosts.xml diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index 4a5cb0347b..cbec7af59e 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -184,6 +184,14 @@ or commas. value is a single string that can contain multiple values separated by commas. Since 0.9.3 +
host
+
The host element within dns is the + definition of DNS hosts to be passed to the DNS service. The IP + address is identified by the ip attribute and the names + for that IP address are identified in the hostname + sub-elements of the host element. + Since 0.9.3 +
dhcp
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index c42382e4db..05f45e5489 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -97,6 +97,14 @@ + + + + + + + + diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index d8f1e25c2f..d0860d874e 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -114,6 +114,14 @@ static void virNetworkDNSDefFree(virNetworkDNSDefPtr def) } VIR_FREE(def->txtrecords); } + 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); + } + VIR_FREE(def->hosts); + } VIR_FREE(def); } } @@ -450,6 +458,71 @@ virNetworkDHCPRangeDefParseXML(const char *networkName, return 0; } +static int +virNetworkDNSHostsDefParseXML(virNetworkDNSDefPtr def, + xmlNodePtr node) +{ + xmlNodePtr cur; + char *ip; + virSocketAddr inaddr; + int ret = -1; + + if (def->hosts == NULL) { + if (VIR_ALLOC(def->hosts) < 0) { + virReportOOMError(); + goto error; + } + def->nhosts = 0; + } + + if (!(ip = virXMLPropString(node, "ip")) || + (virSocketParseAddr(ip, &inaddr, AF_UNSPEC) < 0)) { + virNetworkReportError(VIR_ERR_XML_DETAIL, + _("Missing IP address in DNS host definition")); + 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(); + goto error; + } + + 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) { + virReportOOMError(); + goto error; + } + + def->hosts[def->nhosts].names[def->hosts[def->nhosts].nnames] = strdup((char *)cur->children->content); + def->hosts[def->nhosts].nnames++; + } + } + + cur = cur->next; + } + + def->nhosts++; + + ret = 0; + +error: + return ret; +} + static int virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef, xmlNodePtr node) @@ -496,6 +569,11 @@ virNetworkDNSDefParseXML(virNetworkDNSDefPtr *dnsdef, def->ntxtrecords++; name = NULL; value = NULL; + } else if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "host")) { + ret = virNetworkDNSHostsDefParseXML(def, cur); + if (ret < 0) + goto error; } cur = cur->next; @@ -854,6 +932,22 @@ virNetworkDNSDefFormat(virBufferPtr buf, def->txtrecords[i].value); } + if (def->nhosts) { + int ii, j; + + for (ii = 0 ; ii < def->nhosts; ii++) { + char *ip = virSocketFormatAddr(&def->hosts[ii].ip); + + virBufferAsprintf(buf, " \n", ip); + + for (j = 0; j < def->hosts[ii].nnames; j++) + virBufferAsprintf(buf, " %s\n", + def->hosts[ii].names[j]); + + virBufferAsprintf(buf, " \n"); + } + } + virBufferAddLit(buf, " \n"); out: return result; diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index d0dac02196..d7d2951997 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -64,9 +64,19 @@ struct _virNetworkDNSTxtRecordsDef { char *value; }; +struct virNetworkDNSHostsDef { + virSocketAddr ip; + int nnames; + char **names; +} virNetworkDNSHostsDef; + +typedef struct virNetworkDNSHostsDef *virNetworkDNSHostsDefPtr; + struct virNetworkDNSDef { unsigned int ntxtrecords; virNetworkDNSTxtRecordsDefPtr txtrecords; + unsigned int nhosts; + virNetworkDNSHostsDefPtr hosts; } virNetworkDNSDef; typedef struct virNetworkDNSDef *virNetworkDNSDefPtr; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 448afbdfb7..1b11132413 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -435,10 +435,11 @@ networkShutdown(void) { static dnsmasqContext* networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, + virNetworkDNSDefPtr dnsdef, char *name, bool force) { - unsigned int i; + unsigned int i, j; dnsmasqContext *dctx = dnsmasqContextNew(name, DNSMASQ_STATE_DIR); @@ -447,13 +448,22 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef, goto cleanup; } - if (! force && virFileExists(dctx->hostsfile->path)) - return 0; + if (!(! force && virFileExists(dctx->hostsfile->path))) { + for (i = 0; i < ipdef->nhosts; i++) { + virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]); + if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip)) + dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name); + } + } - for (i = 0; i < ipdef->nhosts; i++) { - virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]); - if ((host->mac) && VIR_SOCKET_HAS_ADDR(&host->ip)) - dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name); + if (dnsdef) { + for (i = 0; i < dnsdef->nhosts; i++) { + virNetworkDNSHostsDefPtr host = &(dnsdef->hosts[i]); + if (VIR_SOCKET_HAS_ADDR(&host->ip)) { + for (j = 0; j < host->nnames; j++) + dnsmasqAddHost(dctx, &host->ip, host->names[j]); + } + } } if (dnsmasqSave(dctx) < 0) @@ -604,7 +614,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, if (ipdef->nranges || ipdef->nhosts) virCommandAddArg(cmd, "--dhcp-no-override"); - if ((dctx = networkSaveDnsmasqHostsfile(ipdef, network->def->name, false))) { + if ((dctx = networkSaveDnsmasqHostsfile(ipdef, network->def->dns, network->def->name, false))) { if (dctx->hostsfile->nhosts) virCommandAddArgPair(cmd, "--dhcp-hostsfile", dctx->hostsfile->path); @@ -2239,7 +2249,7 @@ static virNetworkPtr networkDefine(virConnectPtr conn, const char *xml) { } } if (ipv4def) { - dnsmasqContext* dctx = networkSaveDnsmasqHostsfile(ipv4def, network->def->name, true); + dnsmasqContext* dctx = networkSaveDnsmasqHostsfile(ipv4def, network->def->dns, network->def->name, true); if (dctx == NULL) goto cleanup; dnsmasqContextFree(dctx); diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv new file mode 100644 index 0000000000..d240bf41c8 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv @@ -0,0 +1 @@ +/usr/sbin/dnsmasq --strict-order --bind-interfaces --conf-file= --except-interface lo --listen-address 192.168.122.1 --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \ No newline at end of file diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.xml b/tests/networkxml2argvdata/nat-network-dns-hosts.xml new file mode 100644 index 0000000000..9a83fed17f --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.xml @@ -0,0 +1,14 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9c + + + + + host + gateway + + + + + diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c index 98c84ad7f5..16d57a9c7a 100644 --- a/tests/networkxml2argvtest.c +++ b/tests/networkxml2argvtest.c @@ -101,6 +101,7 @@ mymain(void) DO_TEST("netboot-network"); DO_TEST("netboot-proxy-network"); DO_TEST("nat-network-dns-txt-record"); + DO_TEST("nat-network-dns-hosts"); return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } diff --git a/tests/networkxml2xmlin/nat-network-dns-hosts.xml b/tests/networkxml2xmlin/nat-network-dns-hosts.xml new file mode 100644 index 0000000000..9a83fed17f --- /dev/null +++ b/tests/networkxml2xmlin/nat-network-dns-hosts.xml @@ -0,0 +1,14 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9c + + + + + host + gateway + + + + + diff --git a/tests/networkxml2xmlout/nat-network-dns-hosts.xml b/tests/networkxml2xmlout/nat-network-dns-hosts.xml new file mode 100644 index 0000000000..9a83fed17f --- /dev/null +++ b/tests/networkxml2xmlout/nat-network-dns-hosts.xml @@ -0,0 +1,14 @@ + + default + 81ff0d90-c91e-6742-64da-4a736edb9a9c + + + + + host + gateway + + + + + diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index 2cc8e560fe..065166d724 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -87,6 +87,7 @@ mymain(void) DO_TEST("netboot-network"); DO_TEST("netboot-proxy-network"); DO_TEST("nat-network-dns-txt-record"); + DO_TEST("nat-network-dns-hosts"); return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); }