[libvirt] [PATCH v3 3/3] network: Add support for local PTR domains

Jiri Denemark jdenemar at redhat.com
Fri Dec 16 18:09:24 UTC 2016


Similarly to localOnly DNS domain, localPtr attribute can be used to
tell the DNS server not to forward reverse lookups for unknown IPs which
belong to the virtual network.

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---

Notes:
    Version 3:
    - <ptr> was removed from this patch and will be implemented separately
    - NEWS item
    
    Version 2:
    - RNG schema and tests

 docs/formatnetwork.html.in                      | 21 ++++++++-----
 docs/news.html.in                               |  2 ++
 docs/schemas/network.rng                        |  3 ++
 src/conf/network_conf.c                         | 19 ++++++++++++
 src/conf/network_conf.h                         |  2 ++
 src/network/bridge_driver.c                     | 41 +++++++++++++++++++++++++
 tests/networkxml2confdata/ptr-domains-auto.conf | 20 ++++++++++++
 tests/networkxml2confdata/ptr-domains-auto.xml  | 21 +++++++++++++
 tests/networkxml2conftest.c                     |  1 +
 9 files changed, 123 insertions(+), 7 deletions(-)
 create mode 100644 tests/networkxml2confdata/ptr-domains-auto.conf
 create mode 100644 tests/networkxml2confdata/ptr-domains-auto.xml

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 9cf940052..390aa2e0d 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -855,14 +855,14 @@
     <hostname>myhostalias</hostname>
   </host>
 </dns>
-<ip address="192.168.122.1" netmask="255.255.255.0">
+<ip address="192.168.122.1" netmask="255.255.255.0" localPtr="yes">
   <dhcp>
     <range start="192.168.122.100" end="192.168.122.254"/>
     <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>
 </ip>
-<ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64"/>
+<ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" localPtr="yes"/>
 <route family="ipv6" address="2001:db9:ca1:1::" prefix="64" gateway="2001:db8:ca2:2::2"/>
 </pre>
 
@@ -983,11 +983,18 @@
         to specify the type of address — <code>ipv4</code> or
         <code>ipv6</code>; if no <code>family</code> is given,
         <code>ipv4</code> is assumed. More than one address of each family can
-        be defined for a network. The <code>ip</code> element is supported
-        <span class="since">since 0.3.0</span>. IPv6, multiple addresses on a
-        single network, <code>family</code>, and <code>prefix</code> are
-        supported <span class="since">since 0.8.7</span>. The <code>ip</code>
-        element may contain the following elements:
+        be defined for a network. The optional <code>localPtr</code> attribute
+        (<span class="since">since 3.0.0</span>) configures the DNS server not
+        to forward any reverse DNS requests for IP addresses from the network
+        configured by the <code>address</code> and
+        <code>netmask</code>/<code>prefix</code> attributes. For some unusual
+        network prefixes (not divisible by 8 for IPv4 or not divisible by 4 for
+        IPv6) libvirt may be unable to compute the PTR domain automatically.
+        The <code>ip</code> element is supported <span class="since">since
+        0.3.0</span>. IPv6, multiple addresses on a single network,
+        <code>family</code>, and <code>prefix</code> are supported
+        <span class="since">since 0.8.7</span>. The <code>ip</code> element may
+        contain the following elements:
 
         <dl>
           <dt><code>tftp</code></dt>
diff --git a/docs/news.html.in b/docs/news.html.in
index 80ac304cd..5a34674f1 100644
--- a/docs/news.html.in
+++ b/docs/news.html.in
@@ -16,6 +16,8 @@
     <ul>
       <li><strong>New features</strong>
         <ul>
+          <li>New localPtr attribute for "ip" element in network XML
+          </li>
           <li>qemu: Support QEMU group I/O throttling<br/>
           Add the capability to allow group I/O throttling via a new
           domain <disk> <iotune> subelement "group_name"
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 986119596..8f0a61b5b 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -339,6 +339,9 @@
             <optional>
               <attribute name="family"><ref name="addr-family"/></attribute>
             </optional>
