Make the use of IPv6 configurable.
Set self.use_ipv6 = False before connecting. Fixes issue #175
This commit is contained in:
parent
36c11ad9de
commit
e86444e5fb
2 changed files with 32 additions and 19 deletions
|
@ -52,7 +52,8 @@ def default_resolver():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def resolve(host, port=None, service=None, proto='tcp', resolver=None):
|
def resolve(host, port=None, service=None, proto='tcp',
|
||||||
|
resolver=None, use_ipv6=True):
|
||||||
"""Peform DNS resolution for a given hostname.
|
"""Peform DNS resolution for a given hostname.
|
||||||
|
|
||||||
Resolution may perform SRV record lookups if a service and protocol
|
Resolution may perform SRV record lookups if a service and protocol
|
||||||
|
@ -73,16 +74,23 @@ def resolve(host, port=None, service=None, proto='tcp', resolver=None):
|
||||||
:param proto: Optional SRV protocol name without leading underscore.
|
:param proto: Optional SRV protocol name without leading underscore.
|
||||||
:param resolver: Optionally provide a DNS resolver object that has
|
:param resolver: Optionally provide a DNS resolver object that has
|
||||||
been custom configured.
|
been custom configured.
|
||||||
|
:param use_ipv6: Optionally control the use of IPv6 in situations
|
||||||
|
where it is either not available, or performance
|
||||||
|
is degraded. Defaults to ``True``.
|
||||||
|
|
||||||
:type host: string
|
:type host: string
|
||||||
:type port: int
|
:type port: int
|
||||||
:type service: string
|
:type service: string
|
||||||
:type proto: string
|
:type proto: string
|
||||||
:type resolver: :class:`dns.resolver.Resolver`
|
:type resolver: :class:`dns.resolver.Resolver`
|
||||||
|
:type use_ipv6: bool
|
||||||
|
|
||||||
:return: An iterable of IP address, port pairs in the order
|
:return: An iterable of IP address, port pairs in the order
|
||||||
dictated by SRV priorities and weights, if applicable.
|
dictated by SRV priorities and weights, if applicable.
|
||||||
"""
|
"""
|
||||||
|
if not use_ipv6:
|
||||||
|
log.debug("DNS: Use of IPv6 has been disabled.")
|
||||||
|
|
||||||
if resolver is None and USE_DNSPYTHON:
|
if resolver is None and USE_DNSPYTHON:
|
||||||
resolver = dns.resolver.get_default_resolver()
|
resolver = dns.resolver.get_default_resolver()
|
||||||
|
|
||||||
|
@ -98,13 +106,15 @@ def resolve(host, port=None, service=None, proto='tcp', resolver=None):
|
||||||
except socket.error:
|
except socket.error:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
if use_ipv6:
|
||||||
# Likewise, If `host` is an IPv6 literal, we can return it immediately.
|
try:
|
||||||
if hasattr(socket, 'inet_pton'):
|
# Likewise, If `host` is an IPv6 literal, we can return
|
||||||
ipv6 = socket.inet_pton(socket.AF_INET6, host)
|
# it immediately.
|
||||||
yield (host, port)
|
if hasattr(socket, 'inet_pton'):
|
||||||
except socket.error:
|
ipv6 = socket.inet_pton(socket.AF_INET6, host)
|
||||||
pass
|
yield (host, port)
|
||||||
|
except socket.error:
|
||||||
|
pass
|
||||||
|
|
||||||
# If no service was provided, then we can just do A/AAAA lookups on the
|
# If no service was provided, then we can just do A/AAAA lookups on the
|
||||||
# provided host. Otherwise we need to get an ordered list of hosts to
|
# provided host. Otherwise we need to get an ordered list of hosts to
|
||||||
|
@ -117,10 +127,12 @@ def resolve(host, port=None, service=None, proto='tcp', resolver=None):
|
||||||
for host, port in hosts:
|
for host, port in hosts:
|
||||||
results = []
|
results = []
|
||||||
if host == 'localhost':
|
if host == 'localhost':
|
||||||
results.append(('::1', port))
|
if use_ipv6:
|
||||||
|
results.append(('::1', port))
|
||||||
results.append(('127.0.0.1', port))
|
results.append(('127.0.0.1', port))
|
||||||
for address in get_AAAA(host, resolver=resolver):
|
if use_ipv6:
|
||||||
results.append((address, port))
|
for address in get_AAAA(host, resolver=resolver):
|
||||||
|
results.append((address, port))
|
||||||
for address in get_A(host, resolver=resolver):
|
for address in get_A(host, resolver=resolver):
|
||||||
results.append((address, port))
|
results.append((address, port))
|
||||||
|
|
||||||
|
@ -160,13 +172,13 @@ def get_A(host, resolver=None):
|
||||||
recs = resolver.query(host, dns.rdatatype.A)
|
recs = resolver.query(host, dns.rdatatype.A)
|
||||||
return [rec.to_text() for rec in recs]
|
return [rec.to_text() for rec in recs]
|
||||||
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
||||||
log.debug("DNS: No A records for %s." % host)
|
log.debug("DNS: No A records for %s" % host)
|
||||||
return []
|
return []
|
||||||
except dns.exception.Timeout:
|
except dns.exception.Timeout:
|
||||||
log.debug("DNS: A record resolution timed out for %s." % host)
|
log.debug("DNS: A record resolution timed out for %s" % host)
|
||||||
return []
|
return []
|
||||||
except dns.exception.DNSException as e:
|
except dns.exception.DNSException as e:
|
||||||
log.debug("DNS: Error querying A records for %s." % host)
|
log.debug("DNS: Error querying A records for %s" % host)
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -204,13 +216,13 @@ def get_AAAA(host, resolver=None):
|
||||||
recs = resolver.query(host, dns.rdatatype.AAAA)
|
recs = resolver.query(host, dns.rdatatype.AAAA)
|
||||||
return [rec.to_text() for rec in recs]
|
return [rec.to_text() for rec in recs]
|
||||||
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
|
||||||
log.debug("DNS: No AAAA records for %s." % host)
|
log.debug("DNS: No AAAA records for %s" % host)
|
||||||
return []
|
return []
|
||||||
except dns.exception.Timeout:
|
except dns.exception.Timeout:
|
||||||
log.debug("DNS: AAAA record resolution timed out for %s." % host)
|
log.debug("DNS: AAAA record resolution timed out for %s" % host)
|
||||||
return []
|
return []
|
||||||
except dns.exception.DNSException as e:
|
except dns.exception.DNSException as e:
|
||||||
log.debug("DNS: Error querying AAAA records for %s." % host)
|
log.debug("DNS: Error querying AAAA records for %s" % host)
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -244,7 +256,7 @@ def get_SRV(host, port, service, proto='tcp', resolver=None):
|
||||||
if resolver is None:
|
if resolver is None:
|
||||||
return [(host, port)]
|
return [(host, port)]
|
||||||
|
|
||||||
log.debug("Querying SRV records for %s" % host)
|
log.debug("DNS: Querying SRV records for %s" % host)
|
||||||
try:
|
try:
|
||||||
recs = resolver.query('_%s._%s.%s' % (service, proto, host),
|
recs = resolver.query('_%s._%s.%s' % (service, proto, host),
|
||||||
dns.rdatatype.SRV)
|
dns.rdatatype.SRV)
|
||||||
|
|
|
@ -1018,7 +1018,8 @@ class XMLStream(object):
|
||||||
self.configure_dns(resolver, domain=domain, port=port)
|
self.configure_dns(resolver, domain=domain, port=port)
|
||||||
|
|
||||||
return resolve(domain, port, service=self.dns_service,
|
return resolve(domain, port, service=self.dns_service,
|
||||||
resolver=resolver)
|
resolver=resolver,
|
||||||
|
use_ipv6=self.use_ipv6)
|
||||||
|
|
||||||
def pick_dns_answer(self, domain, port=None):
|
def pick_dns_answer(self, domain, port=None):
|
||||||
"""Pick a server and port from DNS answers.
|
"""Pick a server and port from DNS answers.
|
||||||
|
|
Loading…
Reference in a new issue