summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xinstall/tools/ipa-dns-install21
-rwxr-xr-xinstall/tools/ipa-replica-conncheck2
-rwxr-xr-xinstall/tools/ipa-replica-install29
-rw-r--r--ipapython/dnsclient.py78
-rw-r--r--ipaserver/install/bindinstance.py16
-rw-r--r--ipaserver/install/installutils.py66
6 files changed, 138 insertions, 74 deletions
diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index 5c02c20c0..98929bdc3 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -147,7 +147,26 @@ def main():
else:
hostaddr = resolve_host(api.env.host)
try:
- ip = hostaddr and ipautil.CheckedIPAddress(hostaddr, match_local=True)
+ if len(hostaddr) > 1:
+ print >> sys.stderr, "The server hostname resolves to more than one address:"
+ for addr in hostaddr:
+ print >> sys.stderr, " %s" % addr
+
+ if options.ip_address:
+ if str(options.ip_address) not in hostaddr:
+ print >> sys.stderr, "Address passed in --ip-address did not match any resolved"
+ print >> sys.stderr, "address!"
+ sys.exit(1)
+ print "Selected IP address:", str(options.ip_address)
+ ip = options.ip_address
+ else:
+ if options.unattended:
+ print >> sys.stderr, "Please use --ip-address option to specify the address"
+ sys.exit(1)
+ else:
+ ip = read_ip_address(api.env.host, fstore)
+ else:
+ ip = hostaddr and ipautil.CheckedIPAddress(hostaddr[0], match_local=True)
except Exception, e:
print "Error: Invalid IP Address %s: %s" % (ip, e)
ip = None
diff --git a/install/tools/ipa-replica-conncheck b/install/tools/ipa-replica-conncheck
index 882d77d30..2622130e7 100755
--- a/install/tools/ipa-replica-conncheck
+++ b/install/tools/ipa-replica-conncheck
@@ -237,7 +237,7 @@ class PortResponder(threading.Thread):
def port_check(host, port_list):
ip = installutils.resolve_host(host)
- if ip is None:
+ if not ip:
raise RuntimeError("Port check failed! Unable to resolve host name '%s'" % host)
failed_ports = []
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 34c787b19..c1474ecbf 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -200,27 +200,22 @@ def install_bind(config, options):
else:
forwarders = ()
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
- ip_address = resolve_host(config.host_name)
- if not ip_address:
- sys.exit("Unable to resolve IP address for host name")
- ip = ipautil.CheckedIPAddress(ip_address, match_local=True)
- ip_address = str(ip)
if options.reverse_zone:
- if not bindinstance.verify_reverse_zone(options.reverse_zone, ip):
+ if not bindinstance.verify_reverse_zone(options.reverse_zone, config.ip):
sys.exit(1)
reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
else:
- reverse_zone = bindinstance.find_reverse_zone(ip)
+ reverse_zone = bindinstance.find_reverse_zone(config.ip)
if reverse_zone is None and not options.no_reverse:
- reverse_zone = bindinstance.get_reverse_zone_default(ip)
+ reverse_zone = bindinstance.get_reverse_zone_default(config.ip)
if not options.unattended and bindinstance.create_reverse():
- reverse_zone = bindinstance.read_reverse_zone(reverse_zone, ip)
+ reverse_zone = bindinstance.read_reverse_zone(reverse_zone, config.ip)
if reverse_zone is not None:
print "Using reverse zone %s" % reverse_zone
- bind.setup(config.host_name, ip_address, config.realm_name,
+ bind.setup(config.host_name, config.ip_address, config.realm_name,
config.domain_name, forwarders, options.conf_ntp, reverse_zone)
bind.create_instance()
@@ -240,14 +235,9 @@ def install_dns_records(config, options):
bind_pw=config.dirman_password,
tls_cacertfile=CACERT)
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
- ip_address = resolve_host(config.host_name)
- if not ip_address:
- sys.exit("Unable to resolve IP address for host name")
- ip = ipautil.CheckedIPAddress(ip_address, match_local=True)
- ip_address = str(ip)
- reverse_zone = bindinstance.find_reverse_zone(ip)
-
- bind.add_master_dns_records(config.host_name, ip_address,
+ reverse_zone = bindinstance.find_reverse_zone(config.ip)
+
+ bind.add_master_dns_records(config.host_name, config.ip_address,
config.realm_name, config.domain_name,
reverse_zone, options.conf_ntp)
@@ -341,7 +331,8 @@ def main():
replica_conn_check(config.master_host_name, config.host_name, config.realm_name, options.setup_ca, options.admin_password)
# check replica host IP resolution
- ip = installutils.get_server_ip_address(config.host_name, fstore, True, options)
+ config.ip = installutils.get_server_ip_address(config.host_name, fstore, True, options)
+ config.ip_address = str(config.ip)
# Create the management framework config file
# Note: We must do this before bootstraping and finalizing ipalib.api
diff --git a/ipapython/dnsclient.py b/ipapython/dnsclient.py
index 9a59d9b99..3f08866a6 100644
--- a/ipapython/dnsclient.py
+++ b/ipapython/dnsclient.py
@@ -40,6 +40,11 @@ DNS_T_AAAA = 28
DNS_T_SRV = 33
DNS_T_ANY = 255
+DNS_S_QUERY = 1
+DNS_S_ANSWER = 2
+DNS_S_AUTHORITY = 3
+DNS_S_ADDITIONAL = 4
+
DEBUG_DNSCLIENT = False
class DNSQueryHeader:
@@ -105,6 +110,7 @@ class DNSResult:
self.dns_ttl = 0
self.dns_rlength = 0
self.rdata = None
+ self.section = None
def unpack(self, data):
(self.dns_type, self.dns_class, self.dns_ttl,
@@ -398,47 +404,51 @@ def dnsParseResults(results):
print "Queried for '%s', class = %d, type = %d." % (label,
qq.dns_class, qq.dns_type)
- for i in xrange(header.dns_ancount + header.dns_nscount + header.dns_arcount):
- (rest, label) = dnsParseLabel(rest, results)
- if label is None:
- return []
+ for (rec_count, section_id) in ((header.dns_ancount, DNS_S_ANSWER),
+ (header.dns_nscount, DNS_S_AUTHORITY),
+ (header.dns_arcount, DNS_S_ADDITIONAL)):
+ for i in xrange(rec_count):
+ (rest, label) = dnsParseLabel(rest, results)
+ if label is None:
+ return []
- rr = DNSResult()
+ rr = DNSResult()
- rr.dns_name = label
+ rr.dns_name = label
+ rr.section = section_id
- if len(rest) < rr.size():
- return []
+ if len(rest) < rr.size():
+ return []
- rr.unpack(rest)
-
- rest = rest[rr.size():]
+ rr.unpack(rest)
- if DEBUG_DNSCLIENT:
- print "Answer %d for '%s', class = %d, type = %d, ttl = %d." % (i,
- rr.dns_name, rr.dns_class, rr.dns_type,
- rr.dns_ttl)
+ rest = rest[rr.size():]
- if len(rest) < rr.dns_rlength:
if DEBUG_DNSCLIENT:
- print "Answer too short."
- return []
-
- fmap = { DNS_T_A: dnsParseA, DNS_T_NS: dnsParseNS,
- DNS_T_CNAME: dnsParseCNAME, DNS_T_SOA: dnsParseSOA,
- DNS_T_NULL: dnsParseNULL, DNS_T_WKS: dnsParseWKS,
- DNS_T_PTR: dnsParsePTR, DNS_T_HINFO: dnsParseHINFO,
- DNS_T_MX: dnsParseMX, DNS_T_TXT: dnsParseTXT,
- DNS_T_AAAA : dnsParseAAAA, DNS_T_SRV: dnsParseSRV}
-
- if not rr.dns_type in fmap:
- if DEBUG_DNSCLIENT:
- print "Don't know how to parse RR type %d!" % rr.dns_type
- else:
- rr.rdata = fmap[rr.dns_type](rest[:rr.dns_rlength], results)
-
- rest = rest[rr.dns_rlength:]
- rrlist += [rr]
+ print "Answer %d for '%s', class = %d, type = %d, ttl = %d." % (i,
+ rr.dns_name, rr.dns_class, rr.dns_type,
+ rr.dns_ttl)
+
+ if len(rest) < rr.dns_rlength:
+ if DEBUG_DNSCLIENT:
+ print "Answer too short."
+ return []
+
+ fmap = { DNS_T_A: dnsParseA, DNS_T_NS: dnsParseNS,
+ DNS_T_CNAME: dnsParseCNAME, DNS_T_SOA: dnsParseSOA,
+ DNS_T_NULL: dnsParseNULL, DNS_T_WKS: dnsParseWKS,
+ DNS_T_PTR: dnsParsePTR, DNS_T_HINFO: dnsParseHINFO,
+ DNS_T_MX: dnsParseMX, DNS_T_TXT: dnsParseTXT,
+ DNS_T_AAAA : dnsParseAAAA, DNS_T_SRV: dnsParseSRV}
+
+ if not rr.dns_type in fmap:
+ if DEBUG_DNSCLIENT:
+ print "Don't know how to parse RR type %d!" % rr.dns_type
+ else:
+ rr.rdata = fmap[rr.dns_type](rest[:rr.dns_rlength], results)
+
+ rest = rest[rr.dns_rlength:]
+ rrlist += [rr]
return rrlist
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index c7e382822..6e6c94111 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -197,7 +197,13 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres
raise errors.NotFound("No IPA server with DNS support found!")
ns_main = dns_masters.pop(0)
ns_replicas = dns_masters
- ns_ip_address = resolve_host(ns_main)
+ addresses = resolve_host(ns_main)
+
+ if len(addresses) > 0:
+ # use the first address
+ ns_ip_address = addresses[0]
+ else:
+ ns_ip_address = None
else:
ns_main = ns_hostname
ns_replicas = []
@@ -230,7 +236,13 @@ def add_reverse_zone(zone, ns_hostname=None, ns_ip_address=None,
raise errors.NotFound("No IPA server with DNS support found!")
ns_main = dns_masters.pop(0)
ns_replicas = dns_masters
- ns_ip_address = resolve_host(ns_main)
+ addresses = resolve_host(ns_main)
+
+ if len(addresses) > 0:
+ # use the first address
+ ns_ip_address = addresses[0]
+ else:
+ ns_ip_address = None
else:
ns_main = ns_hostname
ns_replicas = []
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index e2cabf69b..94c1fabfb 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -90,27 +90,35 @@ def verify_dns_records(host_name, responses, resaddr, family):
if family not in familykw.keys():
raise RuntimeError("Unknown faimily %s\n" % family)
- rec = None
+ rec_list = []
for rsn in responses:
- if rsn.dns_type == familykw[family]['dns_type']:
- rec = rsn
- break
+ if rsn.section == dnsclient.DNS_S_ANSWER and \
+ rsn.dns_type == familykw[family]['dns_type']:
+ rec_list.append(rsn)
- if rec == None:
+ if not rec_list:
raise IOError(errno.ENOENT,
"Warning: Hostname (%s) not found in DNS" % host_name)
if family == 'ipv4':
- familykw[family]['address'] = socket.inet_ntop(socket.AF_INET,
- struct.pack('!L',rec.rdata.address))
+ familykw[family]['address'] = [socket.inet_ntop(socket.AF_INET,
+ struct.pack('!L',rec.rdata.address)) \
+ for rec in rec_list]
else:
- familykw[family]['address'] = socket.inet_ntop(socket.AF_INET6,
- struct.pack('!16B', *rec.rdata.address))
+ familykw[family]['address'] = [socket.inet_ntop(socket.AF_INET6,
+ struct.pack('!16B', *rec.rdata.address)) \
+ for rec in rec_list]
# Check that DNS address is the same is address returned via standard glibc calls
- dns_addr = netaddr.IPAddress(familykw[family]['address'])
- if dns_addr.format() != resaddr:
- raise RuntimeError("The network address %s does not match the DNS lookup %s. Check /etc/hosts and ensure that %s is the IP address for %s" % (dns_addr.format(), resaddr, dns_addr.format(), host_name))
+ dns_addrs = [netaddr.IPAddress(addr) for addr in familykw[family]['address']]
+ dns_addr = None
+ for addr in dns_addrs:
+ if addr.format() == resaddr:
+ dns_addr = addr
+ break
+
+ if dns_addr is None:
+ raise RuntimeError("Host address %s does not match any address in DNS lookup." % resaddr)
rs = dnsclient.query(dns_addr.reverse_dns, dnsclient.DNS_C_IN, dnsclient.DNS_T_PTR)
if len(rs) == 0:
@@ -498,14 +506,19 @@ def resolve_host(host_name):
try:
addrinfos = socket.getaddrinfo(host_name, None,
socket.AF_UNSPEC, socket.SOCK_STREAM)
+
+ ip_list = []
+
for ai in addrinfos:
ip = ai[4][0]
if ip == "127.0.0.1" or ip == "::1":
raise HostnameLocalhost("The hostname resolves to the localhost address")
- return addrinfos[0][4][0]
- except:
- return None
+ ip_list.append(ip)
+
+ return ip_list
+ except socket.error:
+ return []
def get_host_name(no_host_dns):
"""
@@ -534,8 +547,27 @@ def get_server_ip_address(host_name, fstore, unattended, options):
sys.exit(1)
ip_add_to_hosts = False
- if hostaddr is not None:
- ip = ipautil.CheckedIPAddress(hostaddr, match_local=True)
+
+ if len(hostaddr) > 1:
+ print >> sys.stderr, "The server hostname resolves to more than one address:"
+ for addr in hostaddr:
+ print >> sys.stderr, " %s" % addr
+
+ if options.ip_address:
+ if str(options.ip_address) not in hostaddr:
+ print >> sys.stderr, "Address passed in --ip-address did not match any resolved"
+ print >> sys.stderr, "address!"
+ sys.exit(1)
+ print "Selected IP address:", str(options.ip_address)
+ ip = options.ip_address
+ else:
+ if unattended:
+ print >> sys.stderr, "Please use --ip-address option to specify the address"
+ sys.exit(1)
+ else:
+ ip = read_ip_address(host_name, fstore)
+ elif len(hostaddr) == 1:
+ ip = ipautil.CheckedIPAddress(hostaddr[0], match_local=True)
else:
# hostname is not resolvable
ip = options.ip_address