]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
make sending queries via IPv6 work
authorBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:23:18 +0000 (05:23 +0000)
committerBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:23:18 +0000 (05:23 +0000)
Original author: Bob Halley <halley@dnspython.org>
Date: 2004-08-04 09:10:14

ChangeLog
dns/inet.py
dns/query.py

index 14b81fa354eec57897298c68cc9c941d03381856..ea213482fba3c05b209e40b71687a28e14f3202a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2004-08-04  Bob Halley  <halley@nominum.com>
+
+       * dns/query.py: sending queries to a nameserver via IPv6 now
+       works.
+       
+       * dns/inet.py (af_for_address): Add af_for_address(), which looks
+       at a textual-form address and attempts to determine which address
+       family it is.
+
+       * dns/query.py: the default for the 'af' parameter of the udp(),
+       tcp(), and xfr() functions has been changed from AF_INET to None,
+       which causes dns.inet.af_for_address() to be used to determine the
+       address family.  If dns.inet.af_for_address() can't figure it out,
+       we fall back to AF_INET and hope for the best.
+
 2004-07-31  Bob Halley  <halley@dnspython.org>
 
        * dns/rdtypes/ANY/NSEC.py (NSEC.from_text): The NSEC text format
index e8e309259f54f4ca48440410408ae436a7e4401f..c12dbbfa6fa0e55ba31338b5c87c53b86b3487f4 100644 (file)
@@ -70,3 +70,21 @@ def inet_ntop(family, address):
         return dns.ipv6.inet_ntoa(address)
     else:
         raise NotImplementedError
+
+def af_for_address(text):
+    """Determine the address family of a textual-form network address.
+
+    @param text: the textual address
+    @type text: string
+    @raises ValueError: the address family cannot be determined from the input.
+    @rtype int
+    """
+    try:
+        junk = dns.ipv4.inet_aton(text)
+        return AF_INET
+    except:
+        try:
+            junk = dns.ipv6.inet_aton(text)
+            return AF_INET6
+        except:
+            raise ValueError
index d0e04d8a4437eb2085ae8f5e5695775d6f9da2d6..d5f86fb04d68734d477404669da8ac91b3b6346f 100644 (file)
@@ -25,6 +25,7 @@ import sys
 import time
 
 import dns.exception
+import dns.inet
 import dns.name
 import dns.message
 import dns.rdataclass
@@ -64,7 +65,7 @@ def _wait_for_readable(s, expiration):
 def _wait_for_writable(s, expiration):
     _wait_for([], [s], [s], expiration)
     
-def udp(q, where, timeout=None, port=53, af=socket.AF_INET):
+def udp(q, where, timeout=None, port=53, af=None):
     """Return the response obtained after sending a query via UDP.
 
     @param q: the query
@@ -76,22 +77,33 @@ def udp(q, where, timeout=None, port=53, af=socket.AF_INET):
     @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 socket.AF_INET.
+    @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 of where.
+    If the inference attempt fails, AF_INET is used.
     @type af: int
     @rtype: dns.message.Message object"""
     
     wire = q.to_wire()
+    if af is None:
+        try:
+            af = dns.inet.af_for_address(where)
+        except:
+            af = dns.inet.AF_INET
+    if af == dns.inet.AF_INET:
+        destination = (where, port)
+    elif af == dns.inet.AF_INET6:
+        destination = (where, port, 0, 0)
     s = socket.socket(af, socket.SOCK_DGRAM, 0)
     try:
         expiration = _compute_expiration(timeout)
         s.setblocking(0)
         _wait_for_writable(s, expiration)
-        s.sendto(wire, (where, port))
+        s.sendto(wire, destination)
         _wait_for_readable(s, expiration)
         (wire, from_address) = s.recvfrom(65535)
     finally:
         s.close()
-    if from_address != (where, port):
+    if from_address != destination:
         raise UnexpectedSource
     r = dns.message.from_wire(wire, keyring=q.keyring, request_mac=q.mac)
     if not q.is_response(r):
@@ -133,7 +145,7 @@ def _connect(s, address):
         if v[0] != errno.EINPROGRESS and v[0] != errno.EWOULDBLOCK:
             raise ty, v
 
-def tcp(q, where, timeout=None, port=53, af=socket.AF_INET):
+def tcp(q, where, timeout=None, port=53, af=None):
     """Return the response obtained after sending a query via TCP.
 
     @param q: the query
@@ -145,16 +157,27 @@ def tcp(q, where, timeout=None, port=53, af=socket.AF_INET):
     @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 socket.AF_INET.
+    @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 of where.
+    If the inference attempt fails, AF_INET is used.
     @type af: int
     @rtype: dns.message.Message object"""
     
     wire = q.to_wire()
+    if af is None:
+        try:
+            af = dns.inet.af_for_address(where)
+        except:
+            af = dns.inet.AF_INET
+    if af == dns.inet.AF_INET:
+        destination = (where, port)
+    elif af == dns.inet.AF_INET6:
+        destination = (where, port, 0, 0)
     s = socket.socket(af, socket.SOCK_STREAM, 0)
     try:
         expiration = _compute_expiration(timeout)
         s.setblocking(0)
-        _connect(s, (where, port))
+        _connect(s, destination)
 
         l = len(wire)
 
@@ -175,7 +198,7 @@ def tcp(q, where, timeout=None, port=53, af=socket.AF_INET):
 
 def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
         timeout=None, port=53, keyring=None, keyname=None, relativize=True,
-        af=socket.AF_INET, lifetime=None):
+        af=None, lifetime=None):
     """Return a generator for the responses to a zone transfer.
 
     @param where: where to send the message
@@ -200,7 +223,9 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
     @param relativize: If True, all names in the zone will be relativized to
     the zone origin.
     @type relativize: bool
-    @param af: the address family to use.  The default is socket.AF_INET.
+    @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 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
@@ -214,9 +239,18 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
     if not keyring is None:
         q.use_tsig(keyring, keyname)
     wire = q.to_wire()
+    if af is None:
+        try:
+            af = dns.inet.af_for_address(where)
+        except:
+            af = dns.inet.AF_INET
+    if af == dns.inet.AF_INET:
+        destination = (where, port)
+    elif af == dns.inet.AF_INET6:
+        destination = (where, port, 0, 0)
     s = socket.socket(af, socket.SOCK_STREAM, 0)
     expiration = _compute_expiration(lifetime)
-    _connect(s, (where, port))
+    _connect(s, destination)
     l = len(wire)
     tcpmsg = struct.pack("!H", l) + wire
     _net_write(s, tcpmsg, expiration)