This patch fixes reverse DNS zone creation so that a /24 IPv4 and /64 IPv6 reverse zones are created by default. The reverse zone can be customized using new --reverse-zone option in ipa-server-install, ipa-replica-prepare, ipa-replica-install and ipa-dns-install, which replaces the old way of using the netmask part of the --ip-address option. The reverse zone name is printed to the user during the install.

https://fedorahosted.org/freeipa/ticket/1398

Honza

--
Jan Cholasta
>From 0c0a797c09102e5c9abd36629a2f66d7121e5a2f Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Mon, 11 Jul 2011 10:14:53 +0200
Subject: [PATCH] Fix creation of reverse DNS zones.

Create reverse DNS zone for /24 IPv4 subnet and /64 IPv6 subnet by
default instead of using the netmask from the --ip-address option.

Custom reverse DNS zone can be specified using new --reverse-zone
option, which replaces the old --ip-address netmask way of creating
reverse zones.

The reverse DNS zone name is printed to the user during the install.

ticket 1398
---
 install/tools/ipa-dns-install           |   50 +++++++-----
 install/tools/ipa-replica-install       |   40 ++++++----
 install/tools/ipa-replica-prepare       |   53 +++++++------
 install/tools/ipa-server-install        |   36 +++++----
 install/tools/man/ipa-dns-install.1     |    3 +
 install/tools/man/ipa-replica-install.1 |    3 +
 install/tools/man/ipa-replica-prepare.1 |    6 ++
 install/tools/man/ipa-server-install.1  |    3 +
 ipaserver/install/bindinstance.py       |  126 +++++++++++++++++++------------
 9 files changed, 196 insertions(+), 124 deletions(-)

diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index b5295b5..eb1336e 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -38,14 +38,14 @@ def parse_options():
     parser.add_option("-d", "--debug", dest="debug", action="store_true",
                       default=False, help="print debugging information")
     parser.add_option("--ip-address", dest="ip_address",
-                      type="ip", ip_netmask=True, ip_local=True, help="Master Server IP Address")
+                      type="ip", ip_local=True, help="Master Server IP Address")
     parser.add_option("--forwarder", dest="forwarders", action="append",
                       type="ip", help="Add a DNS forwarder")
     parser.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
                       default=False, help="Do not add any DNS forwarders, use root servers instead")
-    parser.add_option("--no-reverse", dest="no_reverse",
-                      action="store_true", default=False,
-                      help="Do not create reverse DNS zone")
+    parser.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
+    parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
+                      default=False, help="Do not create reverse DNS zone")
     parser.add_option("--zonemgr", dest="zonemgr", 
                       help="DNS zone manager e-mail address. Defaults to root")
     parser.add_option("-U", "--unattended", dest="unattended", action="store_true",
@@ -56,6 +56,8 @@ def parse_options():
 
     if options.forwarders and options.no_forwarders:
         parser.error("You cannot specify a --forwarder option together with --no-forwarders")
+    elif options.reverse_zone and options.no_reverse:
+        parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
 
     if options.unattended:
         if not options.forwarders and not options.no_forwarders:
@@ -104,26 +106,28 @@ def main():
 
     # Check we have a public IP that is associated with the hostname
     if options.ip_address:
-        ip_address = options.ip_address
+        ip = options.ip_address
     else:
         hostaddr = resolve_host(api.env.host)
-        ip_address = hostaddr and ipautil.CheckedIPAddress(hostaddr)
+        ip = hostaddr and ipautil.CheckedIPAddress(hostaddr)
 
     try:
-        verify_ip_address(ip_address)
+        verify_ip_address(ip)
     except Exception, e:
-        print "Error: Invalid IP Address %s: %s" % (ip_address, e)
-        ip_address = None
+        print "Error: Invalid IP Address %s: %s" % (ip, e)
+        ip = None
 
-    if not ip_address:
+    if not ip:
         if options.unattended:
             sys.exit("Unable to resolve IP address for host name")
         else:
-            ip_address = read_ip_address(api.env.host, fstore)
-    ip_prefixlen = ip_address.prefixlen
-    ip_address = str(ip_address)
+            ip = read_ip_address(api.env.host, fstore)
+    ip_address = str(ip)
     logging.debug("will use ip_address: %s\n", ip_address)
 
+    if options.reverse_zone and not bindinstance.verify_reverse_zone(options.reverse_zone, ip):
+        sys.exit(1)
+
     if options.no_forwarders:
         dns_forwarders = ()
     elif options.forwarders:
@@ -161,13 +165,6 @@ def main():
                 sys.exit("\nPassword is not valid!")
             bind.dm_password = read_password("Directory Manager", confirm=False, validate=False)
 
-    create_reverse = True
-    if options.unattended:
-        create_reverse = not options.no_reverse
-    elif not options.no_reverse:
-        create_reverse = bindinstance.create_reverse()
-    bind.setup(api.env.host, ip_address, ip_prefixlen, api.env.realm, api.env.domain, dns_forwarders, conf_ntp, create_reverse, zonemgr=options.zonemgr)
-
     if bind.dm_password:
         api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=bind.dm_password)
     else:
