summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--README8
-rw-r--r--dns/query.py51
3 files changed, 57 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 26bf590..cbfc804 100644
--- 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 2ca957c..1ca7b55 100644
--- 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.
diff --git a/dns/query.py b/dns/query.py
index f8c0ae3..86df19c 100644
--- a/dns/query.py
+++ b/dns/query.py
@@ -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)