]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
query doco
authorBob Halley <halley@dnspython.org>
Mon, 16 Jan 2017 14:29:01 +0000 (06:29 -0800)
committerBob Halley <halley@dnspython.org>
Mon, 16 Jan 2017 14:29:01 +0000 (06:29 -0800)
dns/query.py
doc/exceptions.rst
doc/manual.rst
doc/query.rst [new file with mode: 0644]
doc/resolver.rst [new file with mode: 0644]

index 2ae1d89c93da457064d2ddda65cea9f0078ce53d..497111063aba03e3340431f1a8757b247d4c8008 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
+# Copyright (C) 2003-2017 Nominum, Inc.
 #
 # Permission to use, copy, modify, and distribute this software and its
 # documentation for any purpose with or without fee is hereby granted,
@@ -42,12 +42,10 @@ else:
 socket_factory = socket.socket
 
 class UnexpectedSource(dns.exception.DNSException):
-
     """A DNS query response came from an unexpected address or port."""
 
 
 class BadResponse(dns.exception.FormError):
-
     """A DNS query response does not respond to the question asked."""
 
 
@@ -57,19 +55,14 @@ def _compute_expiration(timeout):
     else:
         return time.time() + timeout
 
+# This module can use either poll() or select() as the "polling backend".
+#
+# A backend function takes an fd, bools for readability, writablity, and
+# error detection, and a timeout.
 
 def _poll_for(fd, readable, writable, error, timeout):
-    """Poll polling backend.
-    @param fd: File descriptor
-    @type fd: int
-    @param readable: Whether to wait for readability
-    @type readable: bool
-    @param writable: Whether to wait for writability
-    @type writable: bool
-    @param timeout: Deadline timeout (expiration time, in seconds)
-    @type timeout: float
-    @return True on success, False on timeout
-    """
+    """Poll polling backend."""
+
     event_mask = 0
     if readable:
         event_mask |= select.POLLIN
@@ -90,17 +83,8 @@ def _poll_for(fd, readable, writable, error, timeout):
 
 
 def _select_for(fd, readable, writable, error, timeout):
-    """Select polling backend.
-    @param fd: File descriptor
-    @type fd: int
-    @param readable: Whether to wait for readability
-    @type readable: bool
-    @param writable: Whether to wait for writability
-    @type writable: bool
-    @param timeout: Deadline timeout (expiration time, in seconds)
-    @type timeout: float
-    @return True on success, False on timeout
-    """
+    """Select polling backend."""
+
     rset, wset, xset = [], [], []
 
     if readable:
@@ -119,6 +103,10 @@ def _select_for(fd, readable, writable, error, timeout):
 
 
 def _wait_for(fd, readable, writable, error, expiration):
+    # Use the selected polling backend to wait for any of the specified
+    # events.  An "expiration" absolute time is converted into a relative
+    # timeout.
+
     done = False
     while not done:
         if expiration is None:
@@ -137,9 +125,8 @@ def _wait_for(fd, readable, writable, error, expiration):
 
 
 def _set_polling_backend(fn):
-    """
-    Internal API. Do not use.
-    """
+    # Internal API. Do not use.
+
     global _polling_backend
 
     _polling_backend = fn
@@ -165,8 +152,11 @@ def _addresses_equal(af, a1, a2):
     # Convert the first value of the tuple, which is a textual format
     # address into binary form, so that we are not confused by different
     # textual representations of the same address
-    n1 = dns.inet.inet_pton(af, a1[0])
-    n2 = dns.inet.inet_pton(af, a2[0])
+    try:
+        n1 = dns.inet.inet_pton(af, a1[0])
+        n2 = dns.inet.inet_pton(af, a2[0])
+    except dns.exception.SyntaxError:
+        return False
     return n1 == n2 and a1[1:] == a2[1:]
 
 
