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

Reply via email to