From 33397d198607bb789306b1856a9a38aaf9aa9561 Mon Sep 17 00:00:00 2001 From: Philip Hazel Date: Fri, 19 Nov 2004 09:45:54 +0000 Subject: [PATCH] Implement the pseudo dns lookup type "zns" for ${dnsdb lookups. --- doc/doc-txt/ChangeLog | 12 ++++++- doc/doc-txt/NewStuff | 23 ++++++++++++- src/src/dns.c | 74 ++++++++++++++++++++++++++++++++++++----- src/src/exim.h | 7 +++- src/src/functions.h | 3 +- src/src/lookups/dnsdb.c | 16 ++++++--- 6 files changed, 118 insertions(+), 17 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 8a8f552f4..5e213d772 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -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 ----------------- diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index d5d340713..ee9f55c31 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -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 ------------ diff --git a/src/src/dns.c b/src/src/dns.c index 237b734a6..a5a154741 100644 --- a/src/src/dns.c +++ b/src/src/dns.c @@ -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. */ diff --git a/src/src/exim.h b/src/src/exim.h index 96d634efe..998adc3ea 100644 --- a/src/src/exim.h +++ b/src/src/exim.h @@ -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 diff --git a/src/src/functions.h b/src/src/functions.h index 493575d36..8b9f3bbe9 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -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); diff --git a/src/src/lookups/dnsdb.c b/src/src/lookups/dnsdb.c index 14fdc5a2e..492e53574 100644 --- a/src/src/lookups/dnsdb.c +++ b/src/src/lookups/dnsdb.c @@ -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)) -- 2.30.2