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 8a8f552f45fc8466eb6684d0586b6c5149bf3778..5e213d772ba325b510344b053624db220195333e 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 d5d3407139a2e7a3ec61d353b702b1aabf91c6ea..ee9f55c31fd1d0a64a6a3c526a1df66e81d54129 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 237b734a6ba42acea2891fc7dda70d83b82f4c2f..a5a154741aab2454185370f9af4d28f92ea78b4f 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 96d634efeb0a74ac0df73be84b98115382a85852..998adc3ea0a924c44a3747b43b55b31d13c17e08 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 493575d36b6e599f9a8faf93b1a2f53b7b1ab73e..8b9f3bbe96343759bced2376258fc55911d6f787 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 14fdc5a2e5dc1b2da0bcd4447e2610f0dc2dcbc9..492e535744fb793487fbf3490d84bb28e5947b40 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))