]> xenbits.xensource.com Git - libvirt.git/commitdiff
network: Let domains be restricted to local DNS
authorJosh Stone <jistone@redhat.com>
Thu, 4 Dec 2014 00:01:33 +0000 (16:01 -0800)
committerLaine Stump <laine@laine.org>
Tue, 20 Jan 2015 06:07:18 +0000 (01:07 -0500)
This adds a new "localOnly" attribute on the domain element of the
network xml.  With this set to "yes", DNS requests under that domain
will only be resolved by libvirt's dnsmasq, never forwarded upstream.

This was how it worked before commit f69a6b987d616, and I found that
functionality useful.  For example, I have my host's NetworkManager
dnsmasq configured to forward that domain to libvirt's dnsmasq, so I can
easily resolve guest names from outside.  But if libvirt's dnsmasq
doesn't know a name and forwards it to the host, I'd get an endless
forwarding loop.  Now I can set localOnly="yes" to prevent the loop.

Signed-off-by: Josh Stone <jistone@redhat.com>
docs/formatnetwork.html.in
docs/schemas/network.rng
src/conf/network_conf.c
src/conf/network_conf.h
src/network/bridge_driver.c
tests/networkxml2confdata/nat-network-dns-local-domain.conf [new file with mode: 0644]
tests/networkxml2confdata/nat-network-dns-local-domain.xml [new file with mode: 0644]
tests/networkxml2conftest.c

index ca0e20709c902657534fff01369cb1f44c0cc940..7cf3f69d52049a498db087258bb664f2a44410c9 100644 (file)
@@ -82,7 +82,7 @@
     <pre>
         ...
         &lt;bridge name="virbr0" stp="on" delay="5" macTableManager="libvirt"/&gt;
-        &lt;domain name="example.com"/&gt;
+        &lt;domain name="example.com" localOnly="no"/&gt;
         &lt;forward mode="nat" dev="eth0"/&gt;
         ...</pre>
 
         a <code>&lt;forward&gt;</code> mode of "nat" or "route" (or an
         isolated network with no <code>&lt;forward&gt;</code>
         element). <span class="since">Since 0.4.5</span>
+
+        <p>
+          If the optional <code>localOnly</code> attribute on the
+          <code>domain</code> element is "yes", then DNS requests under
+          this domain will only be resolved by the virtual network's own
+          DNS server - they will not be forwarded to the host's upstream
+          DNS server.  If <code>localOnly</code> is "no", and by
+          default, unresolved requests <b>will</b> be forwarded.
+          <span class="since">Since 1.2.12</span>
+        </p>
       </dd>
       <dt><code>forward</code></dt>
       <dd>Inclusion of the <code>forward</code> element indicates that
index a6b8cb2be7d63cbeaf8a1d2928cec26fd6b4857d..56b6086d8ffd250e1a96ce4b3a8fbc9aa6433d80 100644 (file)
         <optional>
           <element name="domain">
             <attribute name="name"><ref name="dnsName"/></attribute>
+            <optional>
+              <attribute name="localOnly"><ref name="virYesNo"/></attribute>
+            </optional>
           </element>
         </optional>
 
index 23ec369c0e8b397b671474f6d891da7b22e88c66..f947d89108f5c4659c5d5948d85cb21032f09cc8 100644 (file)
@@ -1854,6 +1854,18 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
 
     /* Parse network domain information */
     def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
+    tmp = virXPathString("string(./domain[1]/@localOnly)", ctxt);
+    if (tmp) {
+        def->domainLocalOnly = virTristateBoolTypeFromString(tmp);
+        if (def->domainLocalOnly <= 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid domain localOnly setting '%s' "
+                             "in network '%s'"),
+                           tmp, def->name);
+            goto error;
+        }
+        VIR_FREE(tmp);
+    }
 
     if ((bandwidthNode = virXPathNode("./bandwidth", ctxt)) &&
         virNetDevBandwidthParse(&def->bandwidth, bandwidthNode, -1) < 0)
