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