@@ -196,17 +186,20 @@ def _destination_and_source(af, where, port, source, source_port):
 def send_udp(sock, what, destination, expiration=None):
     """Send a DNS message to the specified UDP socket.
 
-    @param sock: the socket
-    @type sock: socket.socket
-    @param what: the message to send
-    @type what: wire format bytes or a dns.message.Message
-    @param destination: where to send the query
-    @type destination: tuple appropriate for the address family of the socket
-    @param expiration: The absolute time at which a timeout exception should
-    be raised.
-    @type expiration: float
-    @rtype: (int, double) tuple of bytes sent and the sent time.
+    *sock*, a ``socket``.
+
+    *what*, a ``binary`` or ``dns.message.Message``, the message to send.
+
+    *destination*, a destination tuple appropriate for the address family
+    of the socket, specifying where to send the query.
+
+    *expiration*, a ``float`` or ``None``, the absolute time at which
+    a timeout exception should be raised.  If ``None``, no timeout will
+    occur.
+
+    Returns an ``(int, float)`` tuple of bytes sent and the sent time.
     """
+
     if isinstance(what, dns.message.Message):
         what = what.to_wire()
     _wait_for_writable(sock, expiration)
@@ -215,38 +208,41 @@ def send_udp(sock, what, destination, expiration=None):
     return (n, sent_time)
 
 
-def receive_udp(sock, destination, expiration=None, af=None,
+def receive_udp(sock, destination, expiration=None,
                 ignore_unexpected=False, one_rr_per_rrset=False,
                 keyring=None, request_mac=b''):
     """Read a DNS message from a UDP socket.
 
-    @param sock: the socket
-    @type sock: socket.socket
-    @param af: the address family to use.  The default is None, which
-    causes the address family to use to be inferred from the form of
-    destination.  If the inference attempt fails, AF_INET is used.
-    @type af: int
-    @param ignore_unexpected: If True, ignore responses from unexpected
-    sources.  The default is False.
-    @type ignore_unexpected: bool
-    @param one_rr_per_rrset: Put each RR into its own RRset
-    @type one_rr_per_rrset: bool
-    @param keyring: the keyring to use for TSIG
-    @type keyring: keyring dict
-    @param request_mac: the MAC of the request (for TSIG)
-    @type request_mac: bytes
-    @rtype: dns.message.Message object
+    *sock*, a ``socket``.
+
+    *destination*, a destination tuple appropriate for the address family
+    of the socket, specifying where the associated query was sent.
+
+    *expiration*, a ``float`` or ``None``, the absolute time at which
+    a timeout exception should be raised.  If ``None``, no timeout will
+    occur.
+
+    *ignore_unexpected*, a ``bool``.  If ``True``, ignore responses from
+    unexpected sources.
+
+    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
+    RRset.
+
+    *keyring*, a ``dict``, the keyring to use for TSIG.
+
+    *request_mac*, a ``binary``, the MAC of the request (for TSIG).
+
+    Raises if the message is malformed, if network errors occur, of if
+    there is a timeout.
+
+    Returns a ``dns.message.Message`` object.
     """
-    if af is None:
-        try:
-            af = dns.inet.af_for_address(destination[0])
-        except Exception:
-            af = dns.inet.AF_INET
+
     wire = b''
     while 1:
         _wait_for_readable(sock, expiration)
         (wire, from_address) = sock.recvfrom(65535)
-        if _addresses_equal(af, from_address, destination) or \
+        if _addresses_equal(socket.family, from_address, destination) or \
            (dns.inet.is_multicast(destination[0]) and
             from_address[1:] == destination[1:]):
             break
@@ -263,30 +259,34 @@ def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
         ignore_unexpected=False, one_rr_per_rrset=False):
     """Return the response obtained after sending a query via UDP.
 
-    @param q: the query
-    @type q: dns.message.Message
-    @param where: where to send the message
-    @type where: string containing an IPv4 or IPv6 address
-    @param timeout: The number of seconds to wait before the query times out.
-    If None, the default, wait forever.
-    @type timeout: float
-    @param port: The port to which to send the message.  The default is 53.
-    @type port: int
-    @param af: the address family to use.  The default is None, which
-    causes the address family to use to be inferred from the form of where.
-    If the inference attempt fails, AF_INET is used.
-    @type af: int
-    @param source: source address.  The default is the wildcard address.
-    @type source: string
-    @param source_port: The port from which to send the message.
+    *q*, a ``dns.message.message``, the query to send
+
+    *where*, a ``text`` containing an IPv4 or IPv6 address,  where
+    to send the message.
+
+    *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
+    query times out.  If ``None``, the default, wait forever.
+
+    *port*, an ``int``, the port send the message to.  The default is 53.
+
+    *af*, an ``int``, the address family to use.  The default is ``None``,
+    which causes the address family to use to be inferred from the form of
+    *where*.  If the inference attempt fails, AF_INET is used.  This
+    parameter is historical; you need never set it.
+
+    *source*, a ``text`` containing an IPv4 or IPv6 address, specifying
+    the source address.  The default is the wildcard address.
+
+    *source_port*, an ``int``, the port from which to send the message.
     The default is 0.
-    @type source_port: int
-    @param ignore_unexpected: If True, ignore responses from unexpected
-    sources.  The default is False.
-    @type ignore_unexpected: bool
-    @param one_rr_per_rrset: Put each RR into its own RRset
-    @type one_rr_per_rrset: bool
-    @rtype: dns.message.Message object
+
+    *ignore_unexpected*, a ``bool``.  If ``True``, ignore responses from
+    unexpected sources.
+
+    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
+    RRset.
+
+    Returns a ``dns.message.Message``.
     """
 
     wire = q.to_wire()