+            <optional>
+              <attribute name="localPtr"><ref name="virYesNo"/></attribute>
+            </optional>
             <interleave>
               <optional>
                 <element name="tftp">
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index b6849ceab..86ce311ee 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1507,6 +1507,7 @@ virNetworkIPDefParseXML(const char *networkName,
     unsigned long prefix = 0;
     int prefixRc;
     int result = -1;
+    char *localPtr = NULL;
 
     save = ctxt->node;
     ctxt->node = node;
@@ -1549,6 +1550,17 @@ virNetworkIPDefParseXML(const char *networkName,
     else
         def->prefix = prefix;
 
+    localPtr = virXPathString("string(./@localPtr)", ctxt);
+    if (localPtr) {
+        def->localPTR = virTristateBoolTypeFromString(localPtr);
+        if (def->localPTR <= 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid localPtr value '%s' in network '%s'"),
+                           localPtr, networkName);
+            goto cleanup;
+        }
+    }
+
     /* validate address, etc. for each family */
     if ((def->family == NULL) || (STREQ(def->family, "ipv4"))) {
         if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) ||
@@ -1627,6 +1639,7 @@ virNetworkIPDefParseXML(const char *networkName,
         virNetworkIPDefClear(def);
     VIR_FREE(address);
     VIR_FREE(netmask);
+    VIR_FREE(localPtr);
 
     ctxt->node = save;
     return result;
@@ -2652,6 +2665,12 @@ virNetworkIPDefFormat(virBufferPtr buf,
     }
     if (def->prefix > 0)
         virBufferAsprintf(buf, " prefix='%u'", def->prefix);
+
+    if (def->localPTR) {
+        virBufferAsprintf(buf, " localPtr='%s'",
+                          virTristateBoolTypeToString(def->localPTR));
+    }
+
     virBufferAddLit(buf, ">\n");
     virBufferAdjustIndent(buf, 2);
 
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 09e091616..b5c9ea24e 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -162,6 +162,8 @@ struct _virNetworkIPDef {
     unsigned int prefix;        /* ipv6 - only prefix allowed */
     virSocketAddr netmask;      /* ipv4 - either netmask or prefix specified */
 
+    int localPTR; /* virTristateBool */
+
     size_t nranges;             /* Zero or more dhcp ranges */
     virSocketAddrRangePtr ranges;
 
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index ae1589d8c..f9022d43c 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -994,6 +994,43 @@ networkBuildDnsmasqHostsList(dnsmasqContext *dctx,
 }
 
 
+static int
+networkDnsmasqConfLocalPTRs(virBufferPtr buf,
+                            virNetworkDefPtr def)
+{
+    virNetworkIPDefPtr ip;
+    size_t i;
+    char *ptr = NULL;
+    int rc;
+
+    for (i = 0; i < def->nips; i++) {
+        ip = def->ips + i;
+
+        if (ip->localPTR != VIR_TRISTATE_BOOL_YES)
+            continue;
+
+        if ((rc = virSocketAddrPTRDomain(&ip->address,
+                                         virNetworkIPDefPrefix(ip),
+                                         &ptr)) < 0) {
+            if (rc == -2) {
+                int family = VIR_SOCKET_ADDR_FAMILY(&ip->address);
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("PTR domain for %s network with prefix %u "
+                                 "cannot be automatically created"),
+                               (family == AF_INET) ? "IPv4" : "IPv6",
+                               virNetworkIPDefPrefix(ip));
+            }
+            return -1;
+        }
+
+        virBufferAsprintf(buf, "local=/%s/\n", ptr);
+        VIR_FREE(ptr);
+    }
+
+    return 0;
+}
+
+
 int
 networkDnsmasqConfContents(virNetworkObjPtr network,
                            const char *pidfile,
@@ -1079,6 +1116,10 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
                           network->def->domain);
     }
 
+    if (wantDNS &&
+        networkDnsmasqConfLocalPTRs(&configbuf, network->def) < 0)
+        goto cleanup;
+
     if (wantDNS && network->def->dns.forwardPlainNames == VIR_TRISTATE_BOOL_NO) {
         virBufferAddLit(&configbuf, "domain-needed\n");
         /* need to specify local=// whether or not a domain is
diff --git a/tests/networkxml2confdata/ptr-domains-auto.conf b/tests/networkxml2confdata/ptr-domains-auto.conf
new file mode 100644
index 000000000..7f1a393dd
--- /dev/null
+++ b/tests/networkxml2confdata/ptr-domains-auto.conf
@@ -0,0 +1,20 @@
+##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=/122.168.192.in-addr.arpa/
+local=/1.0.e.f.0.1.c.a.8.b.d.0.1.0.0.2.ip6.arpa/
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254
+dhcp-no-override
+dhcp-authoritative
+dhcp-lease-max=253
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+dhcp-range=2001:db8:ac10:fe01::1,ra-only
+dhcp-range=2001:db8:ac10:fd01::1,ra-only
diff --git a/tests/networkxml2confdata/ptr-domains-auto.xml b/tests/networkxml2confdata/ptr-domains-auto.xml
new file mode 100644
index 000000000..7fe12dc67
--- /dev/null
+++ b/tests/networkxml2confdata/ptr-domains-auto.xml
@@ -0,0 +1,21 @@
+<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' localPtr='yes'>
+    <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>
+  </ip>
+  <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0' localPtr='no'>
+  </ip>
+  <ip family='ipv6' address='2001:db8:ac10:fe01::1' prefix='64' localPtr='yes'>
+  </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/networkxml2conftest.c b/tests/networkxml2conftest.c
index 65a0e3218..a80d3b2d4 100644
--- a/tests/networkxml2conftest.c
+++ b/tests/networkxml2conftest.c
@@ -129,6 +129,7 @@ mymain(void)
     DO_TEST("dhcp6-network", dhcpv6);
     DO_TEST("dhcp6-nat-network", dhcpv6);
     DO_TEST("dhcp6host-routed-network", dhcpv6);
+    DO_TEST("ptr-domains-auto", dhcpv6);
 
     virObjectUnref(dhcpv6);
     virObjectUnref(full);
-- 
2.11.0




More information about the libvir-list mailing list