]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
allow source address and port to be specified in query.{udp,tcp,xfr}
authorBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:33:20 +0000 (05:33 +0000)
committerBob Halley <halley@dnspython.org>
Fri, 2 Sep 2005 05:33:20 +0000 (05:33 +0000)
Original author: Bob Halley <halley@dnspython.org>
Date: 2005-08-01 04:24:59

ChangeLog
README
dns/query.py

index 26bf59040a199db825bafc91d7149e34288f0375..cbfc804e23c8b4b6fb9f6e5e298591f2bf793fe7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,19 @@
+2005-07-31  Bob Halley  <halley@nominum.com>
+
+       * (Version 1.3.4 released)
+
 2005-07-31  Bob Halley  <halley@dnspython.org>
 
        * dns/message.py (make_response): Trying to respond to a response
          threw a NameError while trying to throw a FormErr since it used
          the wrong name for the FormErr exception.
 
+       * dns/query.py (_connect): We needed to ignore EALREADY too.
+
+       * dns/query.py: Optional "source" and "source_port" parameters
+         have been added to udp(), tcp(), and xfr().  Thanks to Ralf
+         Weber for suggesting the change and providing a patch.
+
 2005-06-05  Bob Halley  <halley@dnspython.org>
 
        * dns/query.py: The requirement that the "where" parameter be
diff --git a/README b/README
index 2ca957c7eec10d0d84436f6bcb2e0163d68919e5..1ca7b55abf77852e915fef8ee22ef3a3272dd8a1 100644 (file)
--- a/README
+++ b/README
@@ -22,13 +22,13 @@ development by continuing to employ the author :).
 
 ABOUT THIS RELEASE
 
-This is dnspython 1.3.4.
+This is dnspython 1.3.4
 
 New since 1.3.3:
 
-       The requirement that the "where" parameter in dns.query.{udp,tcp,xfr}
-       be an IPv4 or IPv6 address is now documented.
-
+       The source address and port may now be specified when calling
+       dns.query.{udp,tcp,xfr}.
+       
        The resolver now does exponential backoff each time it runs
        through all of the nameservers.
 
index f8c0ae3e0732f8ddf09cf914d6eb9209c0117a6f..86df19c9f2cfd91bf617a6033fe35159e2c2c11e 100644 (file)
@@ -64,8 +64,8 @@ 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=None):
+
+def udp(q, where, timeout=None, port=53, af=None, source=None, source_port=0):
     """Return the response obtained after sending a query via UDP.
 
     @param q: the query
@@ -81,7 +81,12 @@ def udp(q, where, timeout=None, port=53, af=None):
     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"""
+    @rtype: dns.message.Message object
+    @param source: source address.  The default is the IPv4 wildcard address.
+    @type source: string
+    @param source_port: The port from which to send the message.
+    The default is 0.
+    @type port: int"""
     
     wire = q.to_wire()
     if af is None:
@@ -91,12 +96,18 @@ def udp(q, where, timeout=None, port=53, af=None):
             af = dns.inet.AF_INET
     if af == dns.inet.AF_INET:
         destination = (where, port)
+        if source is not None:
+            source = (source, source_port)
     elif af == dns.inet.AF_INET6:
         destination = (where, port, 0, 0)
+        if source is not None:
+            source = (source, source_port, 0, 0)
     s = socket.socket(af, socket.SOCK_DGRAM, 0)
     try:
         expiration = _compute_expiration(timeout)
         s.setblocking(0)
+        if source is not None:
+            s.bind(source)
         _wait_for_writable(s, expiration)
         s.sendto(wire, destination)
         _wait_for_readable(s, expiration)
@@ -142,10 +153,12 @@ def _connect(s, address):
         s.connect(address)
     except socket.error:
         (ty, v) = sys.exc_info()[:2]
-        if v[0] != errno.EINPROGRESS and v[0] != errno.EWOULDBLOCK and v[0] != errno.EALREADY:
+        if v[0] != errno.EINPROGRESS and \
+               v[0] != errno.EWOULDBLOCK and \
+               v[0] != errno.EALREADY:
             raise ty, v
 
-def tcp(q, where, timeout=None, port=53, af=None):
+def tcp(q, where, timeout=None, port=53, af=None, source=None, source_port=0):
     """Return the response obtained after sending a query via TCP.
 
     @param q: the query
@@ -161,7 +174,12 @@ def tcp(q, where, timeout=None, port=53, af=None):
     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"""
+    @rtype: dns.message.Message object
+    @param source: source address.  The default is the IPv4 wildcard address.
+    @type source: string
+    @param source_port: The port from which to send the message.
+    The default is 0.
+    @type port: int"""
     
     wire = q.to_wire()
     if af is None:
@@ -171,12 +189,18 @@ def tcp(q, where, timeout=None, port=53, af=None):
             af = dns.inet.AF_INET
     if af == dns.inet.AF_INET:
         destination = (where, port)
+        if source is not None:
+            source = (source, source_port)
     elif af == dns.inet.AF_INET6:
         destination = (where, port, 0, 0)
+        if source is not None:
+            source = (source, source_port, 0, 0)
     s = socket.socket(af, socket.SOCK_STREAM, 0)
     try:
         expiration = _compute_expiration(timeout)
         s.setblocking(0)
+        if source is not None:
+            s.bind(source)
         _connect(s, destination)
 
         l = len(wire)
@@ -198,7 +222,7 @@ def tcp(q, where, timeout=None, port=53, af=None):
 
 def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
         timeout=None, port=53, keyring=None, keyname=None, relativize=True,
-        af=None, lifetime=None):
+        af=None, lifetime=None, source=None, source_port=0):
     """Return a generator for the responses to a zone transfer.
 
     @param where: where to send the message
@@ -231,7 +255,12 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
     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."""
+    @rtype: generator of dns.message.Message objects.
+    @param source: source address.  The default is the IPv4 wildcard address.
+    @type source: string
+    @param source_port: The port from which to send the message.
+    The default is 0.
+    @type port: int"""
 
     if isinstance(zone, str):
         zone = dns.name.from_text(zone)
@@ -246,9 +275,15 @@ def xfr(where, zone, rdtype=dns.rdatatype.AXFR, rdclass=dns.rdataclass.IN,
             af = dns.inet.AF_INET
     if af == dns.inet.AF_INET:
         destination = (where, port)
+        if source is not None:
+            source = (source, source_port)
     elif af == dns.inet.AF_INET6:
         destination = (where, port, 0, 0)
+        if source is not None:
+            source = (source, source_port, 0, 0)
     s = socket.socket(af, socket.SOCK_STREAM, 0)
+    if source is not None:
+        s.bind(source)
     expiration = _compute_expiration(lifetime)
     _connect(s, destination)
     l = len(wire)