1 # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose with or without fee is hereby granted,
5 # provided that the above copyright notice and this permission notice
6 # appear in all copies.
8 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 @var default_resolver: The default resolver object
19 @type default_resolver: dns.resolver.Resolver object"""
34 import dns
.reversename
36 if sys
.platform
== 'win32':
39 class NXDOMAIN(dns
.exception
.DNSException
):
40 """The query name does not exist."""
43 # The definition of the Timeout exception has moved from here to the
44 # dns.exception module. We keep dns.resolver.Timeout defined for
45 # backwards compatibility.
47 Timeout
= dns
.exception
.Timeout
49 class NoAnswer(dns
.exception
.DNSException
):
50 """The response did not contain an answer to the question."""
53 class NoNameservers(dns
.exception
.DNSException
):
54 """No non-broken nameservers are available to answer the query."""
57 class NotAbsolute(dns
.exception
.DNSException
):
58 """Raised if an absolute domain name is required but a relative name
62 class NoRootSOA(dns
.exception
.DNSException
):
63 """Raised if for some reason there is no SOA at the root name.
64 This should never happen!"""
67 class NoMetaqueries(dns
.exception
.DNSException
):
68 """Metaqueries are not allowed."""
73 """DNS stub resolver answer
75 Instances of this class bundle up the result of a successful DNS
78 For convenience, the answer object implements much of the sequence
79 protocol, forwarding to its rrset. E.g. "for a in answer" is
80 equivalent to "for a in answer.rrset", "answer[i]" is equivalent
81 to "answer.rrset[i]", and "answer[i:j]" is equivalent to
84 Note that CNAMEs or DNAMEs in the response may mean that answer
85 node's name might not be the query name.
87 @ivar qname: The query name
88 @type qname: dns.name.Name object
89 @ivar rdtype: The query type
91 @ivar rdclass: The query class
93 @ivar response: The response message
94 @type response: dns.message.Message object
95 @ivar rrset: The answer
96 @type rrset: dns.rrset.RRset object
97 @ivar expiration: The time when the answer expires
98 @type expiration: float (seconds since the epoch)
99 @ivar canonical_name: The canonical name of the query name
100 @type canonical_name: dns.name.Name object
102 def __init__(self
, qname
, rdtype
, rdclass
, response
,
103 raise_on_no_answer
=True):
106 self
.rdclass
= rdclass
107 self
.response
= response
110 for count
in xrange(0, 15):
112 rrset
= response
.find_rrset(response
.answer
, qname
,
114 if min_ttl
== -1 or rrset
.ttl
< min_ttl
:
118 if rdtype
!= dns
.rdatatype
.CNAME
:
120 crrset
= response
.find_rrset(response
.answer
,
124 if min_ttl
== -1 or crrset
.ttl
< min_ttl
:
131 if raise_on_no_answer
:
133 if raise_on_no_answer
:
135 if rrset
is None and raise_on_no_answer
:
137 self
.canonical_name
= qname
141 # Look for a SOA RR whose owner name is a superdomain
144 srrset
= response
.find_rrset(response
.authority
, qname
,
145 rdclass
, dns
.rdatatype
.SOA
)
146 if min_ttl
== -1 or srrset
.ttl
< min_ttl
:
148 if srrset
[0].minimum
< min_ttl
:
149 min_ttl
= srrset
[0].minimum
153 qname
= qname
.parent()
154 except dns
.name
.NoParent
:
156 self
.expiration
= time
.time() + min_ttl
158 def __getattr__(self
, attr
):
160 return self
.rrset
.name
162 return self
.rrset
.ttl
163 elif attr
== 'covers':
164 return self
.rrset
.covers
165 elif attr
== 'rdclass':
166 return self
.rrset
.rdclass
167 elif attr
== 'rdtype':
168 return self
.rrset
.rdtype
170 raise AttributeError(attr
)
173 return len(self
.rrset
)
176 return iter(self
.rrset
)
178 def __getitem__(self
, i
):
181 def __delitem__(self
, i
):
184 def __getslice__(self
, i
, j
):
185 return self
.rrset
[i
:j
]
187 def __delslice__(self
, i
, j
):
191 """Simple DNS answer cache.
193 @ivar data: A dictionary of cached data
195 @ivar cleaning_interval: The number of seconds between cleanings. The
196 default is 300 (5 minutes).
197 @type cleaning_interval: float
198 @ivar next_cleaning: The time the cache should next be cleaned (in seconds
200 @type next_cleaning: float
203 def __init__(self
, cleaning_interval
=300.0):
204 """Initialize a DNS cache.
206 @param cleaning_interval: the number of seconds between periodic
207 cleanings. The default is 300.0
208 @type cleaning_interval: float.
212 self
.cleaning_interval
= cleaning_interval
213 self
.next_cleaning
= time
.time() + self
.cleaning_interval
215 def maybe_clean(self
):
216 """Clean the cache if it's time to do so."""
219 if self
.next_cleaning
<= now
:
221 for (k
, v
) in self
.data
.iteritems():
222 if v
.expiration
<= now
:
223 keys_to_delete
.append(k
)
224 for k
in keys_to_delete
:
227 self
.next_cleaning
= now
+ self
.cleaning_interval
230 """Get the answer associated with I{key}. Returns None if
231 no answer is cached for the key.
233 @type key: (dns.name.Name, int, int) tuple whose values are the
234 query name, rdtype, and rdclass.
235 @rtype: dns.resolver.Answer object or None
239 v
= self
.data
.get(key
)
240 if v
is None or v
.expiration
<= time
.time():
244 def put(self
, key
, value
):
245 """Associate key and value in the cache.
247 @type key: (dns.name.Name, int, int) tuple whose values are the
248 query name, rdtype, and rdclass.
249 @param value: The answer being cached
250 @type value: dns.resolver.Answer object
254 self
.data
[key
] = value
256 def flush(self
, key
=None):
259 If I{key} is specified, only that item is flushed. Otherwise
260 the entire cache is flushed.
262 @param key: the key to flush
263 @type key: (dns.name.Name, int, int) tuple or None
267 if self
.data
.has_key(key
):
271 self
.next_cleaning
= time
.time() + self
.cleaning_interval
273 class LRUCacheNode(object):
276 def __init__(self
, key
, value
):
282 def link_before(self
, node
):
283 self
.prev
= node
.prev
285 node
.prev
.next
= self
288 def link_after(self
, node
):
290 self
.next
= node
.next
291 node
.next
.prev
= self
295 self
.next
.prev
= self
.prev
296 self
.prev
.next
= self
.next
298 class LRUCache(object):
299 """Bounded least-recently-used DNS answer cache.
301 This cache is better than the simple cache (above) if you're
302 running a web crawler or other process that does a lot of
303 resolutions. The LRUCache has a maximum number of nodes, and when
304 it is full, the least-recently used node is removed to make space
307 @ivar data: A dictionary of cached data
309 @ivar sentinel: sentinel node for circular doubly linked list of nodes
310 @type sentinel: LRUCacheNode object
311 @ivar max_size: The maximum number of nodes
315 def __init__(self
, max_size
=100000):
316 """Initialize a DNS cache.
318 @param max_size: The maximum number of nodes to cache; the default is
323 self
.set_max_size(max_size
)
324 self
.sentinel
= LRUCacheNode(None, None)
326 def set_max_size(self
, max_size
):
329 self
.max_size
= max_size
332 """Get the answer associated with I{key}. Returns None if
333 no answer is cached for the key.
335 @type key: (dns.name.Name, int, int) tuple whose values are the
336 query name, rdtype, and rdclass.
337 @rtype: dns.resolver.Answer object or None
339 node
= self
.data
.get(key
)
342 # Unlink because we're either going to move the node to the front
343 # of the LRU list or we're going to free it.
345 if node
.value
.expiration
<= time
.time():
346 del self
.data
[node
.key
]
348 node
.link_after(self
.sentinel
)
351 def put(self
, key
, value
):
352 """Associate key and value in the cache.
354 @type key: (dns.name.Name, int, int) tuple whose values are the
355 query name, rdtype, and rdclass.
356 @param value: The answer being cached
357 @type value: dns.resolver.Answer object
359 node
= self
.data
.get(key
)
362 del self
.data
[node
.key
]
363 while len(self
.data
) >= self
.max_size
:
364 node
= self
.sentinel
.prev
366 del self
.data
[node
.key
]
367 node
= LRUCacheNode(key
, value
)
368 node
.link_after(self
.sentinel
)
369 self
.data
[key
] = node
371 def flush(self
, key
=None):
374 If I{key} is specified, only that item is flushed. Otherwise
375 the entire cache is flushed.
377 @param key: the key to flush
378 @type key: (dns.name.Name, int, int) tuple or None
381 node
= self
.data
.get(key
)
384 del self
.data
[node
.key
]
386 node
= self
.sentinel
.next
387 while node
!= self
.sentinel
:
394 class Resolver(object):
397 @ivar domain: The domain of this host
398 @type domain: dns.name.Name object
399 @ivar nameservers: A list of nameservers to query. Each nameserver is
400 a string which contains the IP address of a nameserver.
401 @type nameservers: list of strings
402 @ivar search: The search list. If the query name is a relative name,
403 the resolver will construct an absolute query name by appending the search
404 names one by one to the query name.
405 @type search: list of dns.name.Name objects
406 @ivar port: The port to which to send queries. The default is 53.
408 @ivar timeout: The number of seconds to wait for a response from a
409 server, before timing out.
411 @ivar lifetime: The total number of seconds to spend trying to get an
412 answer to the question. If the lifetime expires, a Timeout exception
414 @type lifetime: float
415 @ivar keyring: The TSIG keyring to use. The default is None.
417 @ivar keyname: The TSIG keyname to use. The default is None.
418 @type keyname: dns.name.Name object
419 @ivar keyalgorithm: The TSIG key algorithm to use. The default is
420 dns.tsig.default_algorithm.
421 @type keyalgorithm: string
422 @ivar edns: The EDNS level to use. The default is -1, no Edns.
424 @ivar ednsflags: The EDNS flags
426 @ivar payload: The EDNS payload size. The default is 0.
428 @ivar cache: The cache to use. The default is None.
429 @type cache: dns.resolver.Cache object
431 def __init__(self
, filename
='/etc/resolv.conf', configure
=True):
432 """Initialize a resolver instance.
434 @param filename: The filename of a configuration file in
435 standard /etc/resolv.conf format. This parameter is meaningful
436 only when I{configure} is true and the platform is POSIX.
437 @type filename: string or file object
438 @param configure: If True (the default), the resolver instance
439 is configured in the normal fashion for the operating system
440 the resolver is running on. (I.e. a /etc/resolv.conf file on
441 POSIX systems and from the registry on Windows systems.)
442 @type configure: bool"""
446 if sys
.platform
== 'win32':
449 self
.read_resolv_conf(filename
)
452 """Reset all resolver configuration to the defaults."""
454 dns
.name
.Name(dns
.name
.from_text(socket
.gethostname())[1:])
455 if len(self
.domain
) == 0:
456 self
.domain
= dns
.name
.root
457 self
.nameservers
= []
464 self
.keyalgorithm
= dns
.tsig
.default_algorithm
470 def read_resolv_conf(self
, f
):
471 """Process f as a file in the /etc/resolv.conf format. If f is
472 a string, it is used as the name of the file to open; otherwise it
473 is treated as the file itself."""
474 if isinstance(f
, str) or isinstance(f
, unicode):
478 # /etc/resolv.conf doesn't exist, can't be read, etc.
479 # We'll just use the default resolver configuration.
480 self
.nameservers
= ['127.0.0.1']
487 if len(l
) == 0 or l
[0] == '#' or l
[0] == ';':
492 if tokens
[0] == 'nameserver':
493 self
.nameservers
.append(tokens
[1])
494 elif tokens
[0] == 'domain':
495 self
.domain
= dns
.name
.from_text(tokens
[1])
496 elif tokens
[0] == 'search':
497 for suffix
in tokens
[1:]:
498 self
.search
.append(dns
.name
.from_text(suffix
))
502 if len(self
.nameservers
) == 0:
503 self
.nameservers
.append('127.0.0.1')
505 def _determine_split_char(self
, entry
):
507 # The windows registry irritatingly changes the list element
508 # delimiter in between ' ' and ',' (and vice-versa) in various
509 # versions of windows.
511 if entry
.find(' ') >= 0:
513 elif entry
.find(',') >= 0:
516 # probably a singleton; treat as a space-separated list.
520 def _config_win32_nameservers(self
, nameservers
):
521 """Configure a NameServer registry entry."""
522 # we call str() on nameservers to convert it from unicode to ascii
523 nameservers
= str(nameservers
)
524 split_char
= self
._determine
_split
_char
(nameservers
)
525 ns_list
= nameservers
.split(split_char
)
527 if not ns
in self
.nameservers
:
528 self
.nameservers
.append(ns
)
530 def _config_win32_domain(self
, domain
):
531 """Configure a Domain registry entry."""
532 # we call str() on domain to convert it from unicode to ascii
533 self
.domain
= dns
.name
.from_text(str(domain
))
535 def _config_win32_search(self
, search
):
536 """Configure a Search registry entry."""
537 # we call str() on search to convert it from unicode to ascii
539 split_char
= self
._determine
_split
_char
(search
)
540 search_list
= search
.split(split_char
)
541 for s
in search_list
:
542 if not s
in self
.search
:
543 self
.search
.append(dns
.name
.from_text(s
))
545 def _config_win32_fromkey(self
, key
):
546 """Extract DNS info from a registry key."""
548 servers
, rtype
= _winreg
.QueryValueEx(key
, 'NameServer')
552 self
._config
_win
32_nameservers
(servers
)
554 dom
, rtype
= _winreg
.QueryValueEx(key
, 'Domain')
556 self
._config
_win
32_domain
(dom
)
561 servers
, rtype
= _winreg
.QueryValueEx(key
, 'DhcpNameServer')
565 self
._config
_win
32_nameservers
(servers
)
567 dom
, rtype
= _winreg
.QueryValueEx(key
, 'DhcpDomain')
569 self
._config
_win
32_domain
(dom
)
573 search
, rtype
= _winreg
.QueryValueEx(key
, 'SearchList')
577 self
._config
_win
32_search
(search
)
579 def read_registry(self
):
580 """Extract resolver configuration from the Windows registry."""
581 lm
= _winreg
.ConnectRegistry(None, _winreg
.HKEY_LOCAL_MACHINE
)
586 tcp_params
= _winreg
.OpenKey(lm
,
587 r
'SYSTEM\CurrentControlSet'
588 r
'\Services\Tcpip\Parameters')
590 except EnvironmentError:
592 tcp_params
= _winreg
.OpenKey(lm
,
593 r
'SYSTEM\CurrentControlSet'
594 r
'\Services\VxD\MSTCP')
596 self
._config
_win
32_fromkey
(tcp_params
)
600 interfaces
= _winreg
.OpenKey(lm
,
601 r
'SYSTEM\CurrentControlSet'
602 r
'\Services\Tcpip\Parameters'
608 guid
= _winreg
.EnumKey(interfaces
, i
)
610 key
= _winreg
.OpenKey(interfaces
, guid
)
611 if not self
._win
32_is
_nic
_enabled
(lm
, guid
, key
):
614 self
._config
_win
32_fromkey
(key
)
617 except EnvironmentError:
624 def _win32_is_nic_enabled(self
, lm
, guid
, interface_key
):
625 # Look in the Windows Registry to determine whether the network
626 # interface corresponding to the given guid is enabled.
628 # (Code contributed by Paul Marks, thanks!)
631 # This hard-coded location seems to be consistent, at least
632 # from Windows 2000 through Vista.
633 connection_key
= _winreg
.OpenKey(
635 r
'SYSTEM\CurrentControlSet\Control\Network'
636 r
'\{4D36E972-E325-11CE-BFC1-08002BE10318}'
637 r
'\%s\Connection' % guid
)
640 # The PnpInstanceID points to a key inside Enum
641 (pnp_id
, ttype
) = _winreg
.QueryValueEx(
642 connection_key
, 'PnpInstanceID')
644 if ttype
!= _winreg
.REG_SZ
:
647 device_key
= _winreg
.OpenKey(
648 lm
, r
'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id
)
651 # Get ConfigFlags for this device
652 (flags
, ttype
) = _winreg
.QueryValueEx(
653 device_key
, 'ConfigFlags')
655 if ttype
!= _winreg
.REG_DWORD
:
658 # Based on experimentation, bit 0x1 indicates that the
659 # device is disabled.
660 return not (flags
& 0x1)
665 connection_key
.Close()
666 except (EnvironmentError, ValueError):
667 # Pre-vista, enabled interfaces seem to have a non-empty
668 # NTEContextList; this was how dnspython detected enabled
669 # nics before the code above was contributed. We've retained
670 # the old method since we don't know if the code above works
671 # on Windows 95/98/ME.
673 (nte
, ttype
) = _winreg
.QueryValueEx(interface_key
,
675 return nte
is not None
679 def _compute_timeout(self
, start
):
683 # Time going backwards is bad. Just give up.
686 # Time went backwards, but only a little. This can
687 # happen, e.g. under vmware with older linux kernels.
688 # Pretend it didn't happen.
690 duration
= now
- start
691 if duration
>= self
.lifetime
:
693 return min(self
.lifetime
- duration
, self
.timeout
)
695 def query(self
, qname
, rdtype
=dns
.rdatatype
.A
, rdclass
=dns
.rdataclass
.IN
,
696 tcp
=False, source
=None, raise_on_no_answer
=True):
697 """Query nameservers to find the answer to the question.
699 The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
700 of the appropriate type, or strings that can be converted into objects
701 of the appropriate type. E.g. For I{rdtype} the integer 2 and the
702 the string 'NS' both mean to query for records with DNS rdata type NS.
704 @param qname: the query name
705 @type qname: dns.name.Name object or string
706 @param rdtype: the query type
707 @type rdtype: int or string
708 @param rdclass: the query class
709 @type rdclass: int or string
710 @param tcp: use TCP to make the query (default is False).
712 @param source: bind to this IP address (defaults to machine default IP).
713 @type source: IP address in dotted quad notation
714 @param raise_on_no_answer: raise NoAnswer if there's no answer
716 @type raise_on_no_answer: bool
717 @rtype: dns.resolver.Answer instance
718 @raises Timeout: no answers could be found in the specified lifetime
719 @raises NXDOMAIN: the query name does not exist
720 @raises NoAnswer: the response did not contain an answer and
721 raise_on_no_answer is True.
722 @raises NoNameservers: no non-broken nameservers are available to
723 answer the question."""
725 if isinstance(qname
, (str, unicode)):
726 qname
= dns
.name
.from_text(qname
, None)
727 if isinstance(rdtype
, (str, unicode)):
728 rdtype
= dns
.rdatatype
.from_text(rdtype
)
729 if dns
.rdatatype
.is_metatype(rdtype
):
731 if isinstance(rdclass
, (str, unicode)):
732 rdclass
= dns
.rdataclass
.from_text(rdclass
)
733 if dns
.rdataclass
.is_metaclass(rdclass
):
736 if qname
.is_absolute():
737 qnames_to_try
.append(qname
)
740 qnames_to_try
.append(qname
.concatenate(dns
.name
.root
))
742 for suffix
in self
.search
:
743 qnames_to_try
.append(qname
.concatenate(suffix
))
745 qnames_to_try
.append(qname
.concatenate(self
.domain
))
748 for qname
in qnames_to_try
:
750 answer
= self
.cache
.get((qname
, rdtype
, rdclass
))
751 if not answer
is None:
752 if answer
.rrset
is None and raise_on_no_answer
:
756 request
= dns
.message
.make_query(qname
, rdtype
, rdclass
)
757 if not self
.keyname
is None:
758 request
.use_tsig(self
.keyring
, self
.keyname
,
759 algorithm
=self
.keyalgorithm
)
760 request
.use_edns(self
.edns
, self
.ednsflags
, self
.payload
)
763 # make a copy of the servers list so we can alter it later.
765 nameservers
= self
.nameservers
[:]
767 while response
is None:
768 if len(nameservers
) == 0:
770 for nameserver
in nameservers
[:]:
771 timeout
= self
._compute
_timeout
(start
)
774 response
= dns
.query
.tcp(request
, nameserver
,
778 response
= dns
.query
.udp(request
, nameserver
,
781 except (socket
.error
, dns
.exception
.Timeout
):
783 # Communication failure or timeout. Go to the
788 except dns
.query
.UnexpectedSource
:
790 # Who knows? Keep going.
794 except dns
.exception
.FormError
:
796 # We don't understand what this server is
797 # saying. Take it out of the mix and
800 nameservers
.remove(nameserver
)
803 rcode
= response
.rcode()
804 if rcode
== dns
.rcode
.NOERROR
or \
805 rcode
== dns
.rcode
.NXDOMAIN
:
808 # We got a response, but we're not happy with the
809 # rcode in it. Remove the server from the mix if
810 # the rcode isn't SERVFAIL.
812 if rcode
!= dns
.rcode
.SERVFAIL
:
813 nameservers
.remove(nameserver
)
815 if not response
is None:
818 # All nameservers failed!
820 if len(nameservers
) > 0:
822 # But we still have servers to try. Sleep a bit
823 # so we don't pound them!
825 timeout
= self
._compute
_timeout
(start
)
826 sleep_time
= min(timeout
, backoff
)
828 time
.sleep(sleep_time
)
829 if response
.rcode() == dns
.rcode
.NXDOMAIN
:
835 answer
= Answer(qname
, rdtype
, rdclass
, response
,
838 self
.cache
.put((qname
, rdtype
, rdclass
), answer
)
841 def use_tsig(self
, keyring
, keyname
=None,
842 algorithm
=dns
.tsig
.default_algorithm
):
843 """Add a TSIG signature to the query.
845 @param keyring: The TSIG keyring to use; defaults to None.
847 @param keyname: The name of the TSIG key to use; defaults to None.
848 The key must be defined in the keyring. If a keyring is specified
849 but a keyname is not, then the key used will be the first key in the
850 keyring. Note that the order of keys in a dictionary is not defined,
851 so applications should supply a keyname when a keyring is used, unless
852 they know the keyring contains only one key.
853 @param algorithm: The TSIG key algorithm to use. The default
854 is dns.tsig.default_algorithm.
855 @type algorithm: string"""
856 self
.keyring
= keyring
858 self
.keyname
= self
.keyring
.keys()[0]
860 self
.keyname
= keyname
861 self
.keyalgorithm
= algorithm
863 def use_edns(self
, edns
, ednsflags
, payload
):
866 @param edns: The EDNS level to use. The default is -1, no Edns.
868 @param ednsflags: The EDNS flags
870 @param payload: The EDNS payload size. The default is 0.
871 @type payload: int"""
876 self
.ednsflags
= ednsflags
877 self
.payload
= payload
879 default_resolver
= None
881 def get_default_resolver():
882 """Get the default resolver, initializing it if necessary."""
883 global default_resolver
884 if default_resolver
is None:
885 default_resolver
= Resolver()
886 return default_resolver
888 def query(qname
, rdtype
=dns
.rdatatype
.A
, rdclass
=dns
.rdataclass
.IN
,
889 tcp
=False, source
=None, raise_on_no_answer
=True):
890 """Query nameservers to find the answer to the question.
892 This is a convenience function that uses the default resolver
893 object to make the query.
894 @see: L{dns.resolver.Resolver.query} for more information on the
896 return get_default_resolver().query(qname
, rdtype
, rdclass
, tcp
, source
,
899 def zone_for_name(name
, rdclass
=dns
.rdataclass
.IN
, tcp
=False, resolver
=None):
900 """Find the name of the zone which contains the specified name.
902 @param name: the query name
903 @type name: absolute dns.name.Name object or string
904 @param rdclass: The query class
906 @param tcp: use TCP to make the query (default is False).
908 @param resolver: the resolver to use
909 @type resolver: dns.resolver.Resolver object or None
910 @rtype: dns.name.Name"""
912 if isinstance(name
, (str, unicode)):
913 name
= dns
.name
.from_text(name
, dns
.name
.root
)
915 resolver
= get_default_resolver()
916 if not name
.is_absolute():
917 raise NotAbsolute(name
)
920 answer
= resolver
.query(name
, dns
.rdatatype
.SOA
, rdclass
, tcp
)
921 if answer
.rrset
.name
== name
:
923 # otherwise we were CNAMEd or DNAMEd and need to look higher
924 except (dns
.resolver
.NXDOMAIN
, dns
.resolver
.NoAnswer
):
928 except dns
.name
.NoParent
:
932 # Support for overriding the system resolver for all python code in the
936 _protocols_for_socktype
= {
937 socket
.SOCK_DGRAM
: [socket
.SOL_UDP
],
938 socket
.SOCK_STREAM
: [socket
.SOL_TCP
],
942 _original_getaddrinfo
= socket
.getaddrinfo
943 _original_getnameinfo
= socket
.getnameinfo
944 _original_getfqdn
= socket
.getfqdn
945 _original_gethostbyname
= socket
.gethostbyname
946 _original_gethostbyname_ex
= socket
.gethostbyname_ex
947 _original_gethostbyaddr
= socket
.gethostbyaddr
949 def _getaddrinfo(host
=None, service
=None, family
=socket
.AF_UNSPEC
, socktype
=0,
951 if flags
& (socket
.AI_ADDRCONFIG|socket
.AI_V4MAPPED
) != 0:
952 raise NotImplementedError
953 if host
is None and service
is None:
954 raise socket
.gaierror(socket
.EAI_NONAME
)
957 canonical_name
= None
959 # Is host None or a V6 address literal?
961 canonical_name
= 'localhost'
962 if flags
& socket
.AI_PASSIVE
!= 0:
964 v4addrs
.append('0.0.0.0')
966 v6addrs
.append('::1')
967 v4addrs
.append('127.0.0.1')
969 parts
= host
.split('%')
974 addr
= dns
.ipv6
.inet_aton(ahost
)
976 canonical_name
= host
979 # Is it a V4 address literal?
980 addr
= dns
.ipv4
.inet_aton(host
)
982 canonical_name
= host
984 if flags
& socket
.AI_NUMERICHOST
== 0:
987 if family
== socket
.AF_INET6
or family
== socket
.AF_UNSPEC
:
988 v6
= _resolver
.query(host
, dns
.rdatatype
.AAAA
,
989 raise_on_no_answer
=False)
990 # Note that setting host ensures we query the same name
991 # for A as we did for AAAA.
993 canonical_name
= v6
.canonical_name
.to_text(True)
994 if v6
.rrset
is not None:
995 for rdata
in v6
.rrset
:
996 v6addrs
.append(rdata
.address
)
997 if family
== socket
.AF_INET
or family
== socket
.AF_UNSPEC
:
998 v4
= _resolver
.query(host
, dns
.rdatatype
.A
,
999 raise_on_no_answer
=False)
1001 canonical_name
= v4
.canonical_name
.to_text(True)
1002 if v4
.rrset
is not None:
1003 for rdata
in v4
.rrset
:
1004 v4addrs
.append(rdata
.address
)
1005 except dns
.resolver
.NXDOMAIN
:
1006 raise socket
.gaierror(socket
.EAI_NONAME
)
1008 raise socket
.gaierror(socket
.EAI_SYSTEM
)
1011 # Is it a port literal?
1017 if flags
& socket
.AI_NUMERICSERV
== 0:
1019 port
= socket
.getservbyname(service
)
1023 raise socket
.gaierror(socket
.EAI_NONAME
)
1026 socktypes
= [socket
.SOCK_DGRAM
, socket
.SOCK_STREAM
]
1028 socktypes
= [socktype
]
1029 if flags
& socket
.AI_CANONNAME
!= 0:
1030 cname
= canonical_name
1033 if family
== socket
.AF_INET6
or family
== socket
.AF_UNSPEC
:
1034 for addr
in v6addrs
:
1035 for socktype
in socktypes
:
1036 for proto
in _protocols_for_socktype
[socktype
]:
1037 tuples
.append((socket
.AF_INET6
, socktype
, proto
,
1038 cname
, (addr
, port
, 0, 0)))
1039 if family
== socket
.AF_INET
or family
== socket
.AF_UNSPEC
:
1040 for addr
in v4addrs
:
1041 for socktype
in socktypes
:
1042 for proto
in _protocols_for_socktype
[socktype
]:
1043 tuples
.append((socket
.AF_INET
, socktype
, proto
,
1044 cname
, (addr
, port
)))
1045 if len(tuples
) == 0:
1046 raise socket
.gaierror(socket
.EAI_NONAME
)
1049 def _getnameinfo(sockaddr
, flags
=0):
1052 if len(sockaddr
) == 4:
1054 family
= socket
.AF_INET6
1057 family
= socket
.AF_INET
1058 tuples
= _getaddrinfo(host
, port
, family
, socket
.SOCK_STREAM
,
1061 raise socket
.error('sockaddr resolved to multiple addresses')
1062 addr
= tuples
[0][4][0]
1063 if flags
& socket
.NI_DGRAM
:
1067 qname
= dns
.reversename
.from_address(addr
)
1068 if flags
& socket
.NI_NUMERICHOST
== 0:
1070 answer
= _resolver
.query(qname
, 'PTR')
1071 hostname
= answer
.rrset
[0].target
.to_text(True)
1072 except (dns
.resolver
.NXDOMAIN
, dns
.resolver
.NoAnswer
):
1073 if flags
& socket
.NI_NAMEREQD
:
1074 raise socket
.gaierror(socket
.EAI_NONAME
)
1076 if scope
is not None:
1077 hostname
+= '%' + str(scope
)
1080 if scope
is not None:
1081 hostname
+= '%' + str(scope
)
1082 if flags
& socket
.NI_NUMERICSERV
:
1085 service
= socket
.getservbyport(port
, pname
)
1086 return (hostname
, service
)
1088 def _getfqdn(name
=None):
1090 name
= socket
.gethostname()
1091 return _getnameinfo(_getaddrinfo(name
, 80)[0][4])[0]
1093 def _gethostbyname(name
):
1094 return _gethostbyname_ex(name
)[2][0]
1096 def _gethostbyname_ex(name
):
1099 tuples
= _getaddrinfo(name
, 0, socket
.AF_INET
, socket
.SOCK_STREAM
,
1100 socket
.SOL_TCP
, socket
.AI_CANONNAME
)
1101 canonical
= tuples
[0][3]
1103 addresses
.append(item
[4][0])
1104 # XXX we just ignore aliases
1105 return (canonical
, aliases
, addresses
)
1107 def _gethostbyaddr(ip
):
1109 addr
= dns
.ipv6
.inet_aton(ip
)
1110 sockaddr
= (ip
, 80, 0, 0)
1111 family
= socket
.AF_INET6
1114 family
= socket
.AF_INET
1115 (name
, port
) = _getnameinfo(sockaddr
, socket
.NI_NAMEREQD
)
1118 tuples
= _getaddrinfo(name
, 0, family
, socket
.SOCK_STREAM
, socket
.SOL_TCP
,
1119 socket
.AI_CANONNAME
)
1120 canonical
= tuples
[0][3]
1122 addresses
.append(item
[4][0])
1123 # XXX we just ignore aliases
1124 return (canonical
, aliases
, addresses
)
1126 def override_system_resolver(resolver
=None):
1127 """Override the system resolver routines in the socket module with
1128 versions which use dnspython's resolver.
1130 This can be useful in testing situations where you want to control
1131 the resolution behavior of python code without having to change
1132 the system's resolver settings (e.g. /etc/resolv.conf).
1134 The resolver to use may be specified; if it's not, the default
1135 resolver will be used.
1137 @param resolver: the resolver to use
1138 @type resolver: dns.resolver.Resolver object or None
1140 if resolver
is None:
1141 resolver
= get_default_resolver()
1143 _resolver
= resolver
1144 socket
.getaddrinfo
= _getaddrinfo
1145 socket
.getnameinfo
= _getnameinfo
1146 socket
.getfqdn
= _getfqdn
1147 socket
.gethostbyname
= _gethostbyname
1148 socket
.gethostbyname_ex
= _gethostbyname_ex
1149 socket
.gethostbyaddr
= _gethostbyaddr
1151 def restore_system_resolver():
1152 """Undo the effects of override_system_resolver().
1156 socket
.getaddrinfo
= _original_getaddrinfo
1157 socket
.getnameinfo
= _original_getnameinfo
1158 socket
.getfqdn
= _original_getfqdn
1159 socket
.gethostbyname
= _original_gethostbyname
1160 socket
.gethostbyname_ex
= _original_gethostbyname_ex
1161 socket
.gethostbyaddr
= _original_gethostbyaddr