@@ -175,6 +172,19 @@ def main():
         ccache = krbV.default_context().default_ccache().name
         api.Backend.ldap2.connect(ccache)
 
+    if options.reverse_zone:
+        reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
+    else:
+        reverse_zone = bindinstance.find_reverse_zone(ip)
+        if reverse_zone is None and not options.no_reverse:
+            reverse_zone = bindinstance.get_reverse_zone_default(ip)
+            if not options.unattended and bindinstance.create_reverse():
+                reverse_zone = bindinstance.read_reverse_zone(reverse_zone, ip)
+
+    if reverse_zone is not None:
+        print "Using reverse zone %s" % reverse_zone
+
+    bind.setup(api.env.host, ip_address, api.env.realm, api.env.domain, dns_forwarders, conf_ntp, reverse_zone, zonemgr=options.zonemgr)
     bind.create_instance()
 
 
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 7daa0e8..d499754 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -59,6 +59,7 @@ def parse_options():
                       type="ip", help="Add a DNS forwarder")
     parser.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
                       default=False, help="Do not add any DNS forwarders, use root servers instead")
+    parser.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
     parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
                       default=False, help="Do not create reverse DNS zone")
     parser.add_option("--no-host-dns", dest="no_host_dns", action="store_true",
@@ -84,12 +85,16 @@ def parse_options():
             parser.error("You cannot specify a --forwarder option without the --setup-dns option")
         if options.no_forwarders:
             parser.error("You cannot specify a --no-forwarders option without the --setup-dns option")
+        if options.reverse_zone:
+            parser.error("You cannot specify a --reverse-zone option without the --setup-dns option")
         if options.no_reverse:
             parser.error("You cannot specify a --no-reverse option without the --setup-dns option")
     elif options.forwarders and options.no_forwarders:
         parser.error("You cannot specify a --forwarder option together with --no-forwarders")
     elif not options.forwarders and not options.no_forwarders:
         parser.error("You must specify at least one --forwarder option or --no-forwarders option")
+    elif options.reverse_zone and options.no_reverse:
+        parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
 
     return safe_options, options, args[0]
 
@@ -183,22 +188,23 @@ def install_bind(config, options):
         sys.exit("Unable to resolve IP address for host name")
     ip = installutils.parse_ip_address(ip_address)
     ip_address = str(ip)
-    ip_prefixlen = ip.prefixlen
 
-    create_reverse = True
-    if options.unattended:
-        # In unattended mode just use the cmdline flag
-        create_reverse = not options.no_reverse
+    if options.reverse_zone:
+        if not bindinstance.verify_reverse_zone(options.reverse_zone, ip):
+            sys.exit(1)
+        reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
     else:
-        if options.no_reverse:
-            create_reverse = False
-        else:
-            # In interactive mode, if the flag was not explicitly 
-            # specified, ask the user
-            create_reverse = bindinstance.create_reverse()
-
-    bind.setup(config.host_name, ip_address, ip_prefixlen, config.realm_name,
-               config.domain_name, forwarders, options.conf_ntp, create_reverse)
+        reverse_zone = bindinstance.find_reverse_zone(ip)
+        if reverse_zone is None and not options.no_reverse:
+            reverse_zone = bindinstance.get_reverse_zone_default(ip)
+            if not options.unattended and bindinstance.create_reverse():
+                reverse_zone = bindinstance.read_reverse_zone(reverse_zone, ip)
+
+    if reverse_zone is not None:
+        print "Using reverse zone %s" % reverse_zone
+
+    bind.setup(config.host_name, ip_address, config.realm_name,
+               config.domain_name, forwarders, options.conf_ntp, reverse_zone)
     bind.create_instance()
 
 def install_dns_records(config, options):
@@ -221,11 +227,11 @@ def install_dns_records(config, options):
         sys.exit("Unable to resolve IP address for host name")
     ip = installutils.parse_ip_address(ip_address)
     ip_address = str(ip)
-    ip_prefixlen = ip.prefixlen
+    reverse_zone = bindinstance.find_reverse_zone(ip)
 
-    bind.add_master_dns_records(config.host_name, ip_address, ip_prefixlen,
+    bind.add_master_dns_records(config.host_name, ip_address,
                                 config.realm_name, config.domain_name,
-                                options.conf_ntp)
+                                reverse_zone, options.conf_ntp)
 
     #set it back to the default
     api.Backend.ldap2.disconnect()
diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare
index 97dd96a..cb27948 100755
--- a/install/tools/ipa-replica-prepare
+++ b/install/tools/ipa-replica-prepare
@@ -27,7 +27,7 @@ import krbV
 
 from ipapython import ipautil
 from ipaserver.install import bindinstance, dsinstance, installutils, certs
-from ipaserver.install.bindinstance import add_zone, add_reverse_zone, add_fwd_rr, add_ptr_rr, dns_zone_exists
+from ipaserver.install.bindinstance import add_zone, add_reverse_zone, add_fwd_rr, add_ptr_rr
 from ipaserver.install.replication import check_replication_plugin, enable_replication_version_checking
 from ipaserver.install.installutils import resolve_host
 from ipaserver.plugins.ldap2 import ldap2
@@ -54,8 +54,11 @@ def parse_options():
     parser.add_option("-p", "--password", dest="password", 
                       help="Directory Manager (existing master) password")
     parser.add_option("--ip-address", dest="ip_address",
-                      type="ip", ip_netmask=True,
-                      help="Add A and PTR records of the future replica")
+                      type="ip", help="Add A and PTR records of the future replica")
+    parser.add_option("--reverse-zone", dest="reverse_zone",
+                      help="The reverse DNS zone to use")
+    parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
+                      default=False, help="Do not create reverse DNS zone")
     parser.add_option("--ca", dest="ca_file", default="/root/cacert.p12",
                       help="Location of CA PKCS#12 file, default /root/cacert.p12")
     parser.add_option("--no-pkinit", dest="setup_pkinit", action="store_false",
@@ -63,6 +66,14 @@ def parse_options():
 
     options, args = parser.parse_args()
 
+    if not options.ip_address:
+        if options.reverse_zone:
+            parser.error("You cannot specify a --reverse-zone option without the --ip-address option")
+        if options.no_reverse:
+            parser.error("You cannot specify a --no-reverse option without the --ip-address option")
+    elif options.reverse_zone and options.no_reverse:
+        parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
+
     # If any of the PKCS#12 options are selected, all are required. Create a
     # list of the options and count it to enforce that all are required without
     # having a huge set of it blocks.
@@ -255,6 +266,8 @@ def main():
         if not bindinstance.dns_container_exists(api.env.host, api.env.basedn):
             print "You can't add a DNS record because DNS is not set up."
             sys.exit(1)
+        if options.reverse_zone and not bindinstance.verify_reverse_zone(options.reverse_zone, options.ip_address):
+            sys.exit(1)
 
     if not certs.ipa_self_signed() and not ipautil.file_exists("/var/lib/pki-ca/conf/CS.cfg") and not options.dirsrv_pin:
         sys.exit("The replica must be created on the primary IPA server.\nIf you installed IPA with your own certificates using PKCS#12 files you must provide PKCS#12 files for any replicas you create as well.")
@@ -424,31 +437,21 @@ def main():
 
         ip = options.ip_address
         ip_address = str(ip)
-        ip_prefixlen = ip.prefixlen
-
-        if ip.defaultnet:
-            revzone = ip.reverse_dns
-            if ip.version == 4:
-                prefix = 32
-                dec = 8
-            elif ip.version == 6:
-                prefix = 128
-                dec = 4
-
-            while prefix > 0:
-                dummy, dot, revzone = revzone.partition('.')
-                prefix = prefix - dec
-                if dns_zone_exists(revzone):
-                    break
-
-            if prefix > 0:
-                ip_prefixlen = prefix
-            else:
-                add_reverse_zone(ip_address, ip_prefixlen)
+
+        if options.reverse_zone:
+            reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
+        else:
+            reverse_zone = bindinstance.find_reverse_zone(ip)
+            if reverse_zone is None and not options.no_reverse:
+                reverse_zone = bindinstance.get_reverse_zone_default(ip)
 
         add_zone(domain)
         add_fwd_rr(domain, name, ip_address)
-        add_ptr_rr(ip_address, ip_prefixlen, replica_fqdn)
+
+        if reverse_zone is not None:
+            print "Using reverse zone %s" % reverse_zone
+            add_reverse_zone(reverse_zone)
+            add_ptr_rr(reverse_zone, ip_address, replica_fqdn)
 
 try:
     if not os.geteuid()==0:
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 504da2c..35b16da 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -100,7 +100,7 @@ def parse_options():
                       help="File containing PKCS#10 of the external CA chain")
     parser.add_option("--hostname", dest="host_name", help="fully qualified name of server")
     parser.add_option("--ip-address", dest="ip_address",
-                      type="ip", ip_netmask=True, ip_local=True,
+                      type="ip", ip_local=True,
                       help="Master Server IP Address")
     parser.add_option("--setup-dns", dest="setup_dns", action="store_true",
                       default=False, help="configure bind with our zone")