@@ -348,15 +348,17 @@ def _net_write(sock, data, expiration):
 def send_tcp(sock, what, expiration=None):
     """Send a DNS message to the specified TCP socket.
 
-    @param sock: the socket
-    @type sock: socket.socket
-    @param what: the message to send
-    @type what: wire format bytes or a dns.message.Message
-    @param expiration: The absolute time at which a timeout exception should
-    be raised.
-    @type expiration: float
-    @rtype: (int, double) tuple of bytes sent and the sent time.
+    *sock*, a ``socket``.
+
+    *what*, a ``binary`` or ``dns.message.Message``, the message to send.
+
+    *expiration*, a ``float`` or ``None``, the absolute time at which
+    a timeout exception should be raised.  If ``None``, no timeout will
+    occur.
+
+    Returns an ``(int, float)`` tuple of bytes sent and the sent time.
     """
+
     if isinstance(what, dns.message.Message):
         what = what.to_wire()
     l = len(what)
@@ -373,16 +375,25 @@ def receive_tcp(sock, expiration=None, one_rr_per_rrset=False,
                 keyring=None, request_mac=b''):
     """Read a DNS message from a TCP socket.
 
-    @param sock: the socket
-    @type sock: socket.socket
-    @param one_rr_per_rrset: Put each RR into its own RRset
-    @type one_rr_per_rrset: bool
-    @param keyring: the keyring to use for TSIG
-    @type keyring: keyring dict
-    @param request_mac: the MAC of the request (for TSIG)
-    @type request_mac: bytes
-    @rtype: dns.message.Message object
+    *sock*, a ``socket``.
+
+    *expiration*, a ``float`` or ``None``, the absolute time at which
+    a timeout exception should be raised.  If ``None``, no timeout will
+    occur.
+
+    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
+    RRset.
+
+    *keyring*, a ``dict``, the keyring to use for TSIG.
+
+    *request_mac*, a ``binary``, the MAC of the request (for TSIG).
+
+    Raises if the message is malformed, if network errors occur, of if
+    there is a timeout.
+
+    Returns a ``dns.message.Message`` object.
     """
+
     ldata = _net_read(sock, 2, expiration)
     (l,) = struct.unpack("!H", ldata)
     wire = _net_read(sock, l, expiration)
