diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index e103dd7857c8446d2b119ed057ad9b38ee0ec78a..13ca32de9765d3e887e0ab29434ca5b68fd0d936 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -847,7 +847,8 @@
<dns>
<txt name="example" value="example value" />
<forwarder addr="8.8.8.8"/>
- <forwarder addr="8.8.4.4"/>
+ <forwarder domain='example.com' addr="8.8.4.4"/>
+ <forwarder domain='www.example.com'/>
<srv service='name' protocol='tcp' domain='test-domain-name' target='.' port='1024' priority='10' weight='10'/>
<host ip='192.168.122.2'>
<hostname>myhost</hostname>
@@ -915,12 +916,25 @@
Currently supported sub-elements of <dns>
are:
forwarder
- - A
dns
element can have 0 or
- more forwarder
elements. Each forwarder
- element defines an IP address to be used as forwarder in
- DNS server configuration. The addr attribute is required
- and defines the IP address of every
- forwarder. Since 1.1.3
+ - The dns element can have 0 or
+ more
<forwarder>
elements. Each
+ forwarder element defines an alternate DNS server to use
+ for some, or all, DNS requests sent to this network's DNS
+ server. There are two attributes - domain
,
+ and addr
; at least one of these must be
+ specified in any <forwarder>
+ element. If both domain
and addr
+ are specified, then all requests that match the given
+ domain will be forwarded to the DNS server at addr. If
+ only domain
is specified, then all matching
+ domains will be resolved locally (or via the host's
+ standard DNS forwarding if they can't be resolved
+ locally). If an addr
is specified by itself,
+ then all DNS requests to the network's DNS server will be
+ forwarded to the DNS server at that address with no
+ exceptions. addr
Since
+ 1.1.3, domain
Since
+ 2.2.0.
txt
- A
dns
element can have 0 or more txt
elements.
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 12d4b345050e8cb968a8deec2a4a6255bf673aed..1a18e64b24f99548f43ef8d01a85c99463d92cae 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -260,7 +260,13 @@
-
+
+
+
+
+
+
+
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index d77b8379fe067c582ac9b4326e53e7bd68c3649e..aa397768c9c43441d425db2ad844b288ca57c126 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -349,12 +349,20 @@ virNetworkDNSSrvDefClear(virNetworkDNSSrvDefPtr def)
VIR_FREE(def->target);
}
+
+static void
+virNetworkDNSForwarderClear(virNetworkDNSForwarderPtr def)
+{
+ VIR_FREE(def->domain);
+}
+
+
static void
virNetworkDNSDefClear(virNetworkDNSDefPtr def)
{
if (def->forwarders) {
while (def->nfwds)
- VIR_FREE(def->forwarders[--def->nfwds]);
+ virNetworkDNSForwarderClear(&def->forwarders[--def->nfwds]);
VIR_FREE(def->forwarders);
}
if (def->txts) {
@@ -1379,14 +1387,25 @@ virNetworkDNSDefParseXML(const char *networkName,
goto cleanup;
for (i = 0; i < nfwds; i++) {
- def->forwarders[i] = virXMLPropString(fwdNodes[i], "addr");
- if (virSocketAddrParse(NULL, def->forwarders[i], AF_UNSPEC) < 0) {
+ char *addr = virXMLPropString(fwdNodes[i], "addr");
+
+ if (addr && virSocketAddrParse(&def->forwarders[i].addr,
+ addr, AF_UNSPEC) < 0) {
virReportError(VIR_ERR_XML_ERROR,
- _("Invalid forwarder IP address '%s' "
- "in network '%s'"),
- def->forwarders[i], networkName);
+ _("Invalid forwarder IP address '%s' "
+ "in network '%s'"),
+ addr, networkName);
+ VIR_FREE(addr);
+ goto cleanup;
+ }
+ def->forwarders[i].domain = virXMLPropString(fwdNodes[i], "domain");
+ if (!(addr || def->forwarders[i].domain)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid forwarder element, must contain "
+ "at least one of addr or domain"));
goto cleanup;
}
+ VIR_FREE(addr);
def->nfwds++;
}
}
@@ -2554,8 +2573,22 @@ virNetworkDNSDefFormat(virBufferPtr buf,
virBufferAdjustIndent(buf, 2);
for (i = 0; i < def->nfwds; i++) {
- virBufferAsprintf(buf, "\n",
- def->forwarders[i]);
+
+ virBufferAddLit(buf, "forwarders[i].domain) {
+ virBufferEscapeString(buf, " domain='%s'",
+ def->forwarders[i].domain);
+ }
+ if (VIR_SOCKET_ADDR_VALID(&def->forwarders[i].addr)) {
+ char *addr = virSocketAddrFormat(&def->forwarders[i].addr);
+
+ if (!addr)
+ return -1;
+
+ virBufferAsprintf(buf, " addr='%s'", addr);
+ VIR_FREE(addr);
+ }
+ virBufferAddLit(buf, "/>\n");
}
for (i = 0; i < def->ntxts; i++) {
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 9ebd4a73ebdd68e880f024cee65110707dd23e58..3b227db6f3ffd9c0f30f92129cb4edcc8285a333 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -125,6 +125,12 @@ struct _virNetworkDNSHostDef {
char **names;
};
+
+typedef struct _virNetworkDNSForwarder {
+ virSocketAddr addr;
+ char *domain;
+} virNetworkDNSForwarder, *virNetworkDNSForwarderPtr;
+
typedef struct _virNetworkDNSDef virNetworkDNSDef;
typedef virNetworkDNSDef *virNetworkDNSDefPtr;
struct _virNetworkDNSDef {
@@ -137,7 +143,7 @@ struct _virNetworkDNSDef {
size_t nsrvs;
virNetworkDNSSrvDefPtr srvs;
size_t nfwds;
- char **forwarders;
+ virNetworkDNSForwarderPtr forwarders;
};
typedef struct _virNetworkIPDef virNetworkIPDef;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 49c0a2fa76ed3c879a15944251fd71c3135e14f7..74f75d015f79c4c73caa92808315773b33b010f3 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -958,8 +958,21 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
if (wantDNS && network->def->dns.forwarders) {
virBufferAddLit(&configbuf, "no-resolv\n");
for (i = 0; i < network->def->dns.nfwds; i++) {
- virBufferAsprintf(&configbuf, "server=%s\n",
- network->def->dns.forwarders[i]);
+ virNetworkDNSForwarderPtr fwd = &network->def->dns.forwarders[i];
+
+ virBufferAddLit(&configbuf, "server=");
+ if (fwd->domain)
+ virBufferAsprintf(&configbuf, "/%s/", fwd->domain);
+ if (VIR_SOCKET_ADDR_VALID(&fwd->addr)) {
+ char *addr = virSocketAddrFormat(&fwd->addr);
+
+ if (!addr)
+ goto cleanup;
+ virBufferAsprintf(&configbuf, "%s\n", addr);
+ } else {
+ /* "don't forward requests for this domain" */
+ virBufferAddLit(&configbuf, "#\n");
+ }
}
}
diff --git a/tests/networkxml2confdata/nat-network-dns-forwarders.conf b/tests/networkxml2confdata/nat-network-dns-forwarders.conf
index 8bf3b9c360080e2ea323270bef6f0e60d80f0f1b..0bd76bf60c9701a52a4c8502fd79ccb74af2fa7c 100644
--- a/tests/networkxml2confdata/nat-network-dns-forwarders.conf
+++ b/tests/networkxml2confdata/nat-network-dns-forwarders.conf
@@ -8,6 +8,8 @@ strict-order
no-resolv
server=8.8.8.8
server=8.8.4.4
+server=/example.com/192.168.1.1
+server=/www.example.com/#
except-interface=lo
bind-dynamic
interface=virbr0
diff --git a/tests/networkxml2confdata/nat-network-dns-forwarders.xml b/tests/networkxml2confdata/nat-network-dns-forwarders.xml
index 8fab78ea3a3f4ee3360e45cecd734bfd17626230..5d4f3fa6977e6660672e1d076acb3a8690509eb7 100644
--- a/tests/networkxml2confdata/nat-network-dns-forwarders.xml
+++ b/tests/networkxml2confdata/nat-network-dns-forwarders.xml
@@ -6,6 +6,8 @@
+
+
diff --git a/tests/networkxml2xmlin/nat-network-dns-forwarders.xml b/tests/networkxml2xmlin/nat-network-dns-forwarders.xml
index 4d7310d1c6dff59c8aab7feae51b7e9226437909..426dd45cd9a14cc74f1e3f92f8aefea0940693a7 100644
--- a/tests/networkxml2xmlin/nat-network-dns-forwarders.xml
+++ b/tests/networkxml2xmlin/nat-network-dns-forwarders.xml
@@ -4,8 +4,10 @@
-
-
+
+
+
+
diff --git a/tests/networkxml2xmlout/nat-network-dns-forwarders.xml b/tests/networkxml2xmlout/nat-network-dns-forwarders.xml
index 930a42abc0e5d18599614007a758d28a2f41e20c..c05ad5514de611a6751fefabcf7f26c2ab7429d3 100644
--- a/tests/networkxml2xmlout/nat-network-dns-forwarders.xml
+++ b/tests/networkxml2xmlout/nat-network-dns-forwarders.xml
@@ -8,6 +8,8 @@
+
+