@@ -2560,8 +2572,24 @@ virNetworkDefFormatBuf(virBufferPtr buf,
         virBufferAsprintf(buf, "<mac address='%s'/>\n", macaddr);
     }
 
-    if (def->domain)
-        virBufferAsprintf(buf, "<domain name='%s'/>\n", def->domain);
+    if (def->domain) {
+        virBufferAsprintf(buf, "<domain name='%s'", def->domain);
+
+        /* default to "no", but don't format it in the XML */
+        if (def->domainLocalOnly) {
+            const char *local = virTristateBoolTypeToString(def->domainLocalOnly);
+
+            if (!local) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("Unknown localOnly type %d in network"),
+                               def->domainLocalOnly);
+                return -1;
+            }
+            virBufferAsprintf(buf, " localOnly='%s'", local);
+        }
+
+        virBufferAddLit(buf, "/>\n");
+    }
 
     if (virNetworkDNSDefFormat(buf, &def->dns) < 0)
         goto error;
index b113e14e64594767e61d3a4dee31eab900aea5b9..484522e6a85cf77825e39585bfc3680f8807f1fc 100644 (file)
@@ -225,6 +225,7 @@ struct _virNetworkDef {
     char *bridge;       /* Name of bridge device */
     int  macTableManager; /* enum virNetworkBridgeMACTableManager */
     char *domain;
+    int domainLocalOnly; /* enum virTristateBool: yes disables dns forwarding */
     unsigned long delay;   /* Bridge forward delay (ms) */
     bool stp; /* Spanning tree protocol */
     virMacAddr mac; /* mac address of bridge device */
index 7b84e279d701a7cdb33d79160fd01897af88e66c..94e32ecad2138f27a9ebc726d771d609c3542d1d 100644 (file)
@@ -928,6 +928,11 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
     }
 
     if (network->def->domain) {
+        if (network->def->domainLocalOnly == VIR_TRISTATE_BOOL_YES) {
+            virBufferAsprintf(&configbuf,
+                              "local=/%s/\n",
+                              network->def->domain);
+        }
         virBufferAsprintf(&configbuf,
                           "domain=%s\n"
                           "expand-hosts\n",
diff --git a/tests/networkxml2confdata/nat-network-dns-local-domain.conf b/tests/networkxml2confdata/nat-network-dns-local-domain.conf
new file mode 100644 (file)
index 0000000..5f41b91
--- /dev/null
@@ -0,0 +1,14 @@
+##WARNING:  THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST.  Changes to this configuration should be made using:
+##    virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+local=/example.com/
+domain=example.com
+expand-hosts
+except-interface=lo
+bind-dynamic
+interface=virbr0
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
diff --git a/tests/networkxml2confdata/nat-network-dns-local-domain.xml b/tests/networkxml2confdata/nat-network-dns-local-domain.xml
new file mode 100644 (file)
index 0000000..a92d71f
--- /dev/null
@@ -0,0 +1,9 @@
+<network>
+  <name>default</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9c</uuid>
+  <forward dev='eth0' mode='nat'/>
+  <bridge name='virbr0' stp='on' delay='0' />
+  <domain name='example.com' localOnly='yes'/>
+  <ip address='192.168.122.1' netmask='255.255.255.0'>
+  </ip>
+</network>
index 267513f6372c11654fa6f0ebc985c5232c381ca2..280db306b6d6f421500560138e0041259fc86fdb 100644 (file)
@@ -134,6 +134,7 @@ mymain(void)
     DO_TEST("nat-network-dns-hosts", full);
     DO_TEST("nat-network-dns-forward-plain", full);
     DO_TEST("nat-network-dns-forwarders", full);
+    DO_TEST("nat-network-dns-local-domain", full);
     DO_TEST("dhcp6-network", dhcpv6);
     DO_TEST("dhcp6-nat-network", dhcpv6);
     DO_TEST("dhcp6host-routed-network", dhcpv6);