1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """DNS stub resolver.
17
18 @var default_resolver: The default resolver object
19 @type default_resolver: dns.resolver.Resolver object"""
20
21 import socket
22 import sys
23 import time
24 import random
25
26 try:
27 import threading as _threading
28 except ImportError:
29 import dummy_threading as _threading
30
31 import dns.exception
32 import dns.flags
33 import dns.ipv4
34 import dns.ipv6
35 import dns.message
36 import dns.name
37 import dns.query
38 import dns.rcode
39 import dns.rdataclass
40 import dns.rdatatype
41 import dns.reversename
42
43 if sys.platform == 'win32':
44 import _winreg
45
46 -class NXDOMAIN(dns.exception.DNSException):
47 """The DNS query name does not exist."""
48 supp_kwargs = set(['qname'])
49
51 if not 'qname' in self.kwargs:
52 return super(NXDOMAIN, self).__str__()
53
54 qname = self.kwargs['qname']
55 msg = self.__doc__[:-1]
56 if isinstance(qname, (list, set)):
57 if len(qname) > 1:
58 msg = 'None of DNS query names exist'
59 qname = list(map(str, qname))
60 else:
61 qname = qname[0]
62 return "%s: %s" % (msg, (str(qname)))
63
64 -class YXDOMAIN(dns.exception.DNSException):
65 """The DNS query name is too long after DNAME substitution."""
66
67
68
69
70
71 Timeout = dns.exception.Timeout
72
73
74 -class NoAnswer(dns.exception.DNSException):
75 """The DNS response does not contain an answer to the question."""
76 fmt = '%s: {query}' % __doc__[:-1]
77 supp_kwargs = set(['response'])
78
82
84 """All nameservers failed to answer the query.
85
86 @param errors: list of servers and respective errors
87 @type errors: [(server ip address, any object convertible to string)]
88 Non-empty errors list will add explanatory message ()
89 """
90
91 msg = "All nameservers failed to answer the query."
92 fmt = "%s {query}: {errors}" % msg[:-1]
93 supp_kwargs = set(['request', 'errors'])
94
96 srv_msgs = []
97 for err in kwargs['errors']:
98 srv_msgs.append('Server %s %s port %s anwered %s' % (err[0],
99 'TCP' if err[1] else 'UDP', err[2], err[3]))
100 return super(NoNameservers, self)._fmt_kwargs(
101 query=kwargs['request'].question, errors='; '.join(srv_msgs))
102
103
105 """An absolute domain name is required but a relative name was provided."""
106
108 """There is no SOA RR at the DNS root name. This should never happen!"""
109
112
114 """DNS stub resolver answer
115
116 Instances of this class bundle up the result of a successful DNS
117 resolution.
118
119 For convenience, the answer object implements much of the sequence
120 protocol, forwarding to its rrset. E.g. "for a in answer" is
121 equivalent to "for a in answer.rrset", "answer[i]" is equivalent
122 to "answer.rrset[i]", and "answer[i:j]" is equivalent to
123 "answer.rrset[i:j]".
124
125 Note that CNAMEs or DNAMEs in the response may mean that answer
126 node's name might not be the query name.
127
128 @ivar qname: The query name
129 @type qname: dns.name.Name object
130 @ivar rdtype: The query type
131 @type rdtype: int
132 @ivar rdclass: The query class
133 @type rdclass: int
134 @ivar response: The response message
135 @type response: dns.message.Message object
136 @ivar rrset: The answer
137 @type rrset: dns.rrset.RRset object
138 @ivar expiration: The time when the answer expires
139 @type expiration: float (seconds since the epoch)
140 @ivar canonical_name: The canonical name of the query name
141 @type canonical_name: dns.name.Name object
142 """
143 - def __init__(self, qname, rdtype, rdclass, response,
144 raise_on_no_answer=True):
145 self.qname = qname
146 self.rdtype = rdtype
147 self.rdclass = rdclass
148 self.response = response
149 min_ttl = -1
150 rrset = None
151 for count in xrange(0, 15):
152 try:
153 rrset = response.find_rrset(response.answer, qname,
154 rdclass, rdtype)
155 if min_ttl == -1 or rrset.ttl < min_ttl:
156 min_ttl = rrset.ttl
157 break
158 except KeyError:
159 if rdtype != dns.rdatatype.CNAME:
160 try:
161 crrset = response.find_rrset(response.answer,
162 qname,
163 rdclass,
164 dns.rdatatype.CNAME)
165 if min_ttl == -1 or crrset.ttl < min_ttl:
166 min_ttl = crrset.ttl
167 for rd in crrset:
168 qname = rd.target
169 break
170 continue
171 except KeyError:
172 if raise_on_no_answer:
173 raise NoAnswer(response=response)
174 if raise_on_no_answer:
175 raise NoAnswer(response=response)
176 if rrset is None and raise_on_no_answer:
177 raise NoAnswer(response=response)
178 self.canonical_name = qname
179 self.rrset = rrset
180 if rrset is None:
181 while 1:
182
183
184 try:
185 srrset = response.find_rrset(response.authority, qname,
186 rdclass, dns.rdatatype.SOA)
187 if min_ttl == -1 or srrset.ttl < min_ttl:
188 min_ttl = srrset.ttl
189 if srrset[0].minimum < min_ttl:
190 min_ttl = srrset[0].minimum
191 break
192 except KeyError:
193 try:
194 qname = qname.parent()
195 except dns.name.NoParent:
196 break
197 self.expiration = time.time() + min_ttl
198
200 if attr == 'name':
201 return self.rrset.name
202 elif attr == 'ttl':
203 return self.rrset.ttl
204 elif attr == 'covers':
205 return self.rrset.covers
206 elif attr == 'rdclass':
207 return self.rrset.rdclass
208 elif attr == 'rdtype':
209 return self.rrset.rdtype
210 else:
211 raise AttributeError(attr)
212
214 return len(self.rrset)
215
217 return iter(self.rrset)
218
221
224
226 return self.rrset[i:j]
227
230
232 """Simple DNS answer cache.
233
234 @ivar data: A dictionary of cached data
235 @type data: dict
236 @ivar cleaning_interval: The number of seconds between cleanings. The
237 default is 300 (5 minutes).
238 @type cleaning_interval: float
239 @ivar next_cleaning: The time the cache should next be cleaned (in seconds
240 since the epoch.)
241 @type next_cleaning: float
242 """
243
244 - def __init__(self, cleaning_interval=300.0):
245 """Initialize a DNS cache.
246
247 @param cleaning_interval: the number of seconds between periodic
248 cleanings. The default is 300.0
249 @type cleaning_interval: float.
250 """
251
252 self.data = {}
253 self.cleaning_interval = cleaning_interval
254 self.next_cleaning = time.time() + self.cleaning_interval
255 self.lock = _threading.Lock()
256
258 """Clean the cache if it's time to do so."""
259
260 now = time.time()
261 if self.next_cleaning <= now:
262 keys_to_delete = []
263 for (k, v) in self.data.iteritems():
264 if v.expiration <= now:
265 keys_to_delete.append(k)
266 for k in keys_to_delete:
267 del self.data[k]
268 now = time.time()
269 self.next_cleaning = now + self.cleaning_interval
270
271 - def get(self, key):
272 """Get the answer associated with I{key}. Returns None if
273 no answer is cached for the key.
274 @param key: the key
275 @type key: (dns.name.Name, int, int) tuple whose values are the
276 query name, rdtype, and rdclass.
277 @rtype: dns.resolver.Answer object or None
278 """
279
280 try:
281 self.lock.acquire()
282 self._maybe_clean()
283 v = self.data.get(key)
284 if v is None or v.expiration <= time.time():
285 return None
286 return v
287 finally:
288 self.lock.release()
289
290 - def put(self, key, value):
291 """Associate key and value in the cache.
292 @param key: the key
293 @type key: (dns.name.Name, int, int) tuple whose values are the
294 query name, rdtype, and rdclass.
295 @param value: The answer being cached
296 @type value: dns.resolver.Answer object
297 """
298
299 try:
300 self.lock.acquire()
301 self._maybe_clean()
302 self.data[key] = value
303 finally:
304 self.lock.release()
305
306 - def flush(self, key=None):
307 """Flush the cache.
308
309 If I{key} is specified, only that item is flushed. Otherwise
310 the entire cache is flushed.
311
312 @param key: the key to flush
313 @type key: (dns.name.Name, int, int) tuple or None
314 """
315
316 try:
317 self.lock.acquire()
318 if not key is None:
319 if self.data.has_key(key):
320 del self.data[key]
321 else:
322 self.data = {}
323 self.next_cleaning = time.time() + self.cleaning_interval
324 finally:
325 self.lock.release()
326
328 """LRUCache node.
329 """
335
341
347
349 self.next.prev = self.prev
350 self.prev.next = self.next
351
353 """Bounded least-recently-used DNS answer cache.
354
355 This cache is better than the simple cache (above) if you're
356 running a web crawler or other process that does a lot of
357 resolutions. The LRUCache has a maximum number of nodes, and when
358 it is full, the least-recently used node is removed to make space
359 for a new one.
360
361 @ivar data: A dictionary of cached data
362 @type data: dict
363 @ivar sentinel: sentinel node for circular doubly linked list of nodes
364 @type sentinel: LRUCacheNode object
365 @ivar max_size: The maximum number of nodes
366 @type max_size: int
367 """
368
370 """Initialize a DNS cache.
371
372 @param max_size: The maximum number of nodes to cache; the default is 100000. Must be > 1.
373 @type max_size: int
374 """
375 self.data = {}
376 self.set_max_size(max_size)
377 self.sentinel = LRUCacheNode(None, None)
378 self.lock = _threading.Lock()
379
381 if max_size < 1:
382 max_size = 1
383 self.max_size = max_size
384
385 - def get(self, key):
386 """Get the answer associated with I{key}. Returns None if
387 no answer is cached for the key.
388 @param key: the key
389 @type key: (dns.name.Name, int, int) tuple whose values are the
390 query name, rdtype, and rdclass.
391 @rtype: dns.resolver.Answer object or None
392 """
393 try:
394 self.lock.acquire()
395 node = self.data.get(key)
396 if node is None:
397 return None
398
399
400 node.unlink()
401 if node.value.expiration <= time.time():
402 del self.data[node.key]
403 return None
404 node.link_after(self.sentinel)
405 return node.value
406 finally:
407 self.lock.release()
408
409 - def put(self, key, value):
410 """Associate key and value in the cache.
411 @param key: the key
412 @type key: (dns.name.Name, int, int) tuple whose values are the
413 query name, rdtype, and rdclass.
414 @param value: The answer being cached
415 @type value: dns.resolver.Answer object
416 """
417 try:
418 self.lock.acquire()
419 node = self.data.get(key)
420 if not node is None:
421 node.unlink()
422 del self.data[node.key]
423 while len(self.data) >= self.max_size:
424 node = self.sentinel.prev
425 node.unlink()
426 del self.data[node.key]
427 node = LRUCacheNode(key, value)
428 node.link_after(self.sentinel)
429 self.data[key] = node
430 finally:
431 self.lock.release()
432
433 - def flush(self, key=None):
434 """Flush the cache.
435
436 If I{key} is specified, only that item is flushed. Otherwise
437 the entire cache is flushed.
438
439 @param key: the key to flush
440 @type key: (dns.name.Name, int, int) tuple or None
441 """
442 try:
443 self.lock.acquire()
444 if not key is None:
445 node = self.data.get(key)
446 if not node is None:
447 node.unlink()
448 del self.data[node.key]
449 else:
450 node = self.sentinel.next
451 while node != self.sentinel:
452 next = node.next
453 node.prev = None
454 node.next = None
455 node = next
456 self.data = {}
457 finally:
458 self.lock.release()
459
461 """DNS stub resolver
462
463 @ivar domain: The domain of this host
464 @type domain: dns.name.Name object
465 @ivar nameservers: A list of nameservers to query. Each nameserver is
466 a string which contains the IP address of a nameserver.
467 @type nameservers: list of strings
468 @ivar search: The search list. If the query name is a relative name,
469 the resolver will construct an absolute query name by appending the search
470 names one by one to the query name.
471 @type search: list of dns.name.Name objects
472 @ivar port: The port to which to send queries. The default is 53.
473 @type port: int
474 @ivar timeout: The number of seconds to wait for a response from a
475 server, before timing out.
476 @type timeout: float
477 @ivar lifetime: The total number of seconds to spend trying to get an
478 answer to the question. If the lifetime expires, a Timeout exception
479 will occur.
480 @type lifetime: float
481 @ivar keyring: The TSIG keyring to use. The default is None.
482 @type keyring: dict
483 @ivar keyname: The TSIG keyname to use. The default is None.
484 @type keyname: dns.name.Name object
485 @ivar keyalgorithm: The TSIG key algorithm to use. The default is
486 dns.tsig.default_algorithm.
487 @type keyalgorithm: string
488 @ivar edns: The EDNS level to use. The default is -1, no Edns.
489 @type edns: int
490 @ivar ednsflags: The EDNS flags
491 @type ednsflags: int
492 @ivar payload: The EDNS payload size. The default is 0.
493 @type payload: int
494 @ivar flags: The message flags to use. The default is None (i.e. not overwritten)
495 @type flags: int
496 @ivar cache: The cache to use. The default is None.
497 @type cache: dns.resolver.Cache object
498 @ivar retry_servfail: should we retry a nameserver if it says SERVFAIL?
499 The default is 'false'.
500 @type retry_servfail: bool
501 """
502 - def __init__(self, filename='/etc/resolv.conf', configure=True):
503 """Initialize a resolver instance.
504
505 @param filename: The filename of a configuration file in
506 standard /etc/resolv.conf format. This parameter is meaningful
507 only when I{configure} is true and the platform is POSIX.
508 @type filename: string or file object
509 @param configure: If True (the default), the resolver instance
510 is configured in the normal fashion for the operating system
511 the resolver is running on. (I.e. a /etc/resolv.conf file on
512 POSIX systems and from the registry on Windows systems.)
513 @type configure: bool"""
514
515 self.reset()
516 if configure:
517 if sys.platform == 'win32':
518 self.read_registry()
519 elif filename:
520 self.read_resolv_conf(filename)
521
523 """Reset all resolver configuration to the defaults."""
524 self.domain = \
525 dns.name.Name(dns.name.from_text(socket.gethostname())[1:])
526 if len(self.domain) == 0:
527 self.domain = dns.name.root
528 self.nameservers = []
529 self.nameserver_ports = {}
530 self.port = 53
531 self.search = []
532 self.timeout = 2.0
533 self.lifetime = 30.0
534 self.keyring = None
535 self.keyname = None
536 self.keyalgorithm = dns.tsig.default_algorithm
537 self.edns = -1
538 self.ednsflags = 0
539 self.payload = 0
540 self.cache = None
541 self.flags = None
542 self.retry_servfail = False
543 self.rotate = False
544
546 """Process f as a file in the /etc/resolv.conf format. If f is
547 a string, it is used as the name of the file to open; otherwise it
548 is treated as the file itself."""
549 if isinstance(f, str) or isinstance(f, unicode):
550 try:
551 f = open(f, 'r')
552 except IOError:
553
554
555 self.nameservers = ['127.0.0.1']
556 return
557 want_close = True
558 else:
559 want_close = False
560 try:
561 for l in f:
562 if len(l) == 0 or l[0] == '#' or l[0] == ';':
563 continue
564 tokens = l.split()
565 if len(tokens) == 0:
566 continue
567 if tokens[0] == 'nameserver':
568 self.nameservers.append(tokens[1])
569 elif tokens[0] == 'domain':
570 self.domain = dns.name.from_text(tokens[1])
571 elif tokens[0] == 'search':
572 for suffix in tokens[1:]:
573 self.search.append(dns.name.from_text(suffix))
574 elif tokens[0] == 'options':
575 if 'rotate' in tokens[1:]:
576 self.rotate = True
577 finally:
578 if want_close:
579 f.close()
580 if len(self.nameservers) == 0:
581 self.nameservers.append('127.0.0.1')
582
584
585
586
587
588
589 if entry.find(' ') >= 0:
590 split_char = ' '
591 elif entry.find(',') >= 0:
592 split_char = ','
593 else:
594
595 split_char = ' '
596 return split_char
597
599 """Configure a NameServer registry entry."""
600
601 nameservers = str(nameservers)
602 split_char = self._determine_split_char(nameservers)
603 ns_list = nameservers.split(split_char)
604 for ns in ns_list:
605 if not ns in self.nameservers:
606 self.nameservers.append(ns)
607
608 - def _config_win32_domain(self, domain):
609 """Configure a Domain registry entry."""
610
611 self.domain = dns.name.from_text(str(domain))
612
614 """Configure a Search registry entry."""
615
616 search = str(search)
617 split_char = self._determine_split_char(search)
618 search_list = search.split(split_char)
619 for s in search_list:
620 if not s in self.search:
621 self.search.append(dns.name.from_text(s))
622
624 """Extract DNS info from a registry key."""
625 try:
626 servers, rtype = _winreg.QueryValueEx(key, 'NameServer')
627 except WindowsError:
628 servers = None
629 if servers:
630 self._config_win32_nameservers(servers)
631 try:
632 dom, rtype = _winreg.QueryValueEx(key, 'Domain')
633 if dom:
634 self._config_win32_domain(dom)
635 except WindowsError:
636 pass
637 else:
638 try:
639 servers, rtype = _winreg.QueryValueEx(key, 'DhcpNameServer')
640 except WindowsError:
641 servers = None
642 if servers:
643 self._config_win32_nameservers(servers)
644 try:
645 dom, rtype = _winreg.QueryValueEx(key, 'DhcpDomain')
646 if dom:
647 self._config_win32_domain(dom)
648 except WindowsError:
649 pass
650 try:
651 search, rtype = _winreg.QueryValueEx(key, 'SearchList')
652 except WindowsError:
653 search = None
654 if search:
655 self._config_win32_search(search)
656
658 """Extract resolver configuration from the Windows registry."""
659 lm = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
660 want_scan = False
661 try:
662 try:
663
664 tcp_params = _winreg.OpenKey(lm,
665 r'SYSTEM\CurrentControlSet'
666 r'\Services\Tcpip\Parameters')
667 want_scan = True
668 except EnvironmentError:
669
670 tcp_params = _winreg.OpenKey(lm,
671 r'SYSTEM\CurrentControlSet'
672 r'\Services\VxD\MSTCP')
673 try:
674 self._config_win32_fromkey(tcp_params)
675 finally:
676 tcp_params.Close()
677 if want_scan:
678 interfaces = _winreg.OpenKey(lm,
679 r'SYSTEM\CurrentControlSet'
680 r'\Services\Tcpip\Parameters'
681 r'\Interfaces')
682 try:
683 i = 0
684 while True:
685 try:
686 guid = _winreg.EnumKey(interfaces, i)
687 i += 1
688 key = _winreg.OpenKey(interfaces, guid)
689 if not self._win32_is_nic_enabled(lm, guid, key):
690 continue
691 try:
692 self._config_win32_fromkey(key)
693 finally:
694 key.Close()
695 except EnvironmentError:
696 break
697 finally:
698 interfaces.Close()
699 finally:
700 lm.Close()
701
703
704
705
706
707
708 try:
709
710
711 connection_key = _winreg.OpenKey(
712 lm,
713 r'SYSTEM\CurrentControlSet\Control\Network'
714 r'\{4D36E972-E325-11CE-BFC1-08002BE10318}'
715 r'\%s\Connection' % guid)
716
717 try:
718
719 (pnp_id, ttype) = _winreg.QueryValueEx(
720 connection_key, 'PnpInstanceID')
721
722 if ttype != _winreg.REG_SZ:
723 raise ValueError
724
725 device_key = _winreg.OpenKey(
726 lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id)
727
728 try:
729
730 (flags, ttype) = _winreg.QueryValueEx(
731 device_key, 'ConfigFlags')
732
733 if ttype != _winreg.REG_DWORD:
734 raise ValueError
735
736
737
738 return not (flags & 0x1)
739
740 finally:
741 device_key.Close()
742 finally:
743 connection_key.Close()
744 except (EnvironmentError, ValueError):
745
746
747
748
749
750 try:
751 (nte, ttype) = _winreg.QueryValueEx(interface_key,
752 'NTEContextList')
753 return nte is not None
754 except WindowsError:
755 return False
756
758 now = time.time()
759 duration = now - start
760 if duration < 0:
761 if duration < -1:
762
763 raise Timeout(timeout=duration)
764 else:
765
766
767
768 now = start
769 if duration >= self.lifetime:
770 raise Timeout(timeout=duration)
771 return min(self.lifetime - duration, self.timeout)
772
775 """Query nameservers to find the answer to the question.
776
777 The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
778 of the appropriate type, or strings that can be converted into objects
779 of the appropriate type. E.g. For I{rdtype} the integer 2 and the
780 the string 'NS' both mean to query for records with DNS rdata type NS.
781
782 @param qname: the query name
783 @type qname: dns.name.Name object or string
784 @param rdtype: the query type
785 @type rdtype: int or string
786 @param rdclass: the query class
787 @type rdclass: int or string
788 @param tcp: use TCP to make the query (default is False).
789 @type tcp: bool
790 @param source: bind to this IP address (defaults to machine default IP).
791 @type source: IP address in dotted quad notation
792 @param raise_on_no_answer: raise NoAnswer if there's no answer
793 (defaults is True).
794 @type raise_on_no_answer: bool
795 @param source_port: The port from which to send the message.
796 The default is 0.
797 @type source_port: int
798 @rtype: dns.resolver.Answer instance
799 @raises Timeout: no answers could be found in the specified lifetime
800 @raises NXDOMAIN: the query name does not exist
801 @raises YXDOMAIN: the query name is too long after DNAME substitution
802 @raises NoAnswer: the response did not contain an answer and
803 raise_on_no_answer is True.
804 @raises NoNameservers: no non-broken nameservers are available to
805 answer the question."""
806
807 if isinstance(qname, (str, unicode)):
808 qname = dns.name.from_text(qname, None)
809 if isinstance(rdtype, (str, unicode)):
810 rdtype = dns.rdatatype.from_text(rdtype)
811 if dns.rdatatype.is_metatype(rdtype):
812 raise NoMetaqueries
813 if isinstance(rdclass, (str, unicode)):
814 rdclass = dns.rdataclass.from_text(rdclass)
815 if dns.rdataclass.is_metaclass(rdclass):
816 raise NoMetaqueries
817 qnames_to_try = []
818 if qname.is_absolute():
819 qnames_to_try.append(qname)
820 else:
821 if len(qname) > 1:
822 qnames_to_try.append(qname.concatenate(dns.name.root))
823 if self.search:
824 for suffix in self.search:
825 qnames_to_try.append(qname.concatenate(suffix))
826 else:
827 qnames_to_try.append(qname.concatenate(self.domain))
828 all_nxdomain = True
829 start = time.time()
830 for qname in qnames_to_try:
831 if self.cache:
832 answer = self.cache.get((qname, rdtype, rdclass))
833 if not answer is None:
834 if answer.rrset is None and raise_on_no_answer:
835 raise NoAnswer
836 else:
837 return answer
838 request = dns.message.make_query(qname, rdtype, rdclass)
839 if not self.keyname is None:
840 request.use_tsig(self.keyring, self.keyname,
841 algorithm=self.keyalgorithm)
842 request.use_edns(self.edns, self.ednsflags, self.payload)
843 if self.flags is not None:
844 request.flags = self.flags
845 response = None
846
847
848
849 nameservers = self.nameservers[:]
850 errors = []
851 if self.rotate:
852 random.shuffle(nameservers)
853 backoff = 0.10
854 while response is None:
855 if len(nameservers) == 0:
856 raise NoNameservers(request=request, errors=errors)
857 for nameserver in nameservers[:]:
858 timeout = self._compute_timeout(start)
859 port = self.nameserver_ports.get(nameserver, self.port)
860 try:
861 tcp_attempt = tcp
862 if tcp:
863 response = dns.query.tcp(request, nameserver,
864 timeout, port,
865 source=source,
866 source_port=source_port)
867 else:
868 response = dns.query.udp(request, nameserver,
869 timeout, port,
870 source=source,
871 source_port=source_port)
872 if response.flags & dns.flags.TC:
873
874 tcp_attempt = True
875 timeout = self._compute_timeout(start)
876 response = dns.query.tcp(request, nameserver,
877 timeout, port,
878 source=source,
879 source_port=source_port)
880 except (socket.error, dns.exception.Timeout) as ex:
881
882
883
884
885 errors.append((nameserver, tcp_attempt, port, ex,
886 response))
887 response = None
888 continue
889 except dns.query.UnexpectedSource as ex:
890
891
892
893 errors.append((nameserver, tcp_attempt, port, ex,
894 response))
895 response = None
896 continue
897 except dns.exception.FormError as ex:
898
899
900
901
902
903 nameservers.remove(nameserver)
904 errors.append((nameserver, tcp_attempt, port, ex,
905 response))
906 response = None
907 continue
908 except EOFError as ex:
909
910
911
912
913
914
915 nameservers.remove(nameserver)
916 errors.append((nameserver, tcp_attempt, port, ex,
917 response))
918 response = None
919 continue
920 rcode = response.rcode()
921 if rcode == dns.rcode.YXDOMAIN:
922 ex = YXDOMAIN()
923 errors.append((nameserver, tcp_attempt, port, ex,
924 response))
925 raise ex
926 if rcode == dns.rcode.NOERROR or \
927 rcode == dns.rcode.NXDOMAIN:
928 break
929
930
931
932
933
934 if rcode != dns.rcode.SERVFAIL or not self.retry_servfail:
935 nameservers.remove(nameserver)
936 errors.append((nameserver, tcp_attempt, port,
937 dns.rcode.to_text(rcode), response))
938 response = None
939 if not response is None:
940 break
941
942
943
944 if len(nameservers) > 0:
945
946
947
948
949 timeout = self._compute_timeout(start)
950 sleep_time = min(timeout, backoff)
951 backoff *= 2
952 time.sleep(sleep_time)
953 if response.rcode() == dns.rcode.NXDOMAIN:
954 continue
955 all_nxdomain = False
956 break
957 if all_nxdomain:
958 raise NXDOMAIN(qname=qnames_to_try)
959 answer = Answer(qname, rdtype, rdclass, response,
960 raise_on_no_answer)
961 if self.cache:
962 self.cache.put((qname, rdtype, rdclass), answer)
963 return answer
964
967 """Add a TSIG signature to the query.
968
969 @param keyring: The TSIG keyring to use; defaults to None.
970 @type keyring: dict
971 @param keyname: The name of the TSIG key to use; defaults to None.
972 The key must be defined in the keyring. If a keyring is specified
973 but a keyname is not, then the key used will be the first key in the
974 keyring. Note that the order of keys in a dictionary is not defined,
975 so applications should supply a keyname when a keyring is used, unless
976 they know the keyring contains only one key.
977 @param algorithm: The TSIG key algorithm to use. The default
978 is dns.tsig.default_algorithm.
979 @type algorithm: string"""
980 self.keyring = keyring
981 if keyname is None:
982 self.keyname = self.keyring.keys()[0]
983 else:
984 self.keyname = keyname
985 self.keyalgorithm = algorithm
986
987 - def use_edns(self, edns, ednsflags, payload):
988 """Configure Edns.
989
990 @param edns: The EDNS level to use. The default is -1, no Edns.
991 @type edns: int
992 @param ednsflags: The EDNS flags
993 @type ednsflags: int
994 @param payload: The EDNS payload size. The default is 0.
995 @type payload: int"""
996
997 if edns is None:
998 edns = -1
999 self.edns = edns
1000 self.ednsflags = ednsflags
1001 self.payload = payload
1002
1004 """Overrides the default flags with your own
1005
1006 @param flags: The flags to overwrite the default with
1007 @type flags: int"""
1008 self.flags = flags
1009
1010 default_resolver = None
1011
1018
1022 """Query nameservers to find the answer to the question.
1023
1024 This is a convenience function that uses the default resolver
1025 object to make the query.
1026 @see: L{dns.resolver.Resolver.query} for more information on the
1027 parameters."""
1028 return get_default_resolver().query(qname, rdtype, rdclass, tcp, source,
1029 raise_on_no_answer, source_port)
1030
1062
1063
1064
1065
1066
1067
1068 _protocols_for_socktype = {
1069 socket.SOCK_DGRAM : [socket.SOL_UDP],
1070 socket.SOCK_STREAM : [socket.SOL_TCP],
1071 }
1072
1073 _resolver = None
1074 _original_getaddrinfo = socket.getaddrinfo
1075 _original_getnameinfo = socket.getnameinfo
1076 _original_getfqdn = socket.getfqdn
1077 _original_gethostbyname = socket.gethostbyname
1078 _original_gethostbyname_ex = socket.gethostbyname_ex
1079 _original_gethostbyaddr = socket.gethostbyaddr
1080
1081 -def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0,
1082 proto=0, flags=0):
1083 if flags & (socket.AI_ADDRCONFIG|socket.AI_V4MAPPED) != 0:
1084 raise NotImplementedError
1085 if host is None and service is None:
1086 raise socket.gaierror(socket.EAI_NONAME)
1087 v6addrs = []
1088 v4addrs = []
1089 canonical_name = None
1090 try:
1091
1092 if host is None:
1093 canonical_name = 'localhost'
1094 if flags & socket.AI_PASSIVE != 0:
1095 v6addrs.append('::')
1096 v4addrs.append('0.0.0.0')
1097 else:
1098 v6addrs.append('::1')
1099 v4addrs.append('127.0.0.1')
1100 else:
1101 parts = host.split('%')
1102 if len(parts) == 2:
1103 ahost = parts[0]
1104 else:
1105 ahost = host
1106 addr = dns.ipv6.inet_aton(ahost)
1107 v6addrs.append(host)
1108 canonical_name = host
1109 except:
1110 try:
1111
1112 addr = dns.ipv4.inet_aton(host)
1113 v4addrs.append(host)
1114 canonical_name = host
1115 except:
1116 if flags & socket.AI_NUMERICHOST == 0:
1117 try:
1118 qname = None
1119 if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
1120 v6 = _resolver.query(host, dns.rdatatype.AAAA,
1121 raise_on_no_answer=False)
1122
1123
1124 host = v6.qname
1125 canonical_name = v6.canonical_name.to_text(True)
1126 if v6.rrset is not None:
1127 for rdata in v6.rrset:
1128 v6addrs.append(rdata.address)
1129 if family == socket.AF_INET or family == socket.AF_UNSPEC:
1130 v4 = _resolver.query(host, dns.rdatatype.A,
1131 raise_on_no_answer=False)
1132 host = v4.qname
1133 canonical_name = v4.canonical_name.to_text(True)
1134 if v4.rrset is not None:
1135 for rdata in v4.rrset:
1136 v4addrs.append(rdata.address)
1137 except dns.resolver.NXDOMAIN:
1138 raise socket.gaierror(socket.EAI_NONAME)
1139 except:
1140 raise socket.gaierror(socket.EAI_SYSTEM)
1141 port = None
1142 try:
1143
1144 if service is None:
1145 port = 0
1146 else:
1147 port = int(service)
1148 except:
1149 if flags & socket.AI_NUMERICSERV == 0:
1150 try:
1151 port = socket.getservbyname(service)
1152 except:
1153 pass
1154 if port is None:
1155 raise socket.gaierror(socket.EAI_NONAME)
1156 tuples = []
1157 if socktype == 0:
1158 socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM]
1159 else:
1160 socktypes = [socktype]
1161 if flags & socket.AI_CANONNAME != 0:
1162 cname = canonical_name
1163 else:
1164 cname = ''
1165 if family == socket.AF_INET6 or family == socket.AF_UNSPEC:
1166 for addr in v6addrs:
1167 for socktype in socktypes:
1168 for proto in _protocols_for_socktype[socktype]:
1169 tuples.append((socket.AF_INET6, socktype, proto,
1170 cname, (addr, port, 0, 0)))
1171 if family == socket.AF_INET or family == socket.AF_UNSPEC:
1172 for addr in v4addrs:
1173 for socktype in socktypes:
1174 for proto in _protocols_for_socktype[socktype]:
1175 tuples.append((socket.AF_INET, socktype, proto,
1176 cname, (addr, port)))
1177 if len(tuples) == 0:
1178 raise socket.gaierror(socket.EAI_NONAME)
1179 return tuples
1180
1182 host = sockaddr[0]
1183 port = sockaddr[1]
1184 if len(sockaddr) == 4:
1185 scope = sockaddr[3]
1186 family = socket.AF_INET6
1187 else:
1188 scope = None
1189 family = socket.AF_INET
1190 tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM,
1191 socket.SOL_TCP, 0)
1192 if len(tuples) > 1:
1193 raise socket.error('sockaddr resolved to multiple addresses')
1194 addr = tuples[0][4][0]
1195 if flags & socket.NI_DGRAM:
1196 pname = 'udp'
1197 else:
1198 pname = 'tcp'
1199 qname = dns.reversename.from_address(addr)
1200 if flags & socket.NI_NUMERICHOST == 0:
1201 try:
1202 answer = _resolver.query(qname, 'PTR')
1203 hostname = answer.rrset[0].target.to_text(True)
1204 except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
1205 if flags & socket.NI_NAMEREQD:
1206 raise socket.gaierror(socket.EAI_NONAME)
1207 hostname = addr
1208 if scope is not None:
1209 hostname += '%' + str(scope)
1210 else:
1211 hostname = addr
1212 if scope is not None:
1213 hostname += '%' + str(scope)
1214 if flags & socket.NI_NUMERICSERV:
1215 service = str(port)
1216 else:
1217 service = socket.getservbyport(port, pname)
1218 return (hostname, service)
1219
1221 if name is None:
1222 name = socket.gethostname()
1223 try:
1224 return _getnameinfo(_getaddrinfo(name, 80)[0][4])[0]
1225 except:
1226 return name
1227
1229 return _gethostbyname_ex(name)[2][0]
1230
1232 aliases = []
1233 addresses = []
1234 tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM,
1235 socket.SOL_TCP, socket.AI_CANONNAME)
1236 canonical = tuples[0][3]
1237 for item in tuples:
1238 addresses.append(item[4][0])
1239
1240 return (canonical, aliases, addresses)
1241
1243 try:
1244 addr = dns.ipv6.inet_aton(ip)
1245 sockaddr = (ip, 80, 0, 0)
1246 family = socket.AF_INET6
1247 except:
1248 sockaddr = (ip, 80)
1249 family = socket.AF_INET
1250 (name, port) = _getnameinfo(sockaddr, socket.NI_NAMEREQD)
1251 aliases = []
1252 addresses = []
1253 tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP,
1254 socket.AI_CANONNAME)
1255 canonical = tuples[0][3]
1256 for item in tuples:
1257 addresses.append(item[4][0])
1258
1259 return (canonical, aliases, addresses)
1260
1262 """Override the system resolver routines in the socket module with
1263 versions which use dnspython's resolver.
1264
1265 This can be useful in testing situations where you want to control
1266 the resolution behavior of python code without having to change
1267 the system's resolver settings (e.g. /etc/resolv.conf).
1268
1269 The resolver to use may be specified; if it's not, the default
1270 resolver will be used.
1271
1272 @param resolver: the resolver to use
1273 @type resolver: dns.resolver.Resolver object or None
1274 """
1275 if resolver is None:
1276 resolver = get_default_resolver()
1277 global _resolver
1278 _resolver = resolver
1279 socket.getaddrinfo = _getaddrinfo
1280 socket.getnameinfo = _getnameinfo
1281 socket.getfqdn = _getfqdn
1282 socket.gethostbyname = _gethostbyname
1283 socket.gethostbyname_ex = _gethostbyname_ex
1284 socket.gethostbyaddr = _gethostbyaddr
1285
1287 """Undo the effects of override_system_resolver().
1288 """
1289 global _resolver
1290 _resolver = None
1291 socket.getaddrinfo = _original_getaddrinfo
1292 socket.getnameinfo = _original_getnameinfo
1293 socket.getfqdn = _original_getfqdn
1294 socket.gethostbyname = _original_gethostbyname
1295 socket.gethostbyname_ex = _original_gethostbyname_ex
1296 socket.gethostbyaddr = _original_gethostbyaddr
1297