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