Hi,
I wanted an easy way to send non-recursive queries using dnspython.
I considered adjusting the query() interface to take an RD bit argument
and adjust the flags in the Message that is returned from make_query().
That seemed inflexible. What about the other flags (or opcodes, or what
have you) that one might like to tweak?
Instead I chose to extend query() to accept a dns.message.Message
argument. In this way query()'s interface won't need to change further
to accommodate any funny business I want do to the query.
I've been using it something like this:
def iter_query(qname, rdtype, rdclass = dns.rdataclass.IN):
"""Create a dns.message.Message object suitable for an iterative
DNS query -- RD==0
Returns: dns.message.Message object."""
q = dns.message.make_query(qname, rdtype, rdclass)
q.flags &= ~dns.flags.RD
return q
qry = iter_query("www.yahoo.com", "A")
res = dns.resolver.Resolver()
response = res.query(msg=qry).response
Other changes to note:
. The qname arguments defaults to the root name. It needed a default
value so I could supply only the msg argument.
. No search list is applied to the query name in the msg Message.
Patch is attached.
Thanks,
james
--
Times flies like an arrow. Fruit flies like bananas.
--- dns/resolver.py.orig Wed Oct 11 12:33:30 2006
+++ dns/resolver.py Mon Oct 16 18:27:12 2006
@@ -467,14 +467,17 @@
raise Timeout
return min(self.lifetime - duration, self.timeout)
- def query(self, qname, rdtype=dns.rdatatype.A, rdclass=dns.rdataclass.IN,
- tcp=False):
+ def query(self, qname=".", rdtype=dns.rdatatype.A,
+ rdclass=dns.rdataclass.IN, tcp=False, msg=None):
"""Query nameservers to find the answer to the question.
The I{qname}, I{rdtype}, and I{rdclass} parameters may be objects
of the appropriate type, or strings that can be converted into objects
of the appropriate type. E.g. For I{rdtype} the integer 2 and the
the string 'NS' both mean to query for records with DNS rdata type NS.
+ If an instance of dns.message.Message is suppiled as I{msg} it is
+ used as the complete query. The search list is not applied in this
+ case.
@param qname: the query name
@type qname: dns.name.Name object or string
@@ -484,30 +487,40 @@
@type rdclass: int or string
@param tcp: use TCP to make the query (default is False).
@type tcp: bool
+ @param msg: a pre-computed DNS message to use as the query
+ @type msg: dns.message.Message instance
@rtype: dns.resolver.Answer instance
@raises Timeout: no answers could be found in the specified lifetime
@raises NXDOMAIN: the query name does not exist
@raises NoAnswer: the response did not contain an answer
@raises NoNameservers: no non-broken nameservers are available to
answer the question."""
-
- if isinstance(qname, (str, unicode)):
- qname = dns.name.from_text(qname, None)
- if isinstance(rdtype, str):
- rdtype = dns.rdatatype.from_text(rdtype)
- if isinstance(rdclass, str):
- rdclass = dns.rdataclass.from_text(rdclass)
+
qnames_to_try = []
- if qname.is_absolute():
- qnames_to_try.append(qname)
+ if isinstance(msg, dns.message.Message):
+ qname = msg.question[0].name
+ rdtype = msg.question[0].rdtype
+ rdclass = msg.question[0].rdclass
+ qnames_to_try = [qname]
else:
- if len(qname) > 1:
- qnames_to_try.append(qname.concatenate(dns.name.root))
- if self.search:
- for suffix in self.search:
- qnames_to_try.append(qname.concatenate(suffix))
+ msg = None
+ if isinstance(qname, (str, unicode)):
+ qname = dns.name.from_text(qname, None)
+ if isinstance(rdtype, str):
+ rdtype = dns.rdatatype.from_text(rdtype)
+ if isinstance(rdclass, str):
+ rdclass = dns.rdataclass.from_text(rdclass)
+ if qname.is_absolute():
+ qnames_to_try.append(qname)
else:
- qnames_to_try.append(qname.concatenate(self.domain))
+ if len(qname) > 1:
+ qnames_to_try.append(qname.concatenate(dns.name.root))
+ if self.search:
+ for suffix in self.search:
+ qnames_to_try.append(qname.concatenate(suffix))
+ else:
+ qnames_to_try.append(qname.concatenate(self.domain))
+
all_nxdomain = True
start = time.time()
for qname in qnames_to_try:
@@ -515,7 +528,12 @@
answer = self.cache.get((qname, rdtype, rdclass))
if answer:
return answer
- request = dns.message.make_query(qname, rdtype, rdclass)
+
+ if msg is None:
+ request = dns.message.make_query(qname, rdtype, rdclass)
+ else:
+ request = msg
+
if not self.keyname is None:
request.use_tsig(self.keyring, self.keyname)
request.use_edns(self.edns, self.ednsflags, self.payload)
_______________________________________________
dnspython-dev mailing list
[email protected]
http://woof.play-bow.org/mailman/listinfo/dnspython-dev