@@ -409,27 +420,31 @@ def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0,
         one_rr_per_rrset=False):
     """Return the response obtained after sending a query via TCP.
 
-    @param q: the query
-    @type q: dns.message.Message object
-    @param where: where to send the message
-    @type where: string containing an IPv4 or IPv6 address
-    @param timeout: The number of seconds to wait before the query times out.
-    If None, the default, wait forever.
-    @type timeout: float
-    @param port: The port to which to send the message.  The default is 53.
-    @type port: int
-    @param af: the address family to use.  The default is None, which
-    causes the address family to use to be inferred from the form of where.
-    If the inference attempt fails, AF_INET is used.
-    @type af: int
-    @rtype: dns.message.Message object
-    @param source: source address.  The default is the wildcard address.
-    @type source: string
-    @param source_port: The port from which to send the message.
+    *q*, a ``dns.message.message``, the query to send
+
+    *where*, a ``text`` containing an IPv4 or IPv6 address,  where
+    to send the message.
+
+    *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
+    query times out.  If ``None``, the default, wait forever.
+
+    *port*, an ``int``, the port send the message to.  The default is 53.
+
+    *af*, an ``int``, the address family to use.  The default is ``None``,
+    which causes the address family to use to be inferred from the form of
+    *where*.  If the inference attempt fails, AF_INET is used.  This
+    parameter is historical; you need never set it.
+
+    *source*, a ``text`` containing an IPv4 or IPv6 address, specifying
+    the source address.  The default is the wildcard address.
+
+    *source_port*, an ``int``, the port from which to send the message.
     The default is 0.
-    @type source_port: int
-    @param one_rr_per_rrset: Put each RR into its own RRset
-    @type one_rr_per_rrset: bool
+
+    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
+    RRset.
+
+    Returns a ``dns.message.Message``.
     """
 
     wire = q.to_wire()
@@ -465,51 +480,57 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
         use_udp=False, keyalgorithm=dns.tsig.default_algorithm):
     """Return a generator for the responses to a zone transfer.
 
-    @param where: where to send the message
-    @type where: string containing an IPv4 or IPv6 address
-    @param zone: The name of the zone to transfer
-    @type zone: dns.name.Name object or string
-    @param rdtype: The type of zone transfer.  The default is
-    dns.rdatatype.AXFR.
-    @type rdtype: int or string
-    @param rdclass: The class of the zone transfer.  The default is
-    dns.rdataclass.IN.
-    @type rdclass: int or string
-    @param timeout: The number of seconds to wait for each response message.
-    If None, the default, wait forever.
-    @type timeout: float
-    @param port: The port to which to send the message.  The default is 53.
-    @type port: int
-    @param keyring: The TSIG keyring to use
-    @type keyring: dict
-    @param keyname: The name of the TSIG key to use
-    @type keyname: dns.name.Name object or string
-    @param relativize: If True, all names in the zone will be relativized to
-    the zone origin.  It is essential that the relativize setting matches
-    the one specified to dns.zone.from_xfr().
-    @type relativize: bool
-    @param af: the address family to use.  The default is None, which
-    causes the address family to use to be inferred from the form of where.
-    If the inference attempt fails, AF_INET is used.
-    @type af: int
-    @param lifetime: The total number of seconds to spend doing the transfer.
-    If None, the default, then there is no limit on the time the transfer may
-    take.
-    @type lifetime: float
-    @rtype: generator of dns.message.Message objects.
-    @param source: source address.  The default is the wildcard address.
-    @type source: string
-    @param source_port: The port from which to send the message.
+    *where*.  If the inference attempt fails, AF_INET is used.  This
+    parameter is historical; you need never set it.
+
+    *zone*, a ``dns.name.Name`` or ``text``, the name of the zone to transfer.
+
+    *rdtype*, an ``int`` or ``text``, the type of zone transfer.  The
+    default is ``dns.rdatatype.AXFR``.  ``dns.rdatatype.IXFR`` can be
+    used to do an incremental transfer instead.
+
+    *rdclass*, an ``int`` or ``text``, the class of the zone transfer.
+    The default is ``dns.rdataclass.IN``.
+
+    *timeout*, a ``float``, the number of seconds to wait for each
+    response message.  If None, the default, wait forever.
+
+    *port*, an ``int``, the port send the message to.  The default is 53.
+
+    *keyring*, a ``dict``, the keyring to use for TSIG.
+
+    *keyname*, a ``dns.name.Name`` or ``text``, the name of the TSIG
+    key to use.
+
+    *relativize*, a ``bool``.  If ``True``, all names in the zone will be
+    relativized to the zone origin.  It is essential that the
+    relativize setting matches the one specified to
+    ``dns.zone.from_xfr()`` if using this generator to make a zone.
+
+    *af*, an ``int``, the address family to use.  The default is ``None``,
+    which causes the address family to use to be inferred from the form of
+    *where*.  If the inference attempt fails, AF_INET is used.  This
+    parameter is historical; you need never set it.
+
+    *lifetime*, a ``float``, the total number of seconds to spend
+    doing the transfer.  If ``None``, the default, then there is no
+    limit on the time the transfer may take.
+
+    *source*, a ``text`` containing an IPv4 or IPv6 address, specifying
+    the source address.  The default is the wildcard address.
+
+    *source_port*, an ``int``, the port from which to send the message.
     The default is 0.
-    @type source_port: int
-    @param serial: The SOA serial number to use as the base for an IXFR diff
-    sequence (only meaningful if rdtype == dns.rdatatype.IXFR).
-    @type serial: int
-    @param use_udp: Use UDP (only meaningful for IXFR)
-    @type use_udp: bool
-    @param keyalgorithm: The TSIG algorithm to use; defaults to
-    dns.tsig.default_algorithm
-    @type keyalgorithm: string
+
+    *serial*, an ``int``, the SOA serial number to use as the base for
+    an IXFR diff sequence (only meaningful if *rdtype* is
+    ``dns.rdatatype.IXFR``).
+
+    *use_udp*, a ``bool``.  If ``True``, use UDP (only meaningful for IXFR).
+
+    *keyalgorithm*, a ``dns.name.Name`` or ``text``, the TSIG algorithm to use.
+
+    Returns a generator of ``dns.message.Message`` objects.
     """
 
     if isinstance(zone, string_types):