@@ -108,6 +108,7 @@ def parse_options():
                       type="ip", help="Add a DNS forwarder")
     parser.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
                       default=False, help="Do not add any DNS forwarders, use root servers instead")
+    parser.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
     parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
                       default=False, help="Do not create reverse DNS zone")
     parser.add_option("--zonemgr", action="callback", callback=zonemgr_callback,
@@ -154,10 +155,14 @@ def parse_options():
             parser.error("You cannot specify a --forwarder option without the --setup-dns option")
         if options.no_forwarders:
             parser.error("You cannot specify a --no-forwarders option without the --setup-dns option")
+        if options.reverse_zone:
+            parser.error("You cannot specify a --reverse-zone option without the --setup-dns option")
         if options.no_reverse:
             parser.error("You cannot specify a --no-reverse option without the --setup-dns option")
     elif options.forwarders and options.no_forwarders:
         parser.error("You cannot specify a --forwarder option together with --no-forwarders")
+    elif options.reverse_zone and options.no_reverse:
+        parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
 
     if options.uninstall:
         if (options.realm_name or
@@ -552,7 +557,7 @@ def main():
     master_password = ""
     dm_password = ""
     admin_password = ""
-    create_reverse = True
+    reverse_zone = None
 
     # check bind packages are installed
     if options.setup_dns:
@@ -631,7 +636,9 @@ def main():
         ip = read_ip_address(host_name, fstore)
         logging.debug("read ip_address: %s\n" % str(ip))
     ip_address = str(ip)
-    ip_prefixlen = ip.prefixlen
+
+    if options.reverse_zone and not bindinstance.verify_reverse_zone(options.reverse_zone, ip):
+        sys.exit(1)
 
     print "The IPA Master Server will be configured with"
     print "Hostname:    " + host_name
@@ -896,18 +903,17 @@ def main():
     # Create a BIND instance
     bind = bindinstance.BindInstance(fstore, dm_password)
     if options.setup_dns:
-        if options.unattended:
-            # In unattended mode just use the cmdline flag
-            create_reverse = not options.no_reverse
-        else:
-            if options.no_reverse:
-                create_reverse = False
-            else:
-                # In interactive mode, if the flag was not explicitly
-                # specified, ask the user
-                create_reverse = bindinstance.create_reverse()
-
-    bind.setup(host_name, ip_address, ip_prefixlen, realm_name, domain_name, dns_forwarders, options.conf_ntp, create_reverse, zonemgr=options.zonemgr)
+        if options.reverse_zone:
+            reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
+        elif not options.no_reverse:
+            reverse_zone = bindinstance.get_reverse_zone_default(ip)
+            if not options.unattended and bindinstance.create_reverse():
+                reverse_zone = bindinstance.read_reverse_zone(reverse_zone, ip)
+
+        if reverse_zone is not None:
+            print "Using reverse zone %s" % reverse_zone
+
+    bind.setup(host_name, ip_address, realm_name, domain_name, dns_forwarders, options.conf_ntp, reverse_zone, zonemgr=options.zonemgr)
     if options.setup_dns:
         api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=dm_password)
 
diff --git a/install/tools/man/ipa-dns-install.1 b/install/tools/man/ipa-dns-install.1
index f6f99c1..e8c53bf 100644
--- a/install/tools/man/ipa-dns-install.1
+++ b/install/tools/man/ipa-dns-install.1
@@ -40,6 +40,9 @@ A forwarder is a DNS server where queries for a specific non\-resolvable address
 \fB\-\-no\-forwarders\fR
 Do not add any DNS forwarders, send non\-resolvable addresses to the DNS root servers.
 .TP
+\fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
+The reverse DNS zone to use
+.TP
 \fB\-\-no\-reverse\fR
 Do not create reverse DNS zone
 .TP
diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1
index 1dac5fa..1426d61 100644
--- a/install/tools/man/ipa-replica-install.1
+++ b/install/tools/man/ipa-replica-install.1
@@ -56,6 +56,9 @@ the \fB\-\-no\-forwarders\fR option is specified.
 \fB\-\-no\-forwarders\fR
 Do not add any DNS forwarders. Root DNS servers will be used instead.
 .TP
+\fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
+The reverse DNS zone to use
+.TP
 \fB\-\-no\-reverse\fR
 Do not create reverse DNS zone
 .TP
diff --git a/install/tools/man/ipa-replica-prepare.1 b/install/tools/man/ipa-replica-prepare.1
index 88da6f4..a8ebcc9 100644
--- a/install/tools/man/ipa-replica-prepare.1
+++ b/install/tools/man/ipa-replica-prepare.1
@@ -54,6 +54,12 @@ Directory Manager (existing master) password
 \fB\-\-ip\-address\fR=\fIIP_ADDRESS\fR
 IP address of the replica server. If you provide this option, the A and PTR records will be added to the DNS.
 .TP
+\fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
+The reverse DNS zone to use
+.TP
+\fB\-\-no\-reverse\fR
+Do not create reverse DNS zone
+.TP
 \fB\-\-ca\fR=\fICA_FILE\fR
 Location of CA PKCS#12 file, default /root/cacert.p12
 .TP
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index 40d86e7..7450ab9 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -79,6 +79,9 @@ the \fB\-\-no\-forwarders\fR option is specified.
 \fB\-\-no\-forwarders\fR
 Do not add any DNS forwarders. Root DNS servers will be used instead.
 .TP
+\fB\-\-reverse\-zone\fR=\fIREVERSE_ZONE\fR
+The reverse DNS zone to use
+.TP
 \fB\-\-no\-reverse\fR
 Do not create reverse DNS zone
 .TP
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 8981c2f..7aa8a26 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -60,6 +60,12 @@ def check_inst(unattended):
 
     return True
 
+def normalize_zone(zone):
+    if zone[-1] != '.':
+        return zone + '.'
+    else:
+        return zone
+
 def create_reverse():
     return ipautil.user_input("Do you want to configure the reverse zone?", True)
 
@@ -99,22 +105,6 @@ def dns_container_exists(fqdn, suffix):
 
     return ret
 
-def get_reverse_zone(ip_address_str, ip_prefixlen):
-    ip = netaddr.IPAddress(ip_address_str)
-    items = ip.reverse_dns.split('.')
-
-    if ip.version == 4:
-        pos = 4 - ip_prefixlen / 8
-    elif ip.version == 6:
-        pos = 32 - ip_prefixlen / 4
-    else:
-        raise ValueError('Bad address format?')
-
-    name = '.'.join(items[:pos])
-    zone = '.'.join(items[pos:])
-
-    return unicode(zone), unicode(name)
-
 def dns_zone_exists(name):
     try:
         zone = api.Command.dnszone_show(unicode(name))
@@ -126,6 +116,60 @@ def dns_zone_exists(name):
     else:
         return True
 
+def get_reverse_record_name(zone, ip_address):
+    ip = netaddr.IPAddress(ip_address)
+    rev = '.' + normalize_zone(zone)
+    fullrev = '.' + normalize_zone(ip.reverse_dns)
+
+    if not fullrev.endswith(rev):
+        raise ValueError("IP address does not match reverse zone")
+
+    return fullrev[1:-len(rev)]
+
+def verify_reverse_zone(zone, ip_address):
+    try:
+        get_reverse_record_name(zone, ip_address)
+    except ValueError:
+        print "Invalid reverse zone %s" % zone
+        return False
+
+    return True
+
+def get_reverse_zone_default(ip_address):
+    ip = netaddr.IPAddress(ip_address)
+    items = ip.reverse_dns.split('.')
+
+    if ip.version == 4:
+        items = items[1:]   # /24 for IPv4
+    elif ip.version == 6:
+        items = items[16:]  # /64 for IPv6
+
+    return normalize_zone('.'.join(items))
+
+def find_reverse_zone(ip_address):
+    ip = netaddr.IPAddress(ip_address)
+    zone = normalize_zone(ip.reverse_dns)
+
+    while len(zone) > 0:
+        if dns_zone_exists(zone):
+            return zone
+        foo, bar, zone = zone.partition('.')
+
+    return None
+
+def get_reverse_zone(ip_address):
+    return find_reverse_zone(ip_address) or get_reverse_zone_default(ip_address)
+
+def read_reverse_zone(default, ip_address):
+    while True:
+        zone = ipautil.user_input("Please specify the reverse zone name", default=default)
+        if not zone:
+            return None
+        if verify_reverse_zone(zone, ip_address):
+            break
+
+    return normalize_zone(zone)
+
 def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_address=None,
        update_policy=None):
     if update_policy is None:
