Teach the DNS server how to delegate
authorMitchell E Berger <mitchb@mit.edu>
Sat, 29 Oct 2011 09:38:23 +0000 (05:38 -0400)
committerMitchell E Berger <mitchb@mit.edu>
Sat, 29 Oct 2011 09:38:23 +0000 (05:38 -0400)
debian/changelog
invirt-dns

index f61ea58..20b87e8 100644 (file)
@@ -1,3 +1,9 @@
+invirt-dns (0.0.12) unstable; urgency=low
+
+  * Teach the DNS server how to delegate.
+
+ -- Mitchell Berger <mitchb@mit.edu>  Sat, 29 Oct 2011 05:37:00 -0400
+
 invirt-dns (0.0.11) unstable; urgency=low
 
   * Refactor DNS logic.
 invirt-dns (0.0.11) unstable; urgency=low
 
   * Refactor DNS logic.
index d5fa021..de53e0d 100755 (executable)
@@ -147,9 +147,9 @@ class DatabaseAuthority(common.ResolverBase):
             additional = []
         return defer.succeed((results, authority, additional))
 
             additional = []
         return defer.succeed((results, authority, additional))
 
-class QuotingBindAuthority(authority.BindAuthority):
+class DelegatingQuotingBindAuthority(authority.BindAuthority):
     """
     """
-    A BindAuthority that (almost) deals with quoting correctly
+    A delegating BindAuthority that (almost) deals with quoting correctly
     
     This will catch double quotes as marking the start or end of a
     quoted phrase, unless the double quote is escaped by a backslash
     
     This will catch double quotes as marking the start or end of a
     quoted phrase, unless the double quote is escaped by a backslash
@@ -194,12 +194,38 @@ class QuotingBindAuthority(authority.BindAuthority):
             L.append(split_line)
         return filter(None, L)
 
             L.append(split_line)
         return filter(None, L)
 
+    def _lookup(self, name, cls, type, timeout = None):
+        maybeDelegate = False
+        deferredResult = authority.BindAuthority._lookup(self, name, cls,
+                                                         type, timeout)
+        # If we didn't find an exact match for the name we were seeking,
+        # check if it's within a subdomain we're supposed to delegate to
+        # some other DNS server.
+        while (isinstance(deferredResult.result, failure.Failure)
+               and name.find('.') != -1):
+            maybeDelegate = True
+            name = name[name.find('.') + 1 :]
+            deferredResult = authority.BindAuthority._lookup(self, name, cls,
+                                                             dns.NS, timeout)
+        # If we found somewhere to delegate the query to, our _lookup()
+        # for the NS record resulted in it being in the 'results' section.
+        # We need to instead return that information in the 'authority'
+        # section to delegate, and return an empty 'results' section
+        # (because we didn't find the name we were asked about).  We
+        # leave the 'additional' section as we received it because it
+        # may contain A records for the DNS server we're delegating to.
+        if maybeDelegate and not isinstance(deferredResult.result,
+                                            failure.Failure):
+            (nsResults, nsAuthority, nsAdditional) = deferredResult.result
+            deferredResult = defer.succeed(([], nsResults, nsAdditional))
+        return deferredResult
+
 if '__main__' == __name__:
     resolvers = []
     try:
         for zone in config.dns.zone_files:
             for origin in config.dns.domains:
 if '__main__' == __name__:
     resolvers = []
     try:
         for zone in config.dns.zone_files:
             for origin in config.dns.domains:
-                r = QuotingBindAuthority(zone)
+                r = DelegatingQuotingBindAuthority(zone)
                 # This sucks, but if I want a generic zone file, I have to
                 # reload the information by hand
                 r.origin = origin
                 # This sucks, but if I want a generic zone file, I have to
                 # reload the information by hand
                 r.origin = origin