index 9f5e22cc0a18057dec9715d8f7e0de256569efb2..cc04afc65e593810b04f901e100540163179ad19 100644 (file)
@@ -45,7 +45,14 @@ dns.opcode Exceptions
 ---------------------
 
 .. autoexception:: dns.opcode.UnknownOpcode
-                   
+
+dns.query Exceptions
+--------------------
+
+.. autoexception:: dns.query.BadResponse
+.. autoexception:: dns.query.UnexpectedSource
+
+
 dns.rcode Exceptions
 --------------------
 
index c032f4f94b863ed46c9e22bdd8d96f8ffc831b5e..f1528943f8df8446adf213a72eb7bdce4a0a8e09 100644 (file)
@@ -10,5 +10,7 @@ Dnspython Manual
    rdata
    message
    dnssec
+   query
+   resolver
    exceptions
    utilities
diff --git a/doc/query.rst b/doc/query.rst
new file mode 100644 (file)
index 0000000..77e1c6b
--- /dev/null
@@ -0,0 +1,33 @@
+.. module:: dns.query
+.. _query:
+
+DNS Query Support
+=================
+
+The ``dns.query`` module is for sending messages to DNS servers, and
+processing their responses.  If you want "stub resolver" behavior, then
+you should use the higher level ``dns.resolver`` module; see :ref:`resolver`.
+
+For UDP and TCP, the module provides a single "do everything" query
+function, and also provides the send and receive halves of this function
+individually for situations where more sophisticated I/O handling is in
+being used by the application.
+
+UDP
+---
+
+.. autofunction:: dns.query.udp
+.. autofunction:: dns.query.send_udp
+.. autofunction:: dns.query.receive_udp
+
+TCP
+---
+
+.. autofunction:: dns.query.tcp
+.. autofunction:: dns.query.send_tcp
+.. autofunction:: dns.query.receive_tcp
+      
+Zone Transfers
+--------------
+
+.. autofunction:: dns.query.xfr
diff --git a/doc/resolver.rst b/doc/resolver.rst
new file mode 100644 (file)
index 0000000..6fad36d
--- /dev/null
@@ -0,0 +1,8 @@
+.. module:: dns.resolver
+.. _resolver:
+
+Stub Resolver
+=============
+
+This is a placeholder.
+