@@ -158,9 +202,8 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres
         add_ns_rr(name, hostname, dns_backup=None, force=True)
 
 
-def add_reverse_zone(ip_address, ip_prefixlen, ns_hostname=None, ns_ip_address=None,
+def add_reverse_zone(zone, ns_hostname=None, ns_ip_address=None,
         ns_replicas=[], update_policy=None, dns_backup=None):
-    zone, name = get_reverse_zone(ip_address, ip_prefixlen)
     if update_policy is None:
         update_policy = "grant %s krb5-subdomain %s. PTR;" % (api.env.realm, zone)
 
@@ -207,8 +250,8 @@ def add_fwd_rr(zone, host, ip_address):
     elif addr.version == 6:
         add_rr(zone, host, "AAAA", ip_address)
 
-def add_ptr_rr(ip_address, ip_prefixlen, fqdn, dns_backup=None):
-    zone, name = get_reverse_zone(ip_address, ip_prefixlen)
+def add_ptr_rr(zone, ip_address, fqdn, dns_backup=None):
+    name = get_reverse_record_name(zone, ip_address)
     add_rr(zone, name, "PTR", fqdn+".", dns_backup)
 
 def add_ns_rr(zone, hostname, dns_backup=None, force=True):
@@ -288,22 +331,20 @@ class BindInstance(service.Service):
         self.domain = None
         self.host = None
         self.ip_address = None
-        self.ip_prefixlen = None
         self.realm = None
         self.forwarders = None
         self.sub_dict = None
-        self.create_reverse = True
+        self.reverse_zone = None
 
         if fstore:
             self.fstore = fstore
         else:
             self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
 
-    def setup(self, fqdn, ip_address, ip_prefixlen, realm_name, domain_name, forwarders, ntp, create_reverse, named_user="named", zonemgr=None):
+    def setup(self, fqdn, ip_address, realm_name, domain_name, forwarders, ntp, reverse_zone, named_user="named", zonemgr=None):
         self.named_user = named_user
         self.fqdn = fqdn
         self.ip_address = ip_address
-        self.ip_prefixlen = ip_prefixlen
         self.realm = realm_name
         self.domain = domain_name
         self.forwarders = forwarders
@@ -311,7 +352,7 @@ class BindInstance(service.Service):
         self.host_domain = '.'.join(fqdn.split(".")[1:])
         self.suffix = util.realm_to_suffix(self.realm)
         self.ntp = ntp
-        self.create_reverse = create_reverse
+        self.reverse_zone = reverse_zone
 
         if zonemgr:
             self.zonemgr = zonemgr.replace('@','.')
@@ -346,7 +387,7 @@ class BindInstance(service.Service):
             self.step("adding NS record to the zone", self.__add_self_ns)
         else:
             self.step("setting up our zone", self.__setup_zone)
-        if self.create_reverse:
+        if self.reverse_zone is not None:
             self.step("setting up reverse zone", self.__setup_reverse_zone)
         self.step("setting up our own record", self.__add_self)
 
@@ -440,11 +481,11 @@ class BindInstance(service.Service):
 
         # Add forward and reverse records to self
         add_fwd_rr(zone, self.host, self.ip_address)
-        if dns_zone_exists(get_reverse_zone(self.ip_address, self.ip_prefixlen)[0]):
-            add_ptr_rr(self.ip_address, self.ip_prefixlen, self.fqdn)
+        if self.reverse_zone is not None and dns_zone_exists(self.reverse_zone):
+            add_ptr_rr(self.reverse_zone, self.ip_address, self.fqdn)
 
     def __setup_reverse_zone(self):
-        add_reverse_zone(self.ip_address, self.ip_prefixlen, ns_hostname=api.env.host,
+        add_reverse_zone(self.reverse_zone, ns_hostname=api.env.host,
                 ns_ip_address=self.ip_address, dns_backup=self.dns_backup)
 
     def __setup_principal(self):
@@ -501,16 +542,16 @@ class BindInstance(service.Service):
         resolv_fd.write(resolv_txt)
         resolv_fd.close()
 
-    def add_master_dns_records(self, fqdn, ip_address, ip_prefixlen,
-                               realm_name, domain_name, ntp=False):
+    def add_master_dns_records(self, fqdn, ip_address, realm_name, domain_name,
+                               reverse_zone, ntp=False):
         self.fqdn = fqdn
         self.ip_address = ip_address
-        self.ip_prefixlen = ip_prefixlen
         self.realm = realm_name
         self.domain = domain_name
         self.host = fqdn.split(".")[0]
         self.suffix = util.realm_to_suffix(self.realm)
         self.ntp = ntp
+        self.reverse_zone = reverse_zone
 
         self.__add_self()
 
@@ -538,21 +579,12 @@ class BindInstance(service.Service):
         for (type, rdata) in areclist:
             del_rr(zone, host, type, rdata)
 
-            ip = netaddr.IPAddress(rdata)
-            rzone = ip.reverse_dns
-            record = ''
-
-            while True:
-                part, dot, rzone = rzone.partition('.')
-                if len(rzone) == 0:
-                    break
-                record = (record + '.' + part).lstrip('.')
-
-                if dns_zone_exists(rzone):
-                    del_rr(rzone, record, "PTR", fqdn+".")
-                    # remove also master NS record from the reverse zone
-                    del_rr(rzone, "@", "NS", fqdn+".")
-                    break
+            rzone = find_reverse_zone(rdata)
+            if rzone is not None:
+                record = get_reverse_record_name(rzone, rdata)
+                del_rr(rzone, record, "PTR", fqdn+".")
+                # remove also master NS record from the reverse zone
+                del_rr(rzone, "@", "NS", fqdn+".")
 
 
     def uninstall(self):
-- 
1.7.4.4

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to