]> xenbits.xensource.com Git - libvirt.git/commitdiff
network: permit upstream forwarding of unqualified DNS names
authorLaine Stump <laine@laine.org>
Tue, 13 Aug 2013 22:56:38 +0000 (18:56 -0400)
committerLaine Stump <laine@laine.org>
Wed, 14 Aug 2013 13:46:22 +0000 (09:46 -0400)
This resolves the issue that prompted the filing of

  https://bugzilla.redhat.com/show_bug.cgi?id=928638

(although the request there is for something much larger and more
general than this patch).

commit f3868259ca0517212e439a65c9060868f673b6c9 disabled the
forwarding to upstream DNS servers of unresolved DNS requests for
names that had no domain, but were just simple host names (no "."
character anywhere in the name). While this behavior is frowned upon
by DNS root servers (that's why it was changed in libvirt), it is
convenient in some cases, and since dnsmasq can be configured to allow
it, it must not be strictly forbidden.

This patch restores the old behavior, but since it is usually
undesirable, restoring it requires specification of a new option in
the network config. Adding the attribute "forwardPlainNames='yes'" to
the <dns> elemnt does the trick - when that attribute is added to a
network config, any simple hostnames that can't be resolved by the
network's dnsmasq instance will be forwarded to the DNS servers listed
in the host's /etc/resolv.conf for an attempt at resolution (just as
any FQDN would be forwarded).

When that attribute *isn't* specified, unresolved simple names will
*not* be forwarded to the upstream DNS server - this is the default
behavior.

13 files changed:
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-forward-plain.conf [new file with mode: 0644]
tests/networkxml2confdata/nat-network-dns-forward-plain.xml [new file with mode: 0644]
tests/networkxml2confdata/nat-network-dns-hosts.xml
tests/networkxml2conftest.c
tests/networkxml2xmlin/nat-network-dns-forward-plain.xml [new file with mode: 0644]
tests/networkxml2xmlin/nat-network-dns-hosts.xml
tests/networkxml2xmlout/nat-network-dns-forward-plain.xml [new file with mode: 0644]
tests/networkxml2xmltest.c

index eb7c4c722ef90eeaa01d3a4cec4d94b82bab98ca..e1482db972c8e6b1e6d528a5a5d86a80eadb3b16 100644 (file)
         with the idiosyncrasies of the platform where libvirt is
         running. <span class="since">Since 0.8.8</span>
       </dd>
-      <dt><code>dns</code></dt><dd>
-        The dns element of a network contains configuration information for the
-        virtual network's DNS server. <span class="since">Since 0.9.3</span>
-        Currently supported elements are:
+      <dt><code>dns</code></dt>
+      <dd> The dns element of a network contains configuration
+        information for the virtual network's DNS
+        server <span class="since">Since 0.9.3</span>.
+
+        <p>
+          The dns element
+          can have an optional <code>forwardPlainNames</code>
+          attribute <span class="since">Since 1.1.2</span>.
+          If <code>forwardPlainNames</code> is "no", then DNS resolution
+          requests for names that are not qualified with a domain
+          (i.e. names with no "." character) will not be forwarded to
+          the host's upstream DNS server - they will only be resolved if
+          they are known locally within the virtual network's own DNS
+          server. If <code>forwardPlainNames</code> is "yes",
+          unqualified names <b>will</b> be forwarded to the upstream DNS
+          server if they can't be resolved by the virtual network's own
+          DNS server.
+        </p>
+
+        Currently supported sub-elements of <code>&lt;dns&gt;</code> are:
         <dl>
           <dt><code>txt</code></dt>
           <dd>A <code>dns</code> element can have 0 or more <code>txt</code> elements.
index ded858092aebf5e1bd097cf42d597b5a51f40c26..ab183f156990dae6611e2bca5ada1ac9af7796c7 100644 (file)
              and other features in the <dns> element -->
         <optional>
             <element name="dns">
+              <optional>
+                <attribute name="forwardPlainNames">
+                  <choice>
+                    <value>yes</value>
+                    <value>no</value>
+                  </choice>
+                </attribute>
+              </optional>
               <zeroOrMore>
                 <element name="txt">
                   <attribute name="name"><ref name="dnsName"/></attribute>
index 9141bbb2ab042be3776b07027f0316dcfd9da187..bbc980b69364605c0b1fa5bae30f50231b368c57 100644 (file)
@@ -1037,6 +1037,7 @@ virNetworkDNSDefParseXML(const char *networkName,
     xmlNodePtr *hostNodes = NULL;
     xmlNodePtr *srvNodes = NULL;
     xmlNodePtr *txtNodes = NULL;
+    char *forwardPlainNames = NULL;
     int nhosts, nsrvs, ntxts;
     size_t i;
     int ret = -1;
@@ -1044,6 +1045,19 @@ virNetworkDNSDefParseXML(const char *networkName,
 
     ctxt->node = node;
 
+    forwardPlainNames = virXPathString("string(./@forwardPlainNames)", ctxt);
+    if (forwardPlainNames) {
+        if (STREQ(forwardPlainNames, "yes")) {
+            def->forwardPlainNames = true;
+        } else if (STRNEQ(forwardPlainNames, "no")) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid dns forwardPlainNames setting '%s' "
+                             "in network '%s'"),
+                           forwardPlainNames, networkName);
+            goto cleanup;
+        }
+    }
+
     nhosts = virXPathNodeSet("./host", ctxt, &hostNodes);
     if (nhosts < 0) {
         virReportError(VIR_ERR_XML_ERROR,
@@ -1106,6 +1120,7 @@ virNetworkDNSDefParseXML(const char *networkName,
 
     ret = 0;
 cleanup:
+    VIR_FREE(forwardPlainNames);
     VIR_FREE(hostNodes);
     VIR_FREE(srvNodes);
     VIR_FREE(txtNodes);
@@ -2252,10 +2267,19 @@ virNetworkDNSDefFormat(virBufferPtr buf,
     int result = 0;
     size_t i, j;
 
-    if (!(def->nhosts || def->nsrvs || def->ntxts))
+    if (!(def->forwardPlainNames || def->nhosts || def->nsrvs || def->ntxts))
         goto out;
 
-    virBufferAddLit(buf, "<dns>\n");
+    virBufferAddLit(buf, "<dns");
+    if (def->forwardPlainNames) {
+        virBufferAddLit(buf, " forwardPlainNames='yes'");
+        if (!(def->nhosts || def->nsrvs || def->ntxts)) {
+            virBufferAddLit(buf, "/>\n");
+            goto out;
+        }
+    }
+
+    virBufferAddLit(buf, ">\n");
     virBufferAdjustIndent(buf, 2);
 
     for (i = 0; i < def->ntxts; i++) {
index a1d3282db4a0efd9cf9db90bb0a550887338873d..920e899ad889eab0d676b905c937be0e60ce5f4c 100644 (file)
@@ -115,6 +115,7 @@ struct _virNetworkDNSHostDef {
 typedef struct _virNetworkDNSDef virNetworkDNSDef;
 typedef virNetworkDNSDef *virNetworkDNSDefPtr;
 struct _virNetworkDNSDef {
+    bool forwardPlainNames;
     size_t ntxts;
     virNetworkDNSTxtDefPtr txts;
     size_t nhosts;
index dd3024477262a960d4b3db45f4872a31df462371..00f2befcaff96efd1e737f4295efba674f74c570 100644 (file)
@@ -678,20 +678,28 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
                       "##    virsh net-edit %s\n"
                       "## or other application using the libvirt API.\n"
                       "##\n## dnsmasq conf file created by libvirt\n"
-                      "strict-order\n"
-                      "domain-needed\n",
+                      "strict-order\n",
                       network->def->name);
 
+    if (!network->def->dns.forwardPlainNames)
+        virBufferAddLit(&configbuf, "domain-needed\n");
+
     if (network->def->domain) {
         virBufferAsprintf(&configbuf,
                           "domain=%s\n"
                           "expand-hosts\n",
                           network->def->domain);
     }
-    /* need to specify local even if no domain specified */
-    virBufferAsprintf(&configbuf,
-                      "local=/%s/\n",
-                      network->def->domain ? network->def->domain : "");
+
+    if (network->def->domain || !network->def->dns.forwardPlainNames) {
+        /* need to specify local even if no domain specified, unless
+         * the config says we should forward "plain" names (i.e. not
+         * fully qualified, no '.' characters)
+         */
+        virBufferAsprintf(&configbuf,
+                          "local=/%s/\n",
+                          network->def->domain ? network->def->domain : "");
+    }
 
     if (pidfile)
         virBufferAsprintf(&configbuf, "pid-file=%s\n", pidfile);
diff --git a/tests/networkxml2confdata/nat-network-dns-forward-plain.conf b/tests/networkxml2confdata/nat-network-dns-forward-plain.conf
new file mode 100644 (file)
index 0000000..9a000b8
--- /dev/null
@@ -0,0 +1,11 @@
+##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
+except-interface=lo
+bind-dynamic
+interface=virbr0
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
diff --git a/tests/networkxml2confdata/nat-network-dns-forward-plain.xml b/tests/networkxml2confdata/nat-network-dns-forward-plain.xml
new file mode 100644 (file)
index 0000000..10bacb5
--- /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' />
+  <dns forwardPlainNames='yes'/>
+  <ip address='192.168.122.1' netmask='255.255.255.0'>
+  </ip>
+</network>
index 2180a5ddcdfd3d11092e166c9e78b136df9001f9..351df4fb5721004379ff76adcb28cc46c896e16f 100644 (file)
@@ -4,7 +4,7 @@
   <forward dev='eth0' mode='nat'/>
   <bridge name='virbr0' stp='on' delay='0' />
   <domain name="example.com"/>
-  <dns>
+  <dns forwardPlainNames='no'>
     <host ip='192.168.122.1'>
       <hostname>host</hostname>
       <hostname>gateway</hostname>
index b234b306a857abefe595bca1fc2856ca551a0814..5825af3484c3f5ee00f7c4da8ba6088bf5081629 100644 (file)
@@ -144,6 +144,7 @@ mymain(void)
     DO_TEST("nat-network-dns-txt-record", full);
     DO_TEST("nat-network-dns-srv-record", full);
     DO_TEST("nat-network-dns-hosts", full);
+    DO_TEST("nat-network-dns-forward-plain", full);
     DO_TEST("dhcp6-network", dhcpv6);
     DO_TEST("dhcp6-nat-network", dhcpv6);
     DO_TEST("dhcp6host-routed-network", dhcpv6);
diff --git a/tests/networkxml2xmlin/nat-network-dns-forward-plain.xml b/tests/networkxml2xmlin/nat-network-dns-forward-plain.xml
new file mode 100644 (file)
index 0000000..10bacb5
--- /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' />
+  <dns forwardPlainNames='yes'/>
+  <ip address='192.168.122.1' netmask='255.255.255.0'>
+  </ip>
+</network>
index 9a83fed17f41c53334a4b5ab8b4d4cdc21ae346a..954c9dbc9ef870f1e6593915810dd470622aff31 100644 (file)
@@ -3,7 +3,7 @@
   <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9c</uuid>
   <forward dev='eth0' mode='nat'/>
   <bridge name='virbr0' stp='on' delay='0' />
-  <dns>
+  <dns forwardPlainNames='no'>
     <host ip='192.168.122.1'>
       <hostname>host</hostname>
       <hostname>gateway</hostname>
diff --git a/tests/networkxml2xmlout/nat-network-dns-forward-plain.xml b/tests/networkxml2xmlout/nat-network-dns-forward-plain.xml
new file mode 100644 (file)
index 0000000..3b50828
--- /dev/null
@@ -0,0 +1,11 @@
+<network>
+  <name>default</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9c</uuid>
+  <forward dev='eth0' mode='nat'>
+    <interface dev='eth0'/>
+  </forward>
+  <bridge name='virbr0' stp='on' delay='0' />
+  <dns forwardPlainNames='yes'/>
+  <ip address='192.168.122.1' netmask='255.255.255.0'>
+  </ip>
+</network>
index 0dfed161ac7d745f22bb18bb10ff82ded20f6b63..11b3f02228f76c667d3c44e132c905a00f64651f 100644 (file)
@@ -104,6 +104,7 @@ mymain(void)
     DO_TEST("netboot-proxy-network");
     DO_TEST("nat-network-dns-txt-record");
     DO_TEST("nat-network-dns-hosts");
+    DO_TEST("nat-network-dns-forward-plain");
     DO_TEST("8021Qbh-net");
     DO_TEST("direct-net");
     DO_TEST("host-bridge-net");