s4-dns: dlz_bind9: Check result to avoid segfault
[Samba/gbeck.git] / lib / dnspython / dns / resolver.py
blob90f95e8ed0504f42bf86f66c55e488149ef4c8ff
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.
16 """DNS stub resolver.
18 @var default_resolver: The default resolver object
19 @type default_resolver: dns.resolver.Resolver object"""
21 import socket
22 import sys
23 import time
25 import dns.exception
26 import dns.ipv4
27 import dns.ipv6
28 import dns.message
29 import dns.name
30 import dns.query
31 import dns.rcode
32 import dns.rdataclass
33 import dns.rdatatype
34 import dns.reversename
36 if sys.platform == 'win32':
37 import _winreg
39 class NXDOMAIN(dns.exception.DNSException):
40 """The query name does not exist."""
41 pass
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."""
51 pass
53 class NoNameservers(dns.exception.DNSException):
54 """No non-broken nameservers are available to answer the query."""
55 pass
57 class NotAbsolute(dns.exception.DNSException):
58 """Raised if an absolute domain name is required but a relative name
59 was provided."""
60 pass
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!"""
65 pass
67 class NoMetaqueries(dns.exception.DNSException):
68 """Metaqueries are not allowed."""
69 pass
72 class Answer(object):
73 """DNS stub resolver answer
75 Instances of this class bundle up the result of a successful DNS
76 resolution.
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
82 "answer.rrset[i:j]".
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
90 @type rdtype: int
91 @ivar rdclass: The query class
92 @type rdclass: int
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):
104 self.qname = qname
105 self.rdtype = rdtype
106 self.rdclass = rdclass
107 self.response = response
108 min_ttl = -1
109 rrset = None
110 for count in xrange(0, 15):
111 try:
112 rrset = response.find_rrset(response.answer, qname,
113 rdclass, rdtype)
114 if min_ttl == -1 or rrset.ttl < min_ttl:
115 min_ttl = rrset.ttl
116 break
117 except KeyError:
118 if rdtype != dns.rdatatype.CNAME:
119 try:
120 crrset = response.find_rrset(response.answer,
121 qname,
122 rdclass,
123 dns.rdatatype.CNAME)
124 if min_ttl == -1 or crrset.ttl < min_ttl:
125 min_ttl = crrset.ttl
126 for rd in crrset:
127 qname = rd.target
128 break
129 continue
130 except KeyError:
131 if raise_on_no_answer:
132 raise NoAnswer
133 if raise_on_no_answer:
134 raise NoAnswer
135 if rrset is None and raise_on_no_answer:
136 raise NoAnswer
137 self.canonical_name = qname
138 self.rrset = rrset
139 if rrset is None:
140 while 1:
141 # Look for a SOA RR whose owner name is a superdomain
142 # of qname.
143 try:
144 srrset = response.find_rrset(response.authority, qname,
145 rdclass, dns.rdatatype.SOA)
146 if min_ttl == -1 or srrset.ttl < min_ttl:
147 min_ttl = srrset.ttl
148 if srrset[0].minimum < min_ttl:
149 min_ttl = srrset[0].minimum
150 break
151 except KeyError:
152 try:
153 qname = qname.parent()
154 except dns.name.NoParent:
155 break
156 self.expiration = time.time() + min_ttl
158 def __getattr__(self, attr):
159 if attr == 'name':
160 return self.rrset.name
161 elif attr == 'ttl':
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
169 else:
170 raise AttributeError(attr)
172 def __len__(self):
173 return len(self.rrset)
175 def __iter__(self):
176 return iter(self.rrset)
178 def __getitem__(self, i):
179 return self.rrset[i]
181 def __delitem__(self, i):
182 del self.rrset[i]
184 def __getslice__(self, i, j):
185 return self.rrset[i:j]
187 def __delslice__(self, i, j):
188 del self.rrset[i:j]
190 class Cache(object):
191 """Simple DNS answer cache.
193 @ivar data: A dictionary of cached data
194 @type data: dict
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
199 since the epoch.)
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.
211 self.data = {}
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."""
218 now = time.time()
219 if self.next_cleaning <= now:
220 keys_to_delete = []
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:
225 del self.data[k]
226 now = time.time()
227 self.next_cleaning = now + self.cleaning_interval
229 def get(self, key):
230 """Get the answer associated with I{key}. Returns None if
231 no answer is cached for the key.
232 @param key: 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
238 self.maybe_clean()
239 v = self.data.get(key)
240 if v is None or v.expiration <= time.time():
241 return None
242 return v
244 def put(self, key, value):
245 """Associate key and value in the cache.
246 @param key: the key
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
253 self.maybe_clean()
254 self.data[key] = value
256 def flush(self, key=None):
257 """Flush the cache.
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
266 if not key is None:
267 if self.data.has_key(key):
268 del self.data[key]
269 else:
270 self.data = {}
271 self.next_cleaning = time.time() + self.cleaning_interval
273 class LRUCacheNode(object):
274 """LRUCache node.
276 def __init__(self, key, value):
277 self.key = key
278 self.value = value
279 self.prev = self
280 self.next = self
282 def link_before(self, node):
283 self.prev = node.prev
284 self.next = node
285 node.prev.next = self
286 node.prev = self
288 def link_after(self, node):
289 self.prev = node
290 self.next = node.next
291 node.next.prev = self
292 node.next = self
294 def unlink(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
305 for a new one.
307 @ivar data: A dictionary of cached data
308 @type data: dict
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
312 @type max_size: int
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
319 100000. Must be > 1.
320 @type max_size: int
322 self.data = {}
323 self.set_max_size(max_size)
324 self.sentinel = LRUCacheNode(None, None)
326 def set_max_size(self, max_size):
327 if max_size < 1:
328 max_size = 1
329 self.max_size = max_size
331 def get(self, key):
332 """Get the answer associated with I{key}. Returns None if
333 no answer is cached for the key.
334 @param key: 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)
340 if node is None:
341 return None
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.
344 node.unlink()
345 if node.value.expiration <= time.time():
346 del self.data[node.key]
347 return None
348 node.link_after(self.sentinel)
349 return node.value
351 def put(self, key, value):
352 """Associate key and value in the cache.
353 @param key: the key
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)
360 if not node is None:
361 node.unlink()
362 del self.data[node.key]
363 while len(self.data) >= self.max_size:
364 node = self.sentinel.prev
365 node.unlink()
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):
372 """Flush the cache.
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
380 if not key is None:
381 node = self.data.get(key)
382 if not node is None:
383 node.unlink()
384 del self.data[node.key]
385 else:
386 node = self.sentinel.next
387 while node != self.sentinel:
388 next = node.next
389 node.prev = None
390 node.next = None
391 node = next
392 self.data = {}
394 class Resolver(object):
395 """DNS stub resolver
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.
407 @type port: int
408 @ivar timeout: The number of seconds to wait for a response from a
409 server, before timing out.
410 @type timeout: float
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
413 will occur.
414 @type lifetime: float
415 @ivar keyring: The TSIG keyring to use. The default is None.
416 @type keyring: dict
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.
423 @type edns: int
424 @ivar ednsflags: The EDNS flags
425 @type ednsflags: int
426 @ivar payload: The EDNS payload size. The default is 0.
427 @type payload: int
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"""
444 self.reset()
445 if configure:
446 if sys.platform == 'win32':
447 self.read_registry()
448 elif filename:
449 self.read_resolv_conf(filename)
451 def reset(self):
452 """Reset all resolver configuration to the defaults."""
453 self.domain = \
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 = []
458 self.search = []
459 self.port = 53
460 self.timeout = 2.0
461 self.lifetime = 30.0
462 self.keyring = None
463 self.keyname = None
464 self.keyalgorithm = dns.tsig.default_algorithm
465 self.edns = -1
466 self.ednsflags = 0
467 self.payload = 0
468 self.cache = None
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):
475 try:
476 f = open(f, 'r')
477 except IOError:
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']
481 return
482 want_close = True
483 else:
484 want_close = False
485 try:
486 for l in f:
487 if len(l) == 0 or l[0] == '#' or l[0] == ';':
488 continue
489 tokens = l.split()
490 if len(tokens) == 0:
491 continue
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))
499 finally:
500 if want_close:
501 f.close()
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:
512 split_char = ' '
513 elif entry.find(',') >= 0:
514 split_char = ','
515 else:
516 # probably a singleton; treat as a space-separated list.
517 split_char = ' '
518 return split_char
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)
526 for ns in ns_list:
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
538 search = str(search)
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."""
547 try:
548 servers, rtype = _winreg.QueryValueEx(key, 'NameServer')
549 except WindowsError:
550 servers = None
551 if servers:
552 self._config_win32_nameservers(servers)
553 try:
554 dom, rtype = _winreg.QueryValueEx(key, 'Domain')
555 if dom:
556 self._config_win32_domain(dom)
557 except WindowsError:
558 pass
559 else:
560 try:
561 servers, rtype = _winreg.QueryValueEx(key, 'DhcpNameServer')
562 except WindowsError:
563 servers = None
564 if servers:
565 self._config_win32_nameservers(servers)
566 try:
567 dom, rtype = _winreg.QueryValueEx(key, 'DhcpDomain')
568 if dom:
569 self._config_win32_domain(dom)
570 except WindowsError:
571 pass
572 try:
573 search, rtype = _winreg.QueryValueEx(key, 'SearchList')
574 except WindowsError:
575 search = None
576 if search:
577 self._config_win32_search(search)
579 def read_registry(self):
580 """Extract resolver configuration from the Windows registry."""
581 lm = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
582 want_scan = False
583 try:
584 try:
585 # XP, 2000
586 tcp_params = _winreg.OpenKey(lm,
587 r'SYSTEM\CurrentControlSet'
588 r'\Services\Tcpip\Parameters')
589 want_scan = True
590 except EnvironmentError:
591 # ME
592 tcp_params = _winreg.OpenKey(lm,
593 r'SYSTEM\CurrentControlSet'
594 r'\Services\VxD\MSTCP')
595 try:
596 self._config_win32_fromkey(tcp_params)
597 finally:
598 tcp_params.Close()
599 if want_scan:
600 interfaces = _winreg.OpenKey(lm,
601 r'SYSTEM\CurrentControlSet'
602 r'\Services\Tcpip\Parameters'
603 r'\Interfaces')
604 try:
605 i = 0
606 while True:
607 try:
608 guid = _winreg.EnumKey(interfaces, i)
609 i += 1
610 key = _winreg.OpenKey(interfaces, guid)
611 if not self._win32_is_nic_enabled(lm, guid, key):
612 continue
613 try:
614 self._config_win32_fromkey(key)
615 finally:
616 key.Close()
617 except EnvironmentError:
618 break
619 finally:
620 interfaces.Close()
621 finally:
622 lm.Close()
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!)
630 try:
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)
639 try:
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:
645 raise ValueError
647 device_key = _winreg.OpenKey(
648 lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id)
650 try:
651 # Get ConfigFlags for this device
652 (flags, ttype) = _winreg.QueryValueEx(
653 device_key, 'ConfigFlags')
655 if ttype != _winreg.REG_DWORD:
656 raise ValueError
658 # Based on experimentation, bit 0x1 indicates that the
659 # device is disabled.
660 return not (flags & 0x1)
662 finally:
663 device_key.Close()
664 finally:
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.
672 try:
673 (nte, ttype) = _winreg.QueryValueEx(interface_key,
674 'NTEContextList')
675 return nte is not None
676 except WindowsError:
677 return False
679 def _compute_timeout(self, start):
680 now = time.time()
681 if now < start:
682 if start - now > 1:
683 # Time going backwards is bad. Just give up.
684 raise Timeout
685 else:
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.
689 now = start
690 duration = now - start
691 if duration >= self.lifetime:
692 raise Timeout
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).
711 @type tcp: bool
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
715 (defaults is True).
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):
730 raise NoMetaqueries
731 if isinstance(rdclass, (str, unicode)):
732 rdclass = dns.rdataclass.from_text(rdclass)
733 if dns.rdataclass.is_metaclass(rdclass):
734 raise NoMetaqueries
735 qnames_to_try = []
736 if qname.is_absolute():
737 qnames_to_try.append(qname)
738 else:
739 if len(qname) > 1:
740 qnames_to_try.append(qname.concatenate(dns.name.root))
741 if self.search:
742 for suffix in self.search:
743 qnames_to_try.append(qname.concatenate(suffix))
744 else:
745 qnames_to_try.append(qname.concatenate(self.domain))
746 all_nxdomain = True
747 start = time.time()
748 for qname in qnames_to_try:
749 if self.cache:
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:
753 raise NoAnswer
754 else:
755 return 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)
761 response = None
763 # make a copy of the servers list so we can alter it later.
765 nameservers = self.nameservers[:]
766 backoff = 0.10
767 while response is None:
768 if len(nameservers) == 0:
769 raise NoNameservers
770 for nameserver in nameservers[:]:
771 timeout = self._compute_timeout(start)
772 try:
773 if tcp:
774 response = dns.query.tcp(request, nameserver,
775 timeout, self.port,
776 source=source)
777 else:
778 response = dns.query.udp(request, nameserver,
779 timeout, self.port,
780 source=source)
781 except (socket.error, dns.exception.Timeout):
783 # Communication failure or timeout. Go to the
784 # next server
786 response = None
787 continue
788 except dns.query.UnexpectedSource:
790 # Who knows? Keep going.
792 response = None
793 continue
794 except dns.exception.FormError:
796 # We don't understand what this server is
797 # saying. Take it out of the mix and
798 # continue.
800 nameservers.remove(nameserver)
801 response = None
802 continue
803 rcode = response.rcode()
804 if rcode == dns.rcode.NOERROR or \
805 rcode == dns.rcode.NXDOMAIN:
806 break
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)
814 response = None
815 if not response is None:
816 break
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)
827 backoff *= 2
828 time.sleep(sleep_time)
829 if response.rcode() == dns.rcode.NXDOMAIN:
830 continue
831 all_nxdomain = False
832 break
833 if all_nxdomain:
834 raise NXDOMAIN
835 answer = Answer(qname, rdtype, rdclass, response,
836 raise_on_no_answer)
837 if self.cache:
838 self.cache.put((qname, rdtype, rdclass), answer)
839 return 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.
846 @type keyring: dict
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
857 if keyname is None:
858 self.keyname = self.keyring.keys()[0]
859 else:
860 self.keyname = keyname
861 self.keyalgorithm = algorithm
863 def use_edns(self, edns, ednsflags, payload):
864 """Configure Edns.
866 @param edns: The EDNS level to use. The default is -1, no Edns.
867 @type edns: int
868 @param ednsflags: The EDNS flags
869 @type ednsflags: int
870 @param payload: The EDNS payload size. The default is 0.
871 @type payload: int"""
873 if edns is None:
874 edns = -1
875 self.edns = edns
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
895 parameters."""
896 return get_default_resolver().query(qname, rdtype, rdclass, tcp, source,
897 raise_on_no_answer)
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
905 @type rdclass: int
906 @param tcp: use TCP to make the query (default is False).
907 @type tcp: bool
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)
914 if resolver is None:
915 resolver = get_default_resolver()
916 if not name.is_absolute():
917 raise NotAbsolute(name)
918 while 1:
919 try:
920 answer = resolver.query(name, dns.rdatatype.SOA, rdclass, tcp)
921 if answer.rrset.name == name:
922 return name
923 # otherwise we were CNAMEd or DNAMEd and need to look higher
924 except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
925 pass
926 try:
927 name = name.parent()
928 except dns.name.NoParent:
929 raise NoRootSOA
932 # Support for overriding the system resolver for all python code in the
933 # running process.
936 _protocols_for_socktype = {
937 socket.SOCK_DGRAM : [socket.SOL_UDP],
938 socket.SOCK_STREAM : [socket.SOL_TCP],
941 _resolver = None
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,
950 proto=0, flags=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)
955 v6addrs = []
956 v4addrs = []
957 canonical_name = None
958 try:
959 # Is host None or a V6 address literal?
960 if host is None:
961 canonical_name = 'localhost'
962 if flags & socket.AI_PASSIVE != 0:
963 v6addrs.append('::')
964 v4addrs.append('0.0.0.0')
965 else:
966 v6addrs.append('::1')
967 v4addrs.append('127.0.0.1')
968 else:
969 parts = host.split('%')
970 if len(parts) == 2:
971 ahost = parts[0]
972 else:
973 ahost = host
974 addr = dns.ipv6.inet_aton(ahost)
975 v6addrs.append(host)
976 canonical_name = host
977 except:
978 try:
979 # Is it a V4 address literal?
980 addr = dns.ipv4.inet_aton(host)
981 v4addrs.append(host)
982 canonical_name = host
983 except:
984 if flags & socket.AI_NUMERICHOST == 0:
985 try:
986 qname = None
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.
992 host = v6.qname
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)
1000 host = v4.qname
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)
1007 except:
1008 raise socket.gaierror(socket.EAI_SYSTEM)
1009 port = None
1010 try:
1011 # Is it a port literal?
1012 if service is None:
1013 port = 0
1014 else:
1015 port = int(service)
1016 except:
1017 if flags & socket.AI_NUMERICSERV == 0:
1018 try:
1019 port = socket.getservbyname(service)
1020 except:
1021 pass
1022 if port is None:
1023 raise socket.gaierror(socket.EAI_NONAME)
1024 tuples = []
1025 if socktype == 0:
1026 socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM]
1027 else:
1028 socktypes = [socktype]
1029 if flags & socket.AI_CANONNAME != 0:
1030 cname = canonical_name
1031 else:
1032 cname = ''
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)
1047 return tuples
1049 def _getnameinfo(sockaddr, flags=0):
1050 host = sockaddr[0]
1051 port = sockaddr[1]
1052 if len(sockaddr) == 4:
1053 scope = sockaddr[3]
1054 family = socket.AF_INET6
1055 else:
1056 scope = None
1057 family = socket.AF_INET
1058 tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM,
1059 socket.SOL_TCP, 0)
1060 if len(tuples) > 1:
1061 raise socket.error('sockaddr resolved to multiple addresses')
1062 addr = tuples[0][4][0]
1063 if flags & socket.NI_DGRAM:
1064 pname = 'udp'
1065 else:
1066 pname = 'tcp'
1067 qname = dns.reversename.from_address(addr)
1068 if flags & socket.NI_NUMERICHOST == 0:
1069 try:
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)
1075 hostname = addr
1076 if scope is not None:
1077 hostname += '%' + str(scope)
1078 else:
1079 hostname = addr
1080 if scope is not None:
1081 hostname += '%' + str(scope)
1082 if flags & socket.NI_NUMERICSERV:
1083 service = str(port)
1084 else:
1085 service = socket.getservbyport(port, pname)
1086 return (hostname, service)
1088 def _getfqdn(name=None):
1089 if name is 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):
1097 aliases = []
1098 addresses = []
1099 tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM,
1100 socket.SOL_TCP, socket.AI_CANONNAME)
1101 canonical = tuples[0][3]
1102 for item in tuples:
1103 addresses.append(item[4][0])
1104 # XXX we just ignore aliases
1105 return (canonical, aliases, addresses)
1107 def _gethostbyaddr(ip):
1108 try:
1109 addr = dns.ipv6.inet_aton(ip)
1110 sockaddr = (ip, 80, 0, 0)
1111 family = socket.AF_INET6
1112 except:
1113 sockaddr = (ip, 80)
1114 family = socket.AF_INET
1115 (name, port) = _getnameinfo(sockaddr, socket.NI_NAMEREQD)
1116 aliases = []
1117 addresses = []
1118 tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP,
1119 socket.AI_CANONNAME)
1120 canonical = tuples[0][3]
1121 for item in tuples:
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()
1142 global _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().
1154 global _resolver
1155 _resolver = None
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