1# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 2 3# Copyright (C) 2003-2017 Nominum, Inc. 4# 5# Permission to use, copy, modify, and distribute this software and its 6# documentation for any purpose with or without fee is hereby granted, 7# provided that the above copyright notice and this permission notice 8# appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 16# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18"""DNS stub resolver.""" 19from urllib.parse import urlparse 20import contextlib 21import socket 22import sys 23import time 24import random 25import warnings 26try: 27 import threading as _threading 28except ImportError: # pragma: no cover 29 import dummy_threading as _threading # type: ignore 30 31import dns.exception 32import dns.flags 33import dns.inet 34import dns.ipv4 35import dns.ipv6 36import dns.message 37import dns.name 38import dns.query 39import dns.rcode 40import dns.rdataclass 41import dns.rdatatype 42import dns.reversename 43import dns.tsig 44 45if sys.platform == 'win32': 46 import winreg # pragma: no cover 47 48class NXDOMAIN(dns.exception.DNSException): 49 """The DNS query name does not exist.""" 50 supp_kwargs = {'qnames', 'responses'} 51 fmt = None # we have our own __str__ implementation 52 53 def _check_kwargs(self, qnames, responses=None): 54 if not isinstance(qnames, (list, tuple, set)): 55 raise AttributeError("qnames must be a list, tuple or set") 56 if len(qnames) == 0: 57 raise AttributeError("qnames must contain at least one element") 58 if responses is None: 59 responses = {} 60 elif not isinstance(responses, dict): 61 raise AttributeError("responses must be a dict(qname=response)") 62 kwargs = dict(qnames=qnames, responses=responses) 63 return kwargs 64 65 def __str__(self): 66 if 'qnames' not in self.kwargs: 67 return super().__str__() 68 qnames = self.kwargs['qnames'] 69 if len(qnames) > 1: 70 msg = 'None of DNS query names exist' 71 else: 72 msg = 'The DNS query name does not exist' 73 qnames = ', '.join(map(str, qnames)) 74 return "{}: {}".format(msg, qnames) 75 76 @property 77 def canonical_name(self): 78 """Return the unresolved canonical name.""" 79 if 'qnames' not 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[0].target.to_text() 90 if cname is not None: 91 return dns.name.from_text(cname) 92 return self.kwargs['qnames'][0] 93 94 def __add__(self, e_nx): 95 """Augment by results from another NXDOMAIN exception.""" 96 qnames0 = list(self.kwargs.get('qnames', [])) 97 responses0 = dict(self.kwargs.get('responses', {})) 98 responses1 = e_nx.kwargs.get('responses', {}) 99 for qname1 in e_nx.kwargs.get('qnames', []): 100 if qname1 not in qnames0: 101 qnames0.append(qname1) 102 if qname1 in responses1: 103 responses0[qname1] = responses1[qname1] 104 return NXDOMAIN(qnames=qnames0, responses=responses0) 105 106 def qnames(self): 107 """All of the names that were tried. 108 109 Returns a list of ``dns.name.Name``. 110 """ 111 return self.kwargs['qnames'] 112 113 def responses(self): 114 """A map from queried names to their NXDOMAIN responses. 115 116 Returns a dict mapping a ``dns.name.Name`` to a 117 ``dns.message.Message``. 118 """ 119 return self.kwargs['responses'] 120 121 def response(self, qname): 122 """The response for query *qname*. 123 124 Returns a ``dns.message.Message``. 125 """ 126 return self.kwargs['responses'][qname] 127 128 129class YXDOMAIN(dns.exception.DNSException): 130 """The DNS query name is too long after DNAME substitution.""" 131 132# The definition of the Timeout exception has moved from here to the 133# dns.exception module. We keep dns.resolver.Timeout defined for 134# backwards compatibility. 135 136Timeout = dns.exception.Timeout 137 138 139class NoAnswer(dns.exception.DNSException): 140 """The DNS response does not contain an answer to the question.""" 141 fmt = 'The DNS response does not contain an answer ' + \ 142 'to the question: {query}' 143 supp_kwargs = {'response'} 144 145 def _fmt_kwargs(self, **kwargs): 146 return super()._fmt_kwargs(query=kwargs['response'].question) 147 148 149class NoNameservers(dns.exception.DNSException): 150 """All nameservers failed to answer the query. 151 152 errors: list of servers and respective errors 153 The type of errors is 154 [(server IP address, any object convertible to string)]. 155 Non-empty errors list will add explanatory message () 156 """ 157 158 msg = "All nameservers failed to answer the query." 159 fmt = "%s {query}: {errors}" % msg[:-1] 160 supp_kwargs = {'request', 'errors'} 161 162 def _fmt_kwargs(self, **kwargs): 163 srv_msgs = [] 164 for err in kwargs['errors']: 165 srv_msgs.append('Server {} {} port {} answered {}'.format(err[0], 166 'TCP' if err[1] else 'UDP', err[2], err[3])) 167 return super()._fmt_kwargs(query=kwargs['request'].question, 168 errors='; '.join(srv_msgs)) 169 170 171class NotAbsolute(dns.exception.DNSException): 172 """An absolute domain name is required but a relative name was provided.""" 173 174 175class NoRootSOA(dns.exception.DNSException): 176 """There is no SOA RR at the DNS root name. This should never happen!""" 177 178 179class NoMetaqueries(dns.exception.DNSException): 180 """DNS metaqueries are not allowed.""" 181 182class NoResolverConfiguration(dns.exception.DNSException): 183 """Resolver configuration could not be read or specified no nameservers.""" 184 185class Answer: 186 """DNS stub resolver answer. 187 188 Instances of this class bundle up the result of a successful DNS 189 resolution. 190 191 For convenience, the answer object implements much of the sequence 192 protocol, forwarding to its ``rrset`` attribute. E.g. 193 ``for a in answer`` is equivalent to ``for a in answer.rrset``. 194 ``answer[i]`` is equivalent to ``answer.rrset[i]``, and 195 ``answer[i:j]`` is equivalent to ``answer.rrset[i:j]``. 196 197 Note that CNAMEs or DNAMEs in the response may mean that answer 198 RRset's name might not be the query name. 199 """ 200 201 def __init__(self, qname, rdtype, rdclass, response, nameserver=None, 202 port=None): 203 self.qname = qname 204 self.rdtype = rdtype 205 self.rdclass = rdclass 206 self.response = response 207 self.nameserver = nameserver 208 self.port = port 209 min_ttl = -1 210 rrset = None 211 for count in range(0, 15): 212 try: 213 rrset = response.find_rrset(response.answer, qname, 214 rdclass, rdtype) 215 if min_ttl == -1 or rrset.ttl < min_ttl: 216 min_ttl = rrset.ttl 217 break 218 except KeyError: 219 if rdtype != dns.rdatatype.CNAME: 220 try: 221 crrset = response.find_rrset(response.answer, 222 qname, 223 rdclass, 224 dns.rdatatype.CNAME) 225 if min_ttl == -1 or crrset.ttl < min_ttl: 226 min_ttl = crrset.ttl 227 for rd in crrset: 228 qname = rd.target 229 break 230 continue 231 except KeyError: 232 # Exit the chaining loop 233 break 234 self.canonical_name = qname 235 self.rrset = rrset 236 if rrset is None: 237 while 1: 238 # Look for a SOA RR whose owner name is a superdomain 239 # of qname. 240 try: 241 srrset = response.find_rrset(response.authority, qname, 242 rdclass, dns.rdatatype.SOA) 243 if min_ttl == -1 or srrset.ttl < min_ttl: 244 min_ttl = srrset.ttl 245 if srrset[0].minimum < min_ttl: 246 min_ttl = srrset[0].minimum 247 break 248 except KeyError: 249 try: 250 qname = qname.parent() 251 except dns.name.NoParent: 252 break 253 self.expiration = time.time() + min_ttl 254 255 def __getattr__(self, attr): # pragma: no cover 256 if attr == 'name': 257 return self.rrset.name 258 elif attr == 'ttl': 259 return self.rrset.ttl 260 elif attr == 'covers': 261 return self.rrset.covers 262 elif attr == 'rdclass': 263 return self.rrset.rdclass 264 elif attr == 'rdtype': 265 return self.rrset.rdtype 266 else: 267 raise AttributeError(attr) 268 269 def __len__(self): 270 return self.rrset and len(self.rrset) or 0 271 272 def __iter__(self): 273 return self.rrset and iter(self.rrset) or iter(tuple()) 274 275 def __getitem__(self, i): 276 if self.rrset is None: 277 raise IndexError 278 return self.rrset[i] 279 280 def __delitem__(self, i): 281 if self.rrset is None: 282 raise IndexError 283 del self.rrset[i] 284 285 286class Cache: 287 """Simple thread-safe DNS answer cache.""" 288 289 def __init__(self, cleaning_interval=300.0): 290 """*cleaning_interval*, a ``float`` is the number of seconds between 291 periodic cleanings. 292 """ 293 294 self.data = {} 295 self.cleaning_interval = cleaning_interval 296 self.next_cleaning = time.time() + self.cleaning_interval 297 self.lock = _threading.Lock() 298 299 def _maybe_clean(self): 300 """Clean the cache if it's time to do so.""" 301 302 now = time.time() 303 if self.next_cleaning <= now: 304 keys_to_delete = [] 305 for (k, v) in self.data.items(): 306 if v.expiration <= now: 307 keys_to_delete.append(k) 308 for k in keys_to_delete: 309 del self.data[k] 310 now = time.time() 311 self.next_cleaning = now + self.cleaning_interval 312 313 def get(self, key): 314 """Get the answer associated with *key*. 315 316 Returns None if no answer is cached for the key. 317 318 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the 319 query name, rdtype, and rdclass respectively. 320 321 Returns a ``dns.resolver.Answer`` or ``None``. 322 """ 323 324 with self.lock: 325 self._maybe_clean() 326 v = self.data.get(key) 327 if v is None or v.expiration <= time.time(): 328 return None 329 return v 330 331 def put(self, key, value): 332 """Associate key and value in the cache. 333 334 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the 335 query name, rdtype, and rdclass respectively. 336 337 *value*, a ``dns.resolver.Answer``, the answer. 338 """ 339 340 with self.lock: 341 self._maybe_clean() 342 self.data[key] = value 343 344 def flush(self, key=None): 345 """Flush the cache. 346 347 If *key* is not ``None``, only that item is flushed. Otherwise 348 the entire cache is flushed. 349 350 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the 351 query name, rdtype, and rdclass respectively. 352 """ 353 354 with self.lock: 355 if key is not None: 356 if key in self.data: 357 del self.data[key] 358 else: 359 self.data = {} 360 self.next_cleaning = time.time() + self.cleaning_interval 361 362 363class LRUCacheNode: 364 """LRUCache node.""" 365 366 def __init__(self, key, value): 367 self.key = key 368 self.value = value 369 self.prev = self 370 self.next = self 371 372 def link_after(self, node): 373 self.prev = node 374 self.next = node.next 375 node.next.prev = self 376 node.next = self 377 378 def unlink(self): 379 self.next.prev = self.prev 380 self.prev.next = self.next 381 382 383class LRUCache: 384 """Thread-safe, bounded, least-recently-used DNS answer cache. 385 386 This cache is better than the simple cache (above) if you're 387 running a web crawler or other process that does a lot of 388 resolutions. The LRUCache has a maximum number of nodes, and when 389 it is full, the least-recently used node is removed to make space 390 for a new one. 391 """ 392 393 def __init__(self, max_size=100000): 394 """*max_size*, an ``int``, is the maximum number of nodes to cache; 395 it must be greater than 0. 396 """ 397 398 self.data = {} 399 self.set_max_size(max_size) 400 self.sentinel = LRUCacheNode(None, None) 401 self.sentinel.prev = self.sentinel 402 self.sentinel.next = self.sentinel 403 self.lock = _threading.Lock() 404 405 def set_max_size(self, max_size): 406 if max_size < 1: 407 max_size = 1 408 self.max_size = max_size 409 410 def get(self, key): 411 """Get the answer associated with *key*. 412 413 Returns None if no answer is cached for the key. 414 415 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the 416 query name, rdtype, and rdclass respectively. 417 418 Returns a ``dns.resolver.Answer`` or ``None``. 419 """ 420 421 with self.lock: 422 node = self.data.get(key) 423 if node is None: 424 return None 425 # Unlink because we're either going to move the node to the front 426 # of the LRU list or we're going to free it. 427 node.unlink() 428 if node.value.expiration <= time.time(): 429 del self.data[node.key] 430 return None 431 node.link_after(self.sentinel) 432 return node.value 433 434 def put(self, key, value): 435 """Associate key and value in the cache. 436 437 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the 438 query name, rdtype, and rdclass respectively. 439 440 *value*, a ``dns.resolver.Answer``, the answer. 441 """ 442 443 with self.lock: 444 node = self.data.get(key) 445 if node is not None: 446 node.unlink() 447 del self.data[node.key] 448 while len(self.data) >= self.max_size: 449 node = self.sentinel.prev 450 node.unlink() 451 del self.data[node.key] 452 node = LRUCacheNode(key, value) 453 node.link_after(self.sentinel) 454 self.data[key] = node 455 456 def flush(self, key=None): 457 """Flush the cache. 458 459 If *key* is not ``None``, only that item is flushed. Otherwise 460 the entire cache is flushed. 461 462 *key*, a ``(dns.name.Name, int, int)`` tuple whose values are the 463 query name, rdtype, and rdclass respectively. 464 """ 465 466 with self.lock: 467 if key is not None: 468 node = self.data.get(key) 469 if node is not None: 470 node.unlink() 471 del self.data[node.key] 472 else: 473 node = self.sentinel.next 474 while node != self.sentinel: 475 next = node.next 476 node.unlink() 477 node = next 478 self.data = {} 479 480class _Resolution: 481 """Helper class for dns.resolver.Resolver.resolve(). 482 483 All of the "business logic" of resolution is encapsulated in this 484 class, allowing us to have multiple resolve() implementations 485 using different I/O schemes without copying all of the 486 complicated logic. 487 488 This class is a "friend" to dns.resolver.Resolver and manipulates 489 resolver data structures directly. 490 """ 491 492 def __init__(self, resolver, qname, rdtype, rdclass, tcp, 493 raise_on_no_answer, search): 494 if isinstance(qname, str): 495 qname = dns.name.from_text(qname, None) 496 rdtype = dns.rdatatype.RdataType.make(rdtype) 497 if dns.rdatatype.is_metatype(rdtype): 498 raise NoMetaqueries 499 rdclass = dns.rdataclass.RdataClass.make(rdclass) 500 if dns.rdataclass.is_metaclass(rdclass): 501 raise NoMetaqueries 502 self.resolver = resolver 503 self.qnames_to_try = resolver._get_qnames_to_try(qname, search) 504 self.qnames = self.qnames_to_try[:] 505 self.rdtype = rdtype 506 self.rdclass = rdclass 507 self.tcp = tcp 508 self.raise_on_no_answer = raise_on_no_answer 509 self.nxdomain_responses = {} 510 # 511 # Initialize other things to help analysis tools 512 self.qname = dns.name.empty 513 self.nameservers = [] 514 self.current_nameservers = [] 515 self.errors = [] 516 self.nameserver = None 517 self.port = 0 518 self.tcp_attempt = False 519 self.retry_with_tcp = False 520 self.request = None 521 self.backoff = 0 522 523 def next_request(self): 524 """Get the next request to send, and check the cache. 525 526 Returns a (request, answer) tuple. At most one of request or 527 answer will not be None. 528 """ 529 530 # We return a tuple instead of Union[Message,Answer] as it lets 531 # the caller avoid isinstance(). 532 533 while len(self.qnames) > 0: 534 self.qname = self.qnames.pop(0) 535 536 # Do we know the answer? 537 if self.resolver.cache: 538 answer = self.resolver.cache.get((self.qname, self.rdtype, 539 self.rdclass)) 540 if answer is not None: 541 if answer.rrset is None and self.raise_on_no_answer: 542 raise NoAnswer(response=answer.response) 543 else: 544 return (None, answer) 545 answer = self.resolver.cache.get((self.qname, 546 dns.rdatatype.ANY, 547 self.rdclass)) 548 if answer is not None and \ 549 answer.response.rcode() == dns.rcode.NXDOMAIN: 550 # cached NXDOMAIN; record it and continue to next 551 # name. 552 self.nxdomain_responses[self.qname] = answer.response 553 continue 554 555 # Build the request 556 request = dns.message.make_query(self.qname, self.rdtype, 557 self.rdclass) 558 if self.resolver.keyname is not None: 559 request.use_tsig(self.resolver.keyring, self.resolver.keyname, 560 algorithm=self.resolver.keyalgorithm) 561 request.use_edns(self.resolver.edns, self.resolver.ednsflags, 562 self.resolver.payload) 563 if self.resolver.flags is not None: 564 request.flags = self.resolver.flags 565 566 self.nameservers = self.resolver.nameservers[:] 567 if self.resolver.rotate: 568 random.shuffle(self.nameservers) 569 self.current_nameservers = self.nameservers[:] 570 self.errors = [] 571 self.nameserver = None 572 self.tcp_attempt = False 573 self.retry_with_tcp = False 574 self.request = request 575 self.backoff = 0.10 576 577 return (request, None) 578 579 # 580 # We've tried everything and only gotten NXDOMAINs. (We know 581 # it's only NXDOMAINs as anything else would have returned 582 # before now.) 583 # 584 raise NXDOMAIN(qnames=self.qnames_to_try, 585 responses=self.nxdomain_responses) 586 587 def next_nameserver(self): 588 if self.retry_with_tcp: 589 assert self.nameserver is not None 590 self.tcp_attempt = True 591 self.retry_with_tcp = False 592 return (self.nameserver, self.port, True, 0) 593 594 backoff = 0 595 if not self.current_nameservers: 596 if len(self.nameservers) == 0: 597 # Out of things to try! 598 raise NoNameservers(request=self.request, errors=self.errors) 599 self.current_nameservers = self.nameservers[:] 600 backoff = self.backoff 601 self.backoff = min(self.backoff * 2, 2) 602 603 self.nameserver = self.current_nameservers.pop(0) 604 self.port = self.resolver.nameserver_ports.get(self.nameserver, 605 self.resolver.port) 606 self.tcp_attempt = self.tcp 607 return (self.nameserver, self.port, self.tcp_attempt, backoff) 608 609 def query_result(self, response, ex): 610 # 611 # returns an (answer: Answer, end_loop: bool) tuple. 612 # 613 if ex: 614 # Exception during I/O or from_wire() 615 assert response is None 616 self.errors.append((self.nameserver, self.tcp_attempt, self.port, 617 ex, response)) 618 if isinstance(ex, dns.exception.FormError) or \ 619 isinstance(ex, EOFError) or \ 620 isinstance(ex, OSError) or \ 621 isinstance(ex, NotImplementedError): 622 # This nameserver is no good, take it out of the mix. 623 self.nameservers.remove(self.nameserver) 624 elif isinstance(ex, dns.message.Truncated): 625 if self.tcp_attempt: 626 # Truncation with TCP is no good! 627 self.nameservers.remove(self.nameserver) 628 else: 629 self.retry_with_tcp = True 630 return (None, False) 631 # We got an answer! 632 assert response is not None 633 rcode = response.rcode() 634 if rcode == dns.rcode.NOERROR: 635 answer = Answer(self.qname, self.rdtype, self.rdclass, response, 636 self.nameserver, self.port) 637 if self.resolver.cache: 638 self.resolver.cache.put((self.qname, self.rdtype, 639 self.rdclass), answer) 640 if answer.rrset is None and self.raise_on_no_answer: 641 raise NoAnswer(response=answer.response) 642 return (answer, True) 643 elif rcode == dns.rcode.NXDOMAIN: 644 self.nxdomain_responses[self.qname] = response 645 # Make next_nameserver() return None, so caller breaks its 646 # inner loop and calls next_request(). 647 if self.resolver.cache: 648 answer = Answer(self.qname, dns.rdatatype.ANY, 649 dns.rdataclass.IN, response) 650 self.resolver.cache.put((self.qname, 651 dns.rdatatype.ANY, 652 self.rdclass), answer) 653 654 return (None, True) 655 elif rcode == dns.rcode.YXDOMAIN: 656 yex = YXDOMAIN() 657 self.errors.append((self.nameserver, self.tcp_attempt, 658 self.port, yex, response)) 659 raise yex 660 else: 661 # 662 # We got a response, but we're not happy with the 663 # rcode in it. 664 # 665 if rcode != dns.rcode.SERVFAIL or not self.resolver.retry_servfail: 666 self.nameservers.remove(self.nameserver) 667 self.errors.append((self.nameserver, self.tcp_attempt, self.port, 668 dns.rcode.to_text(rcode), response)) 669 return (None, False) 670 671class Resolver: 672 """DNS stub resolver.""" 673 674 # We initialize in reset() 675 # 676 # pylint: disable=attribute-defined-outside-init 677 678 def __init__(self, filename='/etc/resolv.conf', configure=True): 679 """*filename*, a ``str`` or file object, specifying a file 680 in standard /etc/resolv.conf format. This parameter is meaningful 681 only when *configure* is true and the platform is POSIX. 682 683 *configure*, a ``bool``. If True (the default), the resolver 684 instance is configured in the normal fashion for the operating 685 system the resolver is running on. (I.e. by reading a 686 /etc/resolv.conf file on POSIX systems and from the registry 687 on Windows systems.) 688 """ 689 690 self.reset() 691 if configure: 692 if sys.platform == 'win32': 693 self.read_registry() # pragma: no cover 694 elif filename: 695 self.read_resolv_conf(filename) 696 697 def reset(self): 698 """Reset all resolver configuration to the defaults.""" 699 700 self.domain = \ 701 dns.name.Name(dns.name.from_text(socket.gethostname())[1:]) 702 if len(self.domain) == 0: 703 self.domain = dns.name.root 704 self.nameservers = [] 705 self.nameserver_ports = {} 706 self.port = 53 707 self.search = [] 708 self.use_search_by_default = False 709 self.timeout = 2.0 710 self.lifetime = 5.0 711 self.keyring = None 712 self.keyname = None 713 self.keyalgorithm = dns.tsig.default_algorithm 714 self.edns = -1 715 self.ednsflags = 0 716 self.payload = 0 717 self.cache = None 718 self.flags = None 719 self.retry_servfail = False 720 self.rotate = False 721 self.ndots = None 722 723 def read_resolv_conf(self, f): 724 """Process *f* as a file in the /etc/resolv.conf format. If f is 725 a ``str``, it is used as the name of the file to open; otherwise it 726 is treated as the file itself. 727 728 Interprets the following items: 729 730 - nameserver - name server IP address 731 732 - domain - local domain name 733 734 - search - search list for host-name lookup 735 736 - options - supported options are rotate, timeout, edns0, and ndots 737 738 """ 739 740 with contextlib.ExitStack() as stack: 741 if isinstance(f, str): 742 try: 743 f = stack.enter_context(open(f)) 744 except OSError: 745 # /etc/resolv.conf doesn't exist, can't be read, etc. 746 raise NoResolverConfiguration 747 748 for l in f: 749 if len(l) == 0 or l[0] == '#' or l[0] == ';': 750 continue 751 tokens = l.split() 752 753 # Any line containing less than 2 tokens is malformed 754 if len(tokens) < 2: 755 continue 756 757 if tokens[0] == 'nameserver': 758 self.nameservers.append(tokens[1]) 759 elif tokens[0] == 'domain': 760 self.domain = dns.name.from_text(tokens[1]) 761 elif tokens[0] == 'search': 762 for suffix in tokens[1:]: 763 self.search.append(dns.name.from_text(suffix)) 764 elif tokens[0] == 'options': 765 for opt in tokens[1:]: 766 if opt == 'rotate': 767 self.rotate = True 768 elif opt == 'edns0': 769 self.use_edns(0, 0, 0) 770 elif 'timeout' in opt: 771 try: 772 self.timeout = int(opt.split(':')[1]) 773 except (ValueError, IndexError): 774 pass 775 elif 'ndots' in opt: 776 try: 777 self.ndots = int(opt.split(':')[1]) 778 except (ValueError, IndexError): 779 pass 780 if len(self.nameservers) == 0: 781 raise NoResolverConfiguration 782 783 def _determine_split_char(self, entry): 784 # 785 # The windows registry irritatingly changes the list element 786 # delimiter in between ' ' and ',' (and vice-versa) in various 787 # versions of windows. 788 # 789 if entry.find(' ') >= 0: # pragma: no cover 790 split_char = ' ' 791 elif entry.find(',') >= 0: # pragma: no cover 792 split_char = ',' 793 else: 794 # probably a singleton; treat as a space-separated list. 795 split_char = ' ' 796 return split_char 797 798 def _config_win32_nameservers(self, nameservers): 799 # we call str() on nameservers to convert it from unicode to ascii 800 nameservers = str(nameservers) 801 split_char = self._determine_split_char(nameservers) 802 ns_list = nameservers.split(split_char) 803 for ns in ns_list: 804 if ns not in self.nameservers: 805 self.nameservers.append(ns) 806 807 def _config_win32_domain(self, domain): # pragma: no cover 808 # we call str() on domain to convert it from unicode to ascii 809 self.domain = dns.name.from_text(str(domain)) 810 811 def _config_win32_search(self, search): # pragma: no cover 812 # we call str() on search to convert it from unicode to ascii 813 search = str(search) 814 split_char = self._determine_split_char(search) 815 search_list = search.split(split_char) 816 for s in search_list: 817 if s not in self.search: 818 self.search.append(dns.name.from_text(s)) 819 820 def _config_win32_fromkey(self, key, always_try_domain): 821 try: 822 servers, rtype = winreg.QueryValueEx(key, 'NameServer') 823 except WindowsError: # pylint: disable=undefined-variable 824 servers = None 825 if servers: 826 self._config_win32_nameservers(servers) 827 if servers or always_try_domain: 828 try: 829 dom, rtype = winreg.QueryValueEx(key, 'Domain') 830 if dom: 831 self._config_win32_domain(dom) 832 except WindowsError: # pragma: no cover 833 pass 834 else: 835 try: 836 servers, rtype = winreg.QueryValueEx(key, 'DhcpNameServer') 837 except WindowsError: # pragma: no cover 838 servers = None 839 if servers: # pragma: no cover 840 self._config_win32_nameservers(servers) 841 try: 842 dom, rtype = winreg.QueryValueEx(key, 'DhcpDomain') 843 if dom: # pragma: no cover 844 self._config_win32_domain(dom) 845 except WindowsError: # pragma: no cover 846 pass 847 try: 848 search, rtype = winreg.QueryValueEx(key, 'SearchList') 849 except WindowsError: # pylint: disable=undefined-variable 850 search = None 851 if search: # pragma: no cover 852 self._config_win32_search(search) 853 854 def read_registry(self): 855 """Extract resolver configuration from the Windows registry.""" 856 857 lm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) 858 try: 859 tcp_params = winreg.OpenKey(lm, 860 r'SYSTEM\CurrentControlSet' 861 r'\Services\Tcpip\Parameters') 862 try: 863 self._config_win32_fromkey(tcp_params, True) 864 finally: 865 tcp_params.Close() 866 interfaces = winreg.OpenKey(lm, 867 r'SYSTEM\CurrentControlSet' 868 r'\Services\Tcpip\Parameters' 869 r'\Interfaces') 870 try: 871 i = 0 872 while True: 873 try: 874 guid = winreg.EnumKey(interfaces, i) 875 i += 1 876 key = winreg.OpenKey(interfaces, guid) 877 if not self._win32_is_nic_enabled(lm, guid, key): 878 continue 879 try: 880 self._config_win32_fromkey(key, False) 881 finally: 882 key.Close() 883 except EnvironmentError: # pragma: no cover 884 break 885 finally: 886 interfaces.Close() 887 finally: 888 lm.Close() 889 890 def _win32_is_nic_enabled(self, lm, guid, 891 interface_key): 892 # Look in the Windows Registry to determine whether the network 893 # interface corresponding to the given guid is enabled. 894 # 895 # (Code contributed by Paul Marks, thanks!) 896 # 897 try: 898 # This hard-coded location seems to be consistent, at least 899 # from Windows 2000 through Vista. 900 connection_key = winreg.OpenKey( 901 lm, 902 r'SYSTEM\CurrentControlSet\Control\Network' 903 r'\{4D36E972-E325-11CE-BFC1-08002BE10318}' 904 r'\%s\Connection' % guid) 905 906 try: 907 # The PnpInstanceID points to a key inside Enum 908 (pnp_id, ttype) = winreg.QueryValueEx( 909 connection_key, 'PnpInstanceID') 910 911 if ttype != winreg.REG_SZ: # pragma: no cover 912 raise ValueError 913 914 device_key = winreg.OpenKey( 915 lm, r'SYSTEM\CurrentControlSet\Enum\%s' % pnp_id) 916 917 try: 918 # Get ConfigFlags for this device 919 (flags, ttype) = winreg.QueryValueEx( 920 device_key, 'ConfigFlags') 921 922 if ttype != winreg.REG_DWORD: # pragma: no cover 923 raise ValueError 924 925 # Based on experimentation, bit 0x1 indicates that the 926 # device is disabled. 927 return not flags & 0x1 928 929 finally: 930 device_key.Close() 931 finally: 932 connection_key.Close() 933 except Exception: # pragma: no cover 934 return False 935 936 def _compute_timeout(self, start, lifetime=None): 937 lifetime = self.lifetime if lifetime is None else lifetime 938 now = time.time() 939 duration = now - start 940 if duration < 0: 941 if duration < -1: 942 # Time going backwards is bad. Just give up. 943 raise Timeout(timeout=duration) 944 else: 945 # Time went backwards, but only a little. This can 946 # happen, e.g. under vmware with older linux kernels. 947 # Pretend it didn't happen. 948 now = start 949 if duration >= lifetime: 950 raise Timeout(timeout=duration) 951 return min(lifetime - duration, self.timeout) 952 953 def _get_qnames_to_try(self, qname, search): 954 # This is a separate method so we can unit test the search 955 # rules without requiring the Internet. 956 if search is None: 957 search = self.use_search_by_default 958 qnames_to_try = [] 959 if qname.is_absolute(): 960 qnames_to_try.append(qname) 961 else: 962 if len(qname) > 1 or not search: 963 qnames_to_try.append(qname.concatenate(dns.name.root)) 964 if search and self.search: 965 for suffix in self.search: 966 if self.ndots is None or len(qname.labels) >= self.ndots: 967 qnames_to_try.append(qname.concatenate(suffix)) 968 elif search: 969 qnames_to_try.append(qname.concatenate(self.domain)) 970 return qnames_to_try 971 972 def resolve(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, 973 tcp=False, source=None, raise_on_no_answer=True, source_port=0, 974 lifetime=None, search=None): 975 """Query nameservers to find the answer to the question. 976 977 The *qname*, *rdtype*, and *rdclass* parameters may be objects 978 of the appropriate type, or strings that can be converted into objects 979 of the appropriate type. 980 981 *qname*, a ``dns.name.Name`` or ``str``, the query name. 982 983 *rdtype*, an ``int`` or ``str``, the query type. 984 985 *rdclass*, an ``int`` or ``str``, the query class. 986 987 *tcp*, a ``bool``. If ``True``, use TCP to make the query. 988 989 *source*, a ``str`` or ``None``. If not ``None``, bind to this IP 990 address when making queries. 991 992 *raise_on_no_answer*, a ``bool``. If ``True``, raise 993 ``dns.resolver.NoAnswer`` if there's no answer to the question. 994 995 *source_port*, an ``int``, the port from which to send the message. 996 997 *lifetime*, a ``float``, how many seconds a query should run 998 before timing out. 999 1000 *search*, a ``bool`` or ``None``, determines whether the 1001 search list configured in the system's resolver configuration 1002 are used for relative names, and whether the resolver's domain 1003 may be added to relative names. The default is ``None``, 1004 which causes the value of the resolver's 1005 ``use_search_by_default`` attribute to be used. 1006 1007 Raises ``dns.exception.Timeout`` if no answers could be found 1008 in the specified lifetime. 1009 1010 Raises ``dns.resolver.NXDOMAIN`` if the query name does not exist. 1011 1012 Raises ``dns.resolver.YXDOMAIN`` if the query name is too long after 1013 DNAME substitution. 1014 1015 Raises ``dns.resolver.NoAnswer`` if *raise_on_no_answer* is 1016 ``True`` and the query name exists but has no RRset of the 1017 desired type and class. 1018 1019 Raises ``dns.resolver.NoNameservers`` if no non-broken 1020 nameservers are available to answer the question. 1021 1022 Returns a ``dns.resolver.Answer`` instance. 1023 1024 """ 1025 1026 resolution = _Resolution(self, qname, rdtype, rdclass, tcp, 1027 raise_on_no_answer, search) 1028 start = time.time() 1029 while True: 1030 (request, answer) = resolution.next_request() 1031 # Note we need to say "if answer is not None" and not just 1032 # "if answer" because answer implements __len__, and python 1033 # will call that. We want to return if we have an answer 1034 # object, including in cases where its length is 0. 1035 if answer is not None: 1036 # cache hit! 1037 return answer 1038 done = False 1039 while not done: 1040 (nameserver, port, tcp, backoff) = resolution.next_nameserver() 1041 if backoff: 1042 time.sleep(backoff) 1043 timeout = self._compute_timeout(start, lifetime) 1044 try: 1045 if dns.inet.is_address(nameserver): 1046 if tcp: 1047 response = dns.query.tcp(request, nameserver, 1048 timeout=timeout, 1049 port=port, 1050 source=source, 1051 source_port=source_port) 1052 else: 1053 response = dns.query.udp(request, 1054 nameserver, 1055 timeout=timeout, 1056 port=port, 1057 source=source, 1058 source_port=source_port, 1059 raise_on_truncation=True) 1060 else: 1061 protocol = urlparse(nameserver).scheme 1062 if protocol != 'https': 1063 raise NotImplementedError 1064 response = dns.query.https(request, nameserver, 1065 timeout=timeout) 1066 except Exception as ex: 1067 (_, done) = resolution.query_result(None, ex) 1068 continue 1069 (answer, done) = resolution.query_result(response, None) 1070 # Note we need to say "if answer is not None" and not just 1071 # "if answer" because answer implements __len__, and python 1072 # will call that. We want to return if we have an answer 1073 # object, including in cases where its length is 0. 1074 if answer is not None: 1075 return answer 1076 1077 def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, 1078 tcp=False, source=None, raise_on_no_answer=True, source_port=0, 1079 lifetime=None): # pragma: no cover 1080 """Query nameservers to find the answer to the question. 1081 1082 This method calls resolve() with ``search=True``, and is 1083 provided for backwards compatbility with prior versions of 1084 dnspython. See the documentation for the resolve() method for 1085 further details. 1086 """ 1087 warnings.warn('please use dns.resolver.Resolver.resolve() instead', 1088 DeprecationWarning, stacklevel=2) 1089 return self.resolve(qname, rdtype, rdclass, tcp, source, 1090 raise_on_no_answer, source_port, lifetime, 1091 True) 1092 1093 def resolve_address(self, ipaddr, *args, **kwargs): 1094 """Use a resolver to run a reverse query for PTR records. 1095 1096 This utilizes the resolve() method to perform a PTR lookup on the 1097 specified IP address. 1098 1099 *ipaddr*, a ``str``, the IPv4 or IPv6 address you want to get 1100 the PTR record for. 1101 1102 All other arguments that can be passed to the resolve() function 1103 except for rdtype and rdclass are also supported by this 1104 function. 1105 """ 1106 1107 return self.resolve(dns.reversename.from_address(ipaddr), 1108 rdtype=dns.rdatatype.PTR, 1109 rdclass=dns.rdataclass.IN, 1110 *args, **kwargs) 1111 1112 def use_tsig(self, keyring, keyname=None, 1113 algorithm=dns.tsig.default_algorithm): 1114 """Add a TSIG signature to each query. 1115 1116 The parameters are passed to ``dns.message.Message.use_tsig()``; 1117 see its documentation for details. 1118 """ 1119 1120 self.keyring = keyring 1121 self.keyname = keyname 1122 self.keyalgorithm = algorithm 1123 1124 def use_edns(self, edns, ednsflags, payload): 1125 """Configure EDNS behavior. 1126 1127 *edns*, an ``int``, is the EDNS level to use. Specifying 1128 ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case 1129 the other parameters are ignored. Specifying ``True`` is 1130 equivalent to specifying 0, i.e. "use EDNS0". 1131 1132 *ednsflags*, an ``int``, the EDNS flag values. 1133 1134 *payload*, an ``int``, is the EDNS sender's payload field, which is the 1135 maximum size of UDP datagram the sender can handle. I.e. how big 1136 a response to this message can be. 1137 """ 1138 1139 if edns is None: 1140 edns = -1 1141 self.edns = edns 1142 self.ednsflags = ednsflags 1143 self.payload = payload 1144 1145 def set_flags(self, flags): 1146 """Overrides the default flags with your own. 1147 1148 *flags*, an ``int``, the message flags to use. 1149 """ 1150 1151 self.flags = flags 1152 1153 @property 1154 def nameservers(self): 1155 return self._nameservers 1156 1157 @nameservers.setter 1158 def nameservers(self, nameservers): 1159 """ 1160 *nameservers*, a ``list`` of nameservers. 1161 1162 Raises ``ValueError`` if *nameservers* is anything other than a 1163 ``list``. 1164 """ 1165 if isinstance(nameservers, list): 1166 self._nameservers = nameservers 1167 else: 1168 raise ValueError('nameservers must be a list' 1169 ' (not a {})'.format(type(nameservers))) 1170 1171#: The default resolver. 1172default_resolver = None 1173 1174 1175def get_default_resolver(): 1176 """Get the default resolver, initializing it if necessary.""" 1177 if default_resolver is None: 1178 reset_default_resolver() 1179 return default_resolver 1180 1181 1182def reset_default_resolver(): 1183 """Re-initialize default resolver. 1184 1185 Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX 1186 systems) will be re-read immediately. 1187 """ 1188 1189 global default_resolver 1190 default_resolver = Resolver() 1191 1192 1193def resolve(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, 1194 tcp=False, source=None, raise_on_no_answer=True, 1195 source_port=0, lifetime=None, search=None): 1196 """Query nameservers to find the answer to the question. 1197 1198 This is a convenience function that uses the default resolver 1199 object to make the query. 1200 1201 See ``dns.resolver.Resolver.resolve`` for more information on the 1202 parameters. 1203 """ 1204 1205 return get_default_resolver().resolve(qname, rdtype, rdclass, tcp, source, 1206 raise_on_no_answer, source_port, 1207 lifetime, search) 1208 1209def query(qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN, 1210 tcp=False, source=None, raise_on_no_answer=True, 1211 source_port=0, lifetime=None): # pragma: no cover 1212 """Query nameservers to find the answer to the question. 1213 1214 This method calls resolve() with ``search=True``, and is 1215 provided for backwards compatbility with prior versions of 1216 dnspython. See the documentation for the resolve() method for 1217 further details. 1218 """ 1219 warnings.warn('please use dns.resolver.resolve() instead', 1220 DeprecationWarning, stacklevel=2) 1221 return resolve(qname, rdtype, rdclass, tcp, source, 1222 raise_on_no_answer, source_port, lifetime, 1223 True) 1224 1225 1226def resolve_address(ipaddr, *args, **kwargs): 1227 """Use a resolver to run a reverse query for PTR records. 1228 1229 See ``dns.resolver.Resolver.resolve_address`` for more information on the 1230 parameters. 1231 """ 1232 1233 return get_default_resolver().resolve_address(ipaddr, *args, **kwargs) 1234 1235 1236def zone_for_name(name, rdclass=dns.rdataclass.IN, tcp=False, resolver=None): 1237 """Find the name of the zone which contains the specified name. 1238 1239 *name*, an absolute ``dns.name.Name`` or ``str``, the query name. 1240 1241 *rdclass*, an ``int``, the query class. 1242 1243 *tcp*, a ``bool``. If ``True``, use TCP to make the query. 1244 1245 *resolver*, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. 1246 If ``None``, the default resolver is used. 1247 1248 Raises ``dns.resolver.NoRootSOA`` if there is no SOA RR at the DNS 1249 root. (This is only likely to happen if you're using non-default 1250 root servers in your network and they are misconfigured.) 1251 1252 Returns a ``dns.name.Name``. 1253 """ 1254 1255 if isinstance(name, str): 1256 name = dns.name.from_text(name, dns.name.root) 1257 if resolver is None: 1258 resolver = get_default_resolver() 1259 if not name.is_absolute(): 1260 raise NotAbsolute(name) 1261 while 1: 1262 try: 1263 answer = resolver.resolve(name, dns.rdatatype.SOA, rdclass, tcp) 1264 if answer.rrset.name == name: 1265 return name 1266 # otherwise we were CNAMEd or DNAMEd and need to look higher 1267 except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): 1268 pass 1269 try: 1270 name = name.parent() 1271 except dns.name.NoParent: 1272 raise NoRootSOA 1273 1274# 1275# Support for overriding the system resolver for all python code in the 1276# running process. 1277# 1278 1279_protocols_for_socktype = { 1280 socket.SOCK_DGRAM: [socket.SOL_UDP], 1281 socket.SOCK_STREAM: [socket.SOL_TCP], 1282} 1283 1284_resolver = None 1285_original_getaddrinfo = socket.getaddrinfo 1286_original_getnameinfo = socket.getnameinfo 1287_original_getfqdn = socket.getfqdn 1288_original_gethostbyname = socket.gethostbyname 1289_original_gethostbyname_ex = socket.gethostbyname_ex 1290_original_gethostbyaddr = socket.gethostbyaddr 1291 1292 1293def _getaddrinfo(host=None, service=None, family=socket.AF_UNSPEC, socktype=0, 1294 proto=0, flags=0): 1295 if flags & socket.AI_NUMERICHOST != 0: 1296 # Short circuit directly into the system's getaddrinfo(). We're 1297 # not adding any value in this case, and this avoids infinite loops 1298 # because dns.query.* needs to call getaddrinfo() for IPv6 scoping 1299 # reasons. We will also do this short circuit below if we 1300 # discover that the host is an address literal. 1301 return _original_getaddrinfo(host, service, family, socktype, proto, 1302 flags) 1303 if flags & (socket.AI_ADDRCONFIG | socket.AI_V4MAPPED) != 0: 1304 # Not implemented. We raise a gaierror as opposed to a 1305 # NotImplementedError as it helps callers handle errors more 1306 # appropriately. [Issue #316] 1307 # 1308 # We raise EAI_FAIL as opposed to EAI_SYSTEM because there is 1309 # no EAI_SYSTEM on Windows [Issue #416]. We didn't go for 1310 # EAI_BADFLAGS as the flags aren't bad, we just don't 1311 # implement them. 1312 raise socket.gaierror(socket.EAI_FAIL, 1313 'Non-recoverable failure in name resolution') 1314 if host is None and service is None: 1315 raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') 1316 v6addrs = [] 1317 v4addrs = [] 1318 canonical_name = None 1319 # Is host None or an address literal? If so, use the system's 1320 # getaddrinfo(). 1321 if host is None: 1322 return _original_getaddrinfo(host, service, family, socktype, 1323 proto, flags) 1324 try: 1325 # We don't care about the result of af_for_address(), we're just 1326 # calling it so it raises an exception if host is not an IPv4 or 1327 # IPv6 address. 1328 dns.inet.af_for_address(host) 1329 return _original_getaddrinfo(host, service, family, socktype, 1330 proto, flags) 1331 except Exception: 1332 pass 1333 # Something needs resolution! 1334 try: 1335 if family == socket.AF_INET6 or family == socket.AF_UNSPEC: 1336 v6 = _resolver.resolve(host, dns.rdatatype.AAAA, 1337 raise_on_no_answer=False) 1338 # Note that setting host ensures we query the same name 1339 # for A as we did for AAAA. 1340 host = v6.qname 1341 canonical_name = v6.canonical_name.to_text(True) 1342 if v6.rrset is not None: 1343 for rdata in v6.rrset: 1344 v6addrs.append(rdata.address) 1345 if family == socket.AF_INET or family == socket.AF_UNSPEC: 1346 v4 = _resolver.resolve(host, dns.rdatatype.A, 1347 raise_on_no_answer=False) 1348 host = v4.qname 1349 canonical_name = v4.canonical_name.to_text(True) 1350 if v4.rrset is not None: 1351 for rdata in v4.rrset: 1352 v4addrs.append(rdata.address) 1353 except dns.resolver.NXDOMAIN: 1354 raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') 1355 except Exception as e: 1356 print(e) 1357 # We raise EAI_AGAIN here as the failure may be temporary 1358 # (e.g. a timeout) and EAI_SYSTEM isn't defined on Windows. 1359 # [Issue #416] 1360 raise socket.gaierror(socket.EAI_AGAIN, 1361 'Temporary failure in name resolution') 1362 port = None 1363 try: 1364 # Is it a port literal? 1365 if service is None: 1366 port = 0 1367 else: 1368 port = int(service) 1369 except Exception: 1370 if flags & socket.AI_NUMERICSERV == 0: 1371 try: 1372 port = socket.getservbyname(service) 1373 except Exception: 1374 pass 1375 if port is None: 1376 raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') 1377 tuples = [] 1378 if socktype == 0: 1379 socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM] 1380 else: 1381 socktypes = [socktype] 1382 if flags & socket.AI_CANONNAME != 0: 1383 cname = canonical_name 1384 else: 1385 cname = '' 1386 if family == socket.AF_INET6 or family == socket.AF_UNSPEC: 1387 for addr in v6addrs: 1388 for socktype in socktypes: 1389 for proto in _protocols_for_socktype[socktype]: 1390 tuples.append((socket.AF_INET6, socktype, proto, 1391 cname, (addr, port, 0, 0))) 1392 if family == socket.AF_INET or family == socket.AF_UNSPEC: 1393 for addr in v4addrs: 1394 for socktype in socktypes: 1395 for proto in _protocols_for_socktype[socktype]: 1396 tuples.append((socket.AF_INET, socktype, proto, 1397 cname, (addr, port))) 1398 if len(tuples) == 0: 1399 raise socket.gaierror(socket.EAI_NONAME, 'Name or service not known') 1400 return tuples 1401 1402 1403def _getnameinfo(sockaddr, flags=0): 1404 host = sockaddr[0] 1405 port = sockaddr[1] 1406 if len(sockaddr) == 4: 1407 scope = sockaddr[3] 1408 family = socket.AF_INET6 1409 else: 1410 scope = None 1411 family = socket.AF_INET 1412 tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM, 1413 socket.SOL_TCP, 0) 1414 if len(tuples) > 1: 1415 raise socket.error('sockaddr resolved to multiple addresses') 1416 addr = tuples[0][4][0] 1417 if flags & socket.NI_DGRAM: 1418 pname = 'udp' 1419 else: 1420 pname = 'tcp' 1421 qname = dns.reversename.from_address(addr) 1422 if flags & socket.NI_NUMERICHOST == 0: 1423 try: 1424 answer = _resolver.resolve(qname, 'PTR') 1425 hostname = answer.rrset[0].target.to_text(True) 1426 except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): 1427 if flags & socket.NI_NAMEREQD: 1428 raise socket.gaierror(socket.EAI_NONAME, 1429 'Name or service not known') 1430 hostname = addr 1431 if scope is not None: 1432 hostname += '%' + str(scope) 1433 else: 1434 hostname = addr 1435 if scope is not None: 1436 hostname += '%' + str(scope) 1437 if flags & socket.NI_NUMERICSERV: 1438 service = str(port) 1439 else: 1440 service = socket.getservbyport(port, pname) 1441 return (hostname, service) 1442 1443 1444def _getfqdn(name=None): 1445 if name is None: 1446 name = socket.gethostname() 1447 try: 1448 (name, _, _) = _gethostbyaddr(name) 1449 # Python's version checks aliases too, but our gethostbyname 1450 # ignores them, so we do so here as well. 1451 except Exception: 1452 pass 1453 return name 1454 1455 1456def _gethostbyname(name): 1457 return _gethostbyname_ex(name)[2][0] 1458 1459 1460def _gethostbyname_ex(name): 1461 aliases = [] 1462 addresses = [] 1463 tuples = _getaddrinfo(name, 0, socket.AF_INET, socket.SOCK_STREAM, 1464 socket.SOL_TCP, socket.AI_CANONNAME) 1465 canonical = tuples[0][3] 1466 for item in tuples: 1467 addresses.append(item[4][0]) 1468 # XXX we just ignore aliases 1469 return (canonical, aliases, addresses) 1470 1471 1472def _gethostbyaddr(ip): 1473 try: 1474 dns.ipv6.inet_aton(ip) 1475 sockaddr = (ip, 80, 0, 0) 1476 family = socket.AF_INET6 1477 except Exception: 1478 try: 1479 dns.ipv4.inet_aton(ip) 1480 except Exception: 1481 raise socket.gaierror(socket.EAI_NONAME, 1482 'Name or service not known') 1483 sockaddr = (ip, 80) 1484 family = socket.AF_INET 1485 (name, port) = _getnameinfo(sockaddr, socket.NI_NAMEREQD) 1486 aliases = [] 1487 addresses = [] 1488 tuples = _getaddrinfo(name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP, 1489 socket.AI_CANONNAME) 1490 canonical = tuples[0][3] 1491 # We only want to include an address from the tuples if it's the 1492 # same as the one we asked about. We do this comparison in binary 1493 # to avoid any differences in text representations. 1494 bin_ip = dns.inet.inet_pton(family, ip) 1495 for item in tuples: 1496 addr = item[4][0] 1497 bin_addr = dns.inet.inet_pton(family, addr) 1498 if bin_ip == bin_addr: 1499 addresses.append(addr) 1500 # XXX we just ignore aliases 1501 return (canonical, aliases, addresses) 1502 1503 1504def override_system_resolver(resolver=None): 1505 """Override the system resolver routines in the socket module with 1506 versions which use dnspython's resolver. 1507 1508 This can be useful in testing situations where you want to control 1509 the resolution behavior of python code without having to change 1510 the system's resolver settings (e.g. /etc/resolv.conf). 1511 1512 The resolver to use may be specified; if it's not, the default 1513 resolver will be used. 1514 1515 resolver, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. 1516 """ 1517 1518 if resolver is None: 1519 resolver = get_default_resolver() 1520 global _resolver 1521 _resolver = resolver 1522 socket.getaddrinfo = _getaddrinfo 1523 socket.getnameinfo = _getnameinfo 1524 socket.getfqdn = _getfqdn 1525 socket.gethostbyname = _gethostbyname 1526 socket.gethostbyname_ex = _gethostbyname_ex 1527 socket.gethostbyaddr = _gethostbyaddr 1528 1529 1530def restore_system_resolver(): 1531 """Undo the effects of prior override_system_resolver().""" 1532 1533 global _resolver 1534 _resolver = None 1535 socket.getaddrinfo = _original_getaddrinfo 1536 socket.getnameinfo = _original_getnameinfo 1537 socket.getfqdn = _original_getfqdn 1538 socket.gethostbyname = _original_gethostbyname 1539 socket.gethostbyname_ex = _original_gethostbyname_ex 1540 socket.gethostbyaddr = _original_gethostbyaddr 1541