Implement the pseudo dns lookup type "zns" for ${dnsdb lookups.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Fri, 19 Nov 2004 09:45:54 +0000 (09:45 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Fri, 19 Nov 2004 09:45:54 +0000 (09:45 +0000)
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/dns.c
src/src/exim.h
src/src/functions.h
src/src/lookups/dnsdb.c

index 8a8f552..5e213d7 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.33 2004/11/18 11:17:33 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.34 2004/11/19 09:45:54 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -142,6 +142,16 @@ Exim version 4.44
     canonical form (fully expanded) before being placed in
     $sender_host_address.
 
+36. The table in the code that translates DNS record types into text (T_A to
+    "A" for instance) was missing entries for NS and CNAME. It is just possible
+    that this could have caused confusion if both these types were looked up
+    for the same domain, because the text type is used as part of Exim's
+    per-process caching. But the chance of anyone hitting this buglet seems
+    very small.
+
+37. The dnsdb lookup has a new type, "zns", which walks up the domain tree
+    until it finds some nameserver records. It should be used with care.
+
 
 Exim version 4.43
 -----------------
index d5d3407..ee9f55c 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.11 2004/11/17 16:12:26 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.12 2004/11/19 09:45:54 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -108,6 +108,27 @@ Version 4.44
 
     Previously this was a syntax error.
 
+12. There is now a new "record type" that can be specified in dnsdb lookups. It
+    is "zns" (for "zone NS"). It performs a lookup for NS records on the given
+    domain, but if none are found, it removes the first component of the domain
+    name, and tries again. This process continues until NS records are found
+    or there are no more components left (or there's a DNS error). In other
+    words, it may return the name servers for a top-level domain, but it never
+    returns the root name servers. If there are no NS records for the top-level
+    domain, the lookup fails.
+
+    For example, ${lookup dnsdb{zns=xxx.quercite.com}} returns the name
+    servers for quercite.com, whereas ${lookup dnsdb{zns=xxx.edu}} returns
+    the name servers for edu, assuming in each case that there are no NS
+    records for the full domain name.
+
+    You should be careful about how you use this lookup because, unless the
+    top-level domain does not exist, the lookup will always return some host
+    names. The sort of use to which this might be put is for seeing if the name
+    servers for a given domain are on a blacklist. You can probably assume that
+    the name servers for the high-level domains such as .com or .co.uk are not
+    going to be on such a list.
+
 
 Version 4.43
 ------------
index 237b734..a5a1547 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/dns.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/dns.c,v 1.2 2004/11/19 09:45:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -258,14 +258,16 @@ dns_text_type(int t)
 {
 switch(t)
   {
-  case T_A:    return US"A";
-  case T_MX:   return US"MX";
-  case T_AAAA: return US"AAAA";
-  case T_A6:   return US"A6";
-  case T_TXT:  return US"TXT";
-  case T_PTR:  return US"PTR";
-  case T_SRV:  return US"SRV";
-  default:     return US"?";
+  case T_A:     return US"A";
+  case T_MX:    return US"MX";
+  case T_AAAA:  return US"AAAA";
+  case T_A6:    return US"A6";
+  case T_TXT:   return US"TXT";
+  case T_PTR:   return US"PTR";
+  case T_SRV:   return US"SRV";
+  case T_NS:    return US"NS";
+  case T_CNAME: return US"CNAME";  
+  default:      return US"?";
   }
 }
 
@@ -617,6 +619,60 @@ return DNS_FAIL;
 
 
 
+
+
+
+/************************************************
+*    Do a DNS lookup and handle virtual types   *
+************************************************/
+
+/* This function handles some invented "lookup types" that synthesize feature 
+not available in the basic types. The special types all have negative values. 
+Positive type values are passed straight on to dns_lookup().
+
+Arguments:
+  dnsa                  pointer to dns_answer structure
+  name                  domain name to look up
+  type                  DNS record type (T_A, T_MX, etc or a "special")
+  fully_qualified_name  if not NULL, return the returned name here if its
+                          contents are different (i.e. it must be preset)
+
+Returns:                DNS_SUCCEED   successful lookup
+                        DNS_NOMATCH   name not found
+                        DNS_NODATA    no data found
+                        DNS_AGAIN     soft failure, try again later
+                        DNS_FAIL      DNS failure
+*/
+
+int
+dns_special_lookup(dns_answer *dnsa, uschar *name, int type, 
+  uschar **fully_qualified_name)
+{
+if (type >= 0) return dns_lookup(dnsa, name, type, fully_qualified_name);
+
+/* Find nameservers for the domain or the nearest enclosing zone, excluding the 
+root servers. */
+
+if (type == T_ZNS)
+  {
+  uschar *d = name;
+  while (d != 0)
+    {
+    int rc = dns_lookup(dnsa, d, T_NS, fully_qualified_name);
+    if (rc != DNS_NOMATCH && rc != DNS_NODATA) return rc;
+    while (*d != 0 && *d != '.') d++;
+    if (*d++ == 0) break; 
+    }
+  return DNS_NOMATCH;     
+  } 
+
+/* Control should never reach here */
+
+return DNS_FAIL;
+}
+
+
+
 /* Support for A6 records has been commented out since they were demoted to
 experimental status at IETF 51. */
 
index 96d634e..998adc3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/exim.h,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/exim.h,v 1.2 2004/11/19 09:45:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -278,6 +278,11 @@ header files. I don't suppose they have T_SRV either. */
 #define T_SRV 33
 #endif
 
+/* We use the private type T_ZNS for retrieving the nameservers for the
+enclosing zone of a domain. */
+
+#define T_ZNS (-1)
+
 /* The resolv.h header defines __P(x) on some Solaris 2.5.1 systems (without
 checking that it is already defined, in fact). This conflicts with other
 headers that behave likewise (see below), leading to compiler warnings. Arrange
index 493575d..8b9f3bb 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/functions.h,v 1.4 2004/11/18 11:17:33 ph10 Exp $ */
+/* $Cambridge: exim/src/src/functions.h,v 1.5 2004/11/19 09:45:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -74,6 +74,7 @@ extern void    dns_build_reverse(uschar *, uschar *);
 extern void    dns_init(BOOL, BOOL);
 extern int     dns_basic_lookup(dns_answer *, uschar *, int);
 extern int     dns_lookup(dns_answer *, uschar *, int, uschar **);
+extern int     dns_special_lookup(dns_answer *, uschar *, int, uschar **);
 extern dns_record *dns_next_rr(dns_answer *, dns_scan *, int);
 extern uschar *dns_text_type(int);
 
index 14fdc5a..492e535 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.1 2004/10/07 13:10:01 ph10 Exp $ */
+/* $Cambridge: exim/src/src/lookups/dnsdb.c,v 1.2 2004/11/19 09:45:54 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -35,7 +35,9 @@ static char *type_names[] = {
   "ns",
   "ptr",
   "srv",
-  "txt" };
+  "txt",
+  "zns" 
+};
 
 static int type_values[] = {
   T_A,
@@ -50,7 +52,9 @@ static int type_values[] = {
   T_NS,
   T_PTR,
   T_SRV,
-  T_TXT };
+  T_TXT,
+  T_ZNS      /* Private type for "zone nameservers" */
+};
 
 
 /*************************************************
@@ -139,11 +143,15 @@ DEBUG(D_lookup) debug_printf("dnsdb key: %s\n", keystring);
 in this run. Then do the lookup and sort out the result. */
 
 dns_init(FALSE, FALSE);
-rc = dns_lookup(&dnsa, keystring, type, NULL);
+rc = dns_special_lookup(&dnsa, keystring, type, NULL);
 
 if (rc == DNS_NOMATCH || rc == DNS_NODATA) return FAIL;
 if (rc != DNS_SUCCEED) return DEFER;
 
+/* If the lookup was a pseudo-type, change it to the correct type for searching 
+the returned records; then search for them. */
+
+if (type == T_ZNS) type = T_NS;
 for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
      rr != NULL;
      rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))