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