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