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