Hi,
this is the patch to add support for adding TXT records to the
DNS service running on the virtual network. This has been tested
on Fedora-14 i386 box and tests are also added to RelaxNG schema
and test XML files.
It's been tested and checked/syntax-checked and everything was
working fine.
Also, the formatnetwork HTML document has been altered to
include those information about new DNS tag.
Michal
Signed-off-by: Michal Novotny <minovotn(a)redhat.com>
---
docs/formatnetwork.html.in | 26 ++++++++-
docs/schemas/network.rng | 12 ++++
src/conf/network_conf.c | 65 ++++++++++++++++++++
src/conf/network_conf.h | 16 +++++
src/network/bridge_driver.c | 27 ++++++++
.../nat-network-dns-txt-record.xml | 24 +++++++
.../nat-network-dns-txt-record.xml | 24 +++++++
tests/networkxml2xmltest.c | 1 +
8 files changed, 194 insertions(+), 1 deletions(-)
create mode 100644 tests/networkxml2xmlin/nat-network-dns-txt-record.xml
create mode 100644 tests/networkxml2xmlout/nat-network-dns-txt-record.xml
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index c6969eb..2d76d3d 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -108,7 +108,10 @@
The final set of elements define the addresses (IPv4 and/or
IPv6, as well as MAC) to be assigned to the bridge device
associated with the virtual network, and optionally enable DHCP
- services.
+ services. The network creation also supports the TXT record in
+ the DNS to expose some information to the guest using this
+ record. This feature could be used in the similar way like DKIM
+ uses TXT records of DNS to expose public key.
</p>
<pre>
@@ -120,6 +123,9 @@
<host mac="00:16:3e:77:e2:ed"
name="foo.example.com" ip="192.168.122.10" />
<host mac="00:16:3e:3e:a9:1a"
name="bar.example.com" ip="192.168.122.11" />
</dhcp>
+ <dns>
+ <txt-record name="example name" value="example
value" />
+ </dns>
</ip>
</network></pre>
@@ -199,6 +205,24 @@
element is used. The BOOTP options currently have to be the same
for all address ranges and statically assigned addresses.<span
class="since">Since 0.7.1 (<code>server</code> since
0.7.3).</span>
+ </dd><dt><code>dns</code></dt><dd>Also within
the <code>ip</code> element
+ there is an optional <code>dns</code> element. The presence of this
element
+ enables configuration and exposal of records in the DNS service on the
+ virtual network. It will further contain one or more
<code>txt-record</code>
+ elements. The <code>dns</code> element is supported for both IPv4 and
IPv6
+ networks. <span class="since">Since 0.9.0</span>
+ </dd>
+ <dt><code>txt-record</code></dt>
+ <dd>The <code>txt-record</code> element is the definition of TXT
record for the
+ DNS service. There are two attributes that both have to be used for the TXT
+ record definition: <code>name</code> and
<code>value</code>. The <code>name
+ </code>attribute doesn't support commas in it's value and therefore
you should
+ avoid using them since they are automatically replaced by spaces, e.g.
<code>
+ name, clarification</code> value of the <code>name</code> tag
will be replaced
+ to be <code>name clarification</code> instead. This rule doesn't
apply to the
+ record <code>value</code> contents since it supports multiple values
separated
+ by commas.
+ <span class="since">Since 0.9.0</span>
</dd>
</dl>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 6d01b06..e27dace 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -136,6 +136,18 @@
</optional>
</element>
</optional>
+ <optional>
+ <!-- Define the DNS related elements like TXT records
+ and other features -->
+ <element name="dns">
+ <zeroOrMore>
+ <element name="txt-record">
+ <attribute
name="name"><text/></attribute>
+ <attribute
name="value"><text/></attribute>
+ </element>
+ </zeroOrMore>
+ </element>
+ </optional>
</element>
</zeroOrMore>
</interleave>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index dcab9de..145ae20 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -435,6 +435,54 @@ virNetworkDHCPRangeDefParseXML(const char *networkName,
}
static int
+virNetworkDNSDefParseXML(virNetworkIpDefPtr def,
+ xmlNodePtr node)
+{
+
+ xmlNodePtr cur;
+ int result = -1;
+
+ if (VIR_ALLOC(def->dns))
+ goto oom_error;
+
+ cur = node->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE &&
+ xmlStrEqual(cur->name, BAD_CAST "txt-record")) {
+ char *name, *value;
+
+ if (!(name = virXMLPropString(cur, "name"))) {
+ cur = cur->next;
+ continue;
+ }
+ if (!(value = virXMLPropString(cur, "value"))) {
+ VIR_FREE(name);
+ cur = cur->next;
+ continue;
+ }
+
+ if (VIR_REALLOC_N(def->dns->txtrecords, def->dns->ntxtrecords +
1) < 0)
+ goto oom_error;
+
+ def->dns->txtrecords[def->dns->ntxtrecords].name = strdup(name);
+ def->dns->txtrecords[def->dns->ntxtrecords].value =
strdup(value);
+ def->dns->ntxtrecords++;
+
+ VIR_FREE(name);
+ VIR_FREE(value);
+ }
+
+ cur = cur->next;
+ }
+
+ return 0;
+
+oom_error:
+ virReportOOMError();
+ return result;
+}
+
+static int
virNetworkIPParseXML(const char *networkName,
virNetworkIpDefPtr def,
xmlNodePtr node,
@@ -550,6 +598,12 @@ virNetworkIPParseXML(const char *networkName,
goto error;
} else if (cur->type == XML_ELEMENT_NODE &&
+ xmlStrEqual(cur->name, BAD_CAST "dns")) {
+ result = virNetworkDNSDefParseXML(def, cur);
+ if (result)
+ goto error;
+
+ } else if (cur->type == XML_ELEMENT_NODE &&
xmlStrEqual(cur->name, BAD_CAST "tftp")) {
char *root;
@@ -828,6 +882,17 @@ virNetworkIpDefFormat(virBufferPtr buf,
virBufferAddLit(buf, " </dhcp>\n");
}
+ if ((def->dns != NULL) && (def->dns->ntxtrecords)) {
+ int ii;
+
+ virBufferAddLit(buf, " <dns>\n");
+ for (ii = 0 ; ii < def->dns->ntxtrecords ; ii++) {
+ virBufferVSprintf(buf, " <txt-record name='%s'
value='%s' />\n",
+ def->dns->txtrecords[ii].name,
+ def->dns->txtrecords[ii].value);
+ }
+ virBufferAddLit(buf, " </dns>\n");
+ }
virBufferAddLit(buf, " </ip>\n");
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 281124b..5f47595 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -57,6 +57,20 @@ struct _virNetworkDHCPHostDef {
virSocketAddr ip;
};
+typedef struct _virNetworkDNSTxtRecordsDef virNetworkDNSTxtRecordsDef;
+typedef virNetworkDNSTxtRecordsDef *virNetworkDNSTxtRecordsDefPtr;
+struct _virNetworkDNSTxtRecordsDef {
+ char *name;
+ char *value;
+};
+
+struct virNetworkDNSDef {
+ unsigned int ntxtrecords;
+ virNetworkDNSTxtRecordsDefPtr txtrecords;
+} virNetworkDNSDef;
+
+typedef struct virNetworkDNSDef *virNetworkDNSDefPtr;
+
typedef struct _virNetworkIpDef virNetworkIpDef;
typedef virNetworkIpDef *virNetworkIpDefPtr;
struct _virNetworkIpDef {
@@ -75,6 +89,8 @@ struct _virNetworkIpDef {
unsigned int nranges; /* Zero or more dhcp ranges */
virNetworkDHCPRangeDefPtr ranges;
+ virNetworkDNSDefPtr dns; /* DNS related settings for DNSMasq */
+
unsigned int nhosts; /* Zero or more dhcp hosts */
virNetworkDHCPHostDefPtr hosts;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index ea2bfd4..5d901ff 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -442,6 +442,18 @@ networkSaveDnsmasqHostsfile(virNetworkIpDefPtr ipdef,
return 0;
}
+static char *
+replace_all(char *input, int chr1, int chr2)
+{
+ char *tmp;
+ char *out;
+
+ out = strdup(input);
+ while ((tmp = strchr(out, chr1)) != NULL)
+ out[ strlen(input) - strlen(tmp) ] = chr2;
+
+ return out;
+}
static int
networkBuildDnsmasqArgv(virNetworkObjPtr network,
@@ -497,6 +509,21 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
if (network->def->forwardType == VIR_NETWORK_FORWARD_NONE)
virCommandAddArg(cmd, "--dhcp-option=3");
+ if (ipdef->dns != NULL) {
+ int i;
+
+ for (i = 0; i < ipdef->dns->ntxtrecords; i++) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ virBufferVSprintf(&buf, "%s,%s",
+ replace_all(ipdef->dns->txtrecords[i].name,
',', ' '),
+ ipdef->dns->txtrecords[i].value);
+
+ virCommandAddArgPair(cmd, "--txt-record",
virBufferContentAndReset(&buf));
+ VIR_FREE(buf);
+ }
+ }
+
/*
* --interface does not actually work with dnsmasq < 2.47,
* due to DAD for ipv6 addresses on the interface.
diff --git a/tests/networkxml2xmlin/nat-network-dns-txt-record.xml
b/tests/networkxml2xmlin/nat-network-dns-txt-record.xml
new file mode 100644
index 0000000..d3cdbd5
--- /dev/null
+++ b/tests/networkxml2xmlin/nat-network-dns-txt-record.xml
@@ -0,0 +1,24 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com'
ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com'
ip='192.168.122.11' />
+ </dhcp>
+ <dns>
+ <txt-record name='example name' value='example value' />
+ </dns>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1'
netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1'
prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1'
prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2xmlout/nat-network-dns-txt-record.xml
b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml
new file mode 100644
index 0000000..d3cdbd5
--- /dev/null
+++ b/tests/networkxml2xmlout/nat-network-dns-txt-record.xml
@@ -0,0 +1,24 @@
+<network>
+ <name>default</name>
+ <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+ <forward dev='eth1' mode='nat'/>
+ <bridge name='virbr0' stp='on' delay='0' />
+ <ip address='192.168.122.1' netmask='255.255.255.0'>
+ <dhcp>
+ <range start='192.168.122.2' end='192.168.122.254' />
+ <host mac='00:16:3e:77:e2:ed' name='a.example.com'
ip='192.168.122.10' />
+ <host mac='00:16:3e:3e:a9:1a' name='b.example.com'
ip='192.168.122.11' />
+ </dhcp>
+ <dns>
+ <txt-record name='example name' value='example value' />
+ </dns>
+ </ip>
+ <ip family='ipv4' address='192.168.123.1'
netmask='255.255.255.0'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fe01::1'
prefix='64'>
+ </ip>
+ <ip family='ipv6' address='2001:db8:ac10:fd01::1'
prefix='64'>
+ </ip>
+ <ip family='ipv4' address='10.24.10.1'>
+ </ip>
+</network>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index 7805548..beb00ef 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -90,6 +90,7 @@ mymain(int argc, char **argv)
DO_TEST("nat-network");
DO_TEST("netboot-network");
DO_TEST("netboot-proxy-network");
+ DO_TEST("nat-network-dns-txt-record");
return (ret==0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
--
1.7.3.2