Further changes for the benefit of the new test suite.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Fri, 16 Sep 2005 14:44:11 +0000 (14:44 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Fri, 16 Sep 2005 14:44:11 +0000 (14:44 +0000)
doc/doc-txt/ChangeLog
src/OS/Makefile-Base
src/src/child.c
src/src/dns.c
src/src/host.c

index a11fba9d6ecf0aca0589f2e3339dfcb389f6f4cd..6c39998b5ae4ee52f77eb9f1f13166a78f060fe0 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.233 2005/09/15 16:02:07 fanf2 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.234 2005/09/16 14:44:11 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -199,6 +199,10 @@ TF/04 Fix the ratelimit support in exim_fixdb. Patch provided by Brian
 TF/05 The fix for PH/43 was not completely correct; widen_domains is always
       OK for addresses that are the result of redirections.
 
 TF/05 The fix for PH/43 was not completely correct; widen_domains is always
       OK for addresses that are the result of redirections.
 
+PH/48 A number of further additions for the benefit of the new test suite,
+      including a fake gethostbyname() that interfaces to the fake DNS resolver
+      (see PH/47 above).
+
 
 Exim version 4.52
 -----------------
 
 Exim version 4.52
 -----------------
index 2b805d87051622f365cb315a75a6b6de21b6fe89..e1f6ee6cb3a55e924093ac669ff766fbbdbf9143 100644 (file)
@@ -1,4 +1,4 @@
-# $Cambridge: exim/src/OS/Makefile-Base,v 1.8 2005/09/12 13:50:03 ph10 Exp $
+# $Cambridge: exim/src/OS/Makefile-Base,v 1.9 2005/09/16 14:44:11 ph10 Exp $
 
 # This file is the basis of the main makefile for Exim and friends. The
 # makefile at the top level arranges to build the main makefile by calling
 
 # This file is the basis of the main makefile for Exim and friends. The
 # makefile at the top level arranges to build the main makefile by calling
@@ -727,15 +727,16 @@ test_dbfn:   config.h dbfn.c dummies.o sa-globals.o sa-os.o store.o \
          tod.o version.o $(LIBS) $(DBMLIB)
        rm -f dbfn.o
 
          tod.o version.o $(LIBS) $(DBMLIB)
        rm -f dbfn.o
 
-test_host:   config.h host.c dns.c dummies.o sa-globals.o sa-os.o store.o \
-              string.o tod.o tree.o
+test_host:   config.h child.c host.c dns.c dummies.c sa-globals.o sa-os.o \
+              store.o string.o tod.o tree.o
+       $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE -DTEST_HOST child.c
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE -DTEST_HOST host.c
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE -DTEST_HOST dns.c
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE -DTEST_HOST dummies.c
        $(LNCC) -o test_host $(LFLAGS) \
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE -DTEST_HOST host.c
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE -DTEST_HOST dns.c
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE -DTEST_HOST dummies.c
        $(LNCC) -o test_host $(LFLAGS) \
-         host.o dns.o dummies.o sa-globals.o os.o store.o string.o tod.o tree.o \
-         $(LIBS) $(LIBRESOLV)
-       rm -f dummies.o  host.o dns.o
+         host.o child.o dns.o dummies.o sa-globals.o os.o store.o string.o \
+         tod.o tree.o $(LIBS) $(LIBRESOLV)
+       rm -f child.o dummies.o host.o dns.o
 
 test_os:     os.h os.c dummies.o sa-globals.o store.o string.o tod.o
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE os.c
 
 test_os:     os.h os.c dummies.o sa-globals.o store.o string.o tod.o
        $(CC) -c $(CFLAGS) $(INCLUDE) -DSTAND_ALONE os.c
index 2cd5e6fb99b55c916a046011d5be03a1352e098c..8445bf5ad850020cfcbcb075692a3248bb573296 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/child.c,v 1.5 2005/06/27 14:29:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/child.c,v 1.6 2005/09/16 14:44:11 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -38,7 +38,7 @@ if (oldfd == newfd) return;
 }
 
 
 }
 
 
-
+#ifndef STAND_ALONE
 /*************************************************
 *   Build argv list and optionally re-exec Exim  *
 *************************************************/
 /*************************************************
 *   Build argv list and optionally re-exec Exim  *
 *************************************************/
@@ -233,7 +233,7 @@ if (pid > 0)
 errno = save_errno;
 return (pid_t)(-1);
 }
 errno = save_errno;
 return (pid_t)(-1);
 }
-
+#endif
 
 
 
 
 
 
index 83daf50f39a902dac92071ff80a644e7c791d5da..7395854ff9f17db3ac8be1bff26b4a413f2cfbb1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/dns.c,v 1.10 2005/09/13 15:40:07 ph10 Exp $ */
+/* $Cambridge: exim/src/src/dns.c,v 1.11 2005/09/16 14:44:11 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -30,16 +30,16 @@ static void dns_complete_a6(dns_address ***, dns_answer *, dns_record *,
 /* This function is called instead of res_search() when Exim is running in its
 test harness. It recognizes some special domain names, and uses them to force
 failure and retry responses (optionally with a delay). It also recognises the
 /* This function is called instead of res_search() when Exim is running in its
 test harness. It recognizes some special domain names, and uses them to force
 failure and retry responses (optionally with a delay). It also recognises the
-zones test.ex and 10.in-addr.arpa, and for those it calls an external utility
-that mock-up a nameserver, if it can find the utility. Otherwise, it passes its
-arguments on to res_search().
+zones test.ex, 10.in-addr.arpa, and 0.8.e.f.ip6.arpa, and for those it calls an
+external utility that mock-up a nameserver, if it can find the utility.
+Otherwise, it passes its arguments on to res_search().
 
 Background: the original test suite required a real nameserver to carry the
 
 Background: the original test suite required a real nameserver to carry the
-test.ex and 10.in-addr.arpa zones, whereas the new test suit has the fake
-server for portability. This code supports both.
+test zones, whereas the new test suit has the fake server for portability. This
+code supports both.
 
 Arguments:
 
 Arguments:
-  name        the domain name
+  domain      the domain name
   type        the DNS record type
   answerptr   where to put the answer
   size        size of the answer area
   type        the DNS record type
   answerptr   where to put the answer
   size        size of the answer area
@@ -48,10 +48,16 @@ Returns:      length of returned data, or -1 on error (h_errno set)
 */
 
 static int
 */
 
 static int
-fakens_search(uschar *name, int type, uschar *answerptr, int size)
+fakens_search(uschar *domain, int type, uschar *answerptr, int size)
 {
 {
-int len = Ustrlen(name);
-uschar *endname = name + len;
+int len = Ustrlen(domain);
+uschar *endname;
+uschar name[256];
+
+if (domain[len - 1] == '.') len--;
+Ustrncpy(name, domain, len);
+name[len] = 0;
+endname = name + len;
 
 if (len >= 14 && Ustrcmp(endname - 14, "test.again.dns") == 0)
   {
 
 if (len >= 14 && Ustrcmp(endname - 14, "test.again.dns") == 0)
   {
@@ -77,7 +83,8 @@ if (len >= 13 && Ustrcmp(endname - 13, "test.fail.dns") == 0)
 
 if (Ustrcmp(name, "test.ex") == 0 ||
     (len > 8 && Ustrcmp(endname - 8, ".test.ex") == 0) ||
 
 if (Ustrcmp(name, "test.ex") == 0 ||
     (len > 8 && Ustrcmp(endname - 8, ".test.ex") == 0) ||
-    (len >= 16 && Ustrcmp(endname - 16, ".10.in-addr.arpa") == 0))
+    (len >= 16 && Ustrcmp(endname - 16, ".10.in-addr.arpa") == 0) ||
+    (len >= 17 && Ustrcmp(endname - 17, ".0.8.e.f.ip6.arpa") == 0))
   {
   uschar utilname[256];
   struct stat statbuf;
   {
   uschar utilname[256];
   struct stat statbuf;
@@ -133,7 +140,9 @@ if (Ustrcmp(name, "test.ex") == 0 ||
 
 /* Not test.ex or 10.in-addr.arpa, or fakens utility not found. */
 
 
 /* Not test.ex or 10.in-addr.arpa, or fakens utility not found. */
 
-return res_search(CS name, C_IN, type, answerptr, size);
+DEBUG(D_dns) debug_printf("passing %s on to res_search\n", domain);
+
+return res_search(CS domain, C_IN, type, answerptr, size);
 }
 
 
 }
 
 
index 58e18a757e034d477fc809f80e8f68fac60f8923..ee4461bc8d9b00b3857b688a59173c5f49c59e1e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/host.c,v 1.13 2005/08/22 15:28:20 ph10 Exp $ */
+/* $Cambridge: exim/src/src/host.c,v 1.14 2005/09/16 14:44:11 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -102,6 +102,13 @@ number of multihomed host IP addresses into the order, so as to get
 repeatability. This doesn't have to be efficient. But don't interchange IPv4
 and IPv6 addresses!
 
 repeatability. This doesn't have to be efficient. But don't interchange IPv4
 and IPv6 addresses!
 
+NOTE:
+This sorting is not necessary for the new test harness, because it
+doesn't call the real DNS resolver, and its output is repeatable. However,
+until the old test harness is discarded, we need to retain this capability.
+The new harness is being developed towards the end of 2005. It will be some
+time before it can do everything that the old one can do.
+
 Arguments:
   host        -> the first host item
   last        -> the last host item
 Arguments:
   host        -> the first host item
   last        -> the last host item
@@ -135,6 +142,148 @@ while (!done)
 
 
 
 
 
 
+/*************************************************
+*       Replace gethostbyname() when testing     *
+*************************************************/
+
+/* This function is called instead of gethostbyname(), gethostbyname2(), or
+getipnodebyname() when running in the test harness. It uses only the DNS to
+look up the host name. In the new test harness, this means it will access only
+the fake DNS resolver. In the old harness it will call the real resolver and
+access the test zone.
+
+Arguments:
+  name          the host name or a textual IP address
+  af            AF_INET or AF_INET6
+  error_num     where to put an error code:
+                HOST_NOT_FOUND/TRY_AGAIN/NO_RECOVERY/NO_DATA
+
+Returns:        a hostent structure or NULL for an error
+*/
+
+static struct hostent *
+host_fake_gethostbyname(uschar *name, int af, int *error_num)
+{
+int ipa;
+int alen = (af == AF_INET)? sizeof(struct in_addr):sizeof(struct in6_addr);
+uschar *lname = name;
+uschar *adds;
+uschar **alist;
+struct hostent *yield;
+dns_answer dnsa;
+dns_scan dnss;
+dns_record *rr;
+
+DEBUG(D_host_lookup)
+  debug_printf("using host_fake_gethostbyname for %s (%s)\n", name,
+    (af == AF_INET)? "IPv4" : "IPv6");
+
+if (Ustrcmp(name, "localhost") == 0)
+  lname = (af == AF_INET)? US"127.0.0.1" : US"::1";
+
+/* Handle a literal IP address */
+
+ipa = string_is_ip_address(lname, NULL);
+if (ipa != 0)
+  {
+  if ((ipa == 4 && af == AF_INET) ||
+      (ipa == 6 && af == AF_INET6))
+    {
+    int i, n;
+    int x[4];
+    yield = store_get(sizeof(struct hostent));
+    alist = store_get(2 * sizeof(char *));
+    adds  = store_get(alen);
+    yield->h_name = CS name;
+    yield->h_aliases = NULL;
+    yield->h_addrtype = af;
+    yield->h_length = alen;
+    yield->h_addr_list = CSS alist;
+    *alist++ = adds;
+    n = host_aton(lname, x);
+    for (i = 0; i < n; i++)
+      {
+      int y = x[i];
+      *adds++ = (y >> 24) & 255;
+      *adds++ = (y >> 16) & 255;
+      *adds++ = (y >> 8) & 255;
+      *adds++ = y & 255;
+      }
+    *alist = NULL;
+    }
+
+  /* Wrong kind of literal address */
+
+  else
+    {
+    *error_num = HOST_NOT_FOUND;
+    return NULL;
+    }
+  }
+
+/* Handle a host name */
+
+else
+  {
+  int type = (af == AF_INET)? T_A:T_AAAA;
+  int rc = dns_lookup(&dnsa, lname, type, NULL);
+  int count = 0;
+
+  switch(rc)
+    {
+    case DNS_SUCCEED: break;
+    case DNS_NOMATCH: *error_num = HOST_NOT_FOUND; return NULL;
+    case DNS_NODATA:  *error_num = NO_DATA; return NULL;
+    case DNS_AGAIN:   *error_num = TRY_AGAIN; return NULL;
+    default:
+    case DNS_FAIL:    *error_num = NO_RECOVERY; return NULL;
+    }
+
+  for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
+       rr != NULL;
+       rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
+    {
+    if (rr->type == type) count++;
+    }
+
+  yield = store_get(sizeof(struct hostent));
+  alist = store_get((count + 1) * sizeof(char **));
+  adds  = store_get(count *alen);
+
+  yield->h_name = CS name;
+  yield->h_aliases = NULL;
+  yield->h_addrtype = af;
+  yield->h_length = alen;
+  yield->h_addr_list = CSS alist;
+
+  for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
+       rr != NULL;
+       rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
+    {
+    int i, n;
+    int x[4];
+    dns_address *da;
+    if (rr->type != type) continue;
+    da = dns_address_from_rr(&dnsa, rr);
+    *alist++ = adds;
+    n = host_aton(da->address, x);
+    for (i = 0; i < n; i++)
+      {
+      int y = x[i];
+      *adds++ = (y >> 24) & 255;
+      *adds++ = (y >> 16) & 255;
+      *adds++ = (y >> 8) & 255;
+      *adds++ = y & 255;
+      }
+    }
+  *alist = NULL;
+  }
+
+return yield;
+}
+
+
+
 /*************************************************
 *       Build chain of host items from list      *
 *************************************************/
 /*************************************************
 *       Build chain of host items from list      *
 *************************************************/
@@ -1813,16 +1962,27 @@ for (i = 1; i <= times;
   struct hostent *hostdata;
 
   #if HAVE_IPV6
   struct hostent *hostdata;
 
   #if HAVE_IPV6
+  if (running_in_test_harness)
+    hostdata = host_fake_gethostbyname(host->name, af, &error_num);
+  else
+    {
     #if HAVE_GETIPNODEBYNAME
     hostdata = getipnodebyname(CS host->name, af, 0, &error_num);
     #else
     hostdata = gethostbyname2(CS host->name, af);
     error_num = h_errno;
     #endif
     #if HAVE_GETIPNODEBYNAME
     hostdata = getipnodebyname(CS host->name, af, 0, &error_num);
     #else
     hostdata = gethostbyname2(CS host->name, af);
     error_num = h_errno;
     #endif
-  #else
-  hostdata = gethostbyname(CS host->name);
-  error_num = h_errno;
-  #endif
+    }
+
+  #else    /* not HAVE_IPV6 */
+  if (running_in_test_harness)
+    hostdata = host_fake_gethostbyname(host->name, AF_INET, &error_num);
+  else
+    {
+    hostdata = gethostbyname(CS host->name);
+    error_num = h_errno;
+    }
+  #endif   /* HAVE_IPV6 */
 
   if (hostdata == NULL)
     {
 
   if (hostdata == NULL)
     {
@@ -2053,7 +2213,6 @@ to do so. On an IPv4 system, go round the loop once only, looking only for A
 records. */
 
 #if HAVE_IPV6
 records. */
 
 #if HAVE_IPV6
-
   #ifndef STAND_ALONE
     if (dns_ipv4_lookup != NULL &&
         match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
   #ifndef STAND_ALONE
     if (dns_ipv4_lookup != NULL &&
         match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
@@ -2317,8 +2476,10 @@ if ((whichrrs & HOST_FIND_BY_SRV) != 0)
 
   if (rc == DNS_FAIL || rc == DNS_AGAIN)
     {
 
   if (rc == DNS_FAIL || rc == DNS_AGAIN)
     {
+    #ifndef STAND_ALONE
     if (match_isinlist(host->name, &srv_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
         TRUE, NULL) != OK)
     if (match_isinlist(host->name, &srv_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
         TRUE, NULL) != OK)
+    #endif
       return HOST_FIND_AGAIN;
     DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
       "(domain in srv_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
       return HOST_FIND_AGAIN;
     DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
       "(domain in srv_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
@@ -2339,8 +2500,10 @@ if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0)
   if (rc == DNS_NOMATCH) return HOST_FIND_FAILED;
   if (rc == DNS_FAIL || rc == DNS_AGAIN)
     {
   if (rc == DNS_NOMATCH) return HOST_FIND_FAILED;
   if (rc == DNS_FAIL || rc == DNS_AGAIN)
     {
+    #ifndef STAND_ALONE
     if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
         TRUE, NULL) != OK)
     if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
         TRUE, NULL) != OK)
+    #endif
       return HOST_FIND_AGAIN;
     DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
       "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
       return HOST_FIND_AGAIN;
     DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
       "(domain in mx_fail_domains)\n", (rc == DNS_FAIL)? "FAIL":"AGAIN");
@@ -2986,18 +3149,6 @@ return yield;
 
 #ifdef STAND_ALONE
 
 
 #ifdef STAND_ALONE
 
-BOOL alldigits(uschar *buffer)
-{
-if (!isdigit(*buffer)) return FALSE;
-if (*buffer == '0' && buffer[1] == 'x')
-  {
-  buffer++;
-  while (isxdigit(*(++buffer)));
-  }
-else while (isdigit(*(++buffer)));
-return (*buffer == 0);
-}
-
 int main(int argc, char **cargv)
 {
 host_item h;
 int main(int argc, char **cargv)
 {
 host_item h;
@@ -3053,6 +3204,12 @@ while (Ufgets(buffer, 256, stdin) != NULL)
   else if (Ustrcmp(buffer, "no_qualify_single") == 0) qualify_single = FALSE;
   else if (Ustrcmp(buffer, "search_parents") == 0) search_parents = TRUE;
   else if (Ustrcmp(buffer, "no_search_parents") == 0) search_parents = FALSE;
   else if (Ustrcmp(buffer, "no_qualify_single") == 0) qualify_single = FALSE;
   else if (Ustrcmp(buffer, "search_parents") == 0) search_parents = TRUE;
   else if (Ustrcmp(buffer, "no_search_parents") == 0) search_parents = FALSE;
+  else if (Ustrcmp(buffer, "test_harness") == 0)
+    running_in_test_harness = !running_in_test_harness;
+  else if (Ustrcmp(buffer, "res_debug") == 0)
+    {
+    _res.options ^= RES_DEBUG;
+    }
   else if (Ustrncmp(buffer, "retrans", 7) == 0)
     {
     (void)sscanf(CS(buffer+8), "%d", &dns_retrans);
   else if (Ustrncmp(buffer, "retrans", 7) == 0)
     {
     (void)sscanf(CS(buffer+8), "%d", &dns_retrans);
@@ -3063,12 +3220,6 @@ while (Ufgets(buffer, 256, stdin) != NULL)
     (void)sscanf(CS(buffer+6), "%d", &dns_retry);
     _res.retry = dns_retry;
     }
     (void)sscanf(CS(buffer+6), "%d", &dns_retry);
     _res.retry = dns_retry;
     }
-  else if (alldigits(buffer))
-    {
-    debug_selector = Ustrtol(buffer, NULL, 0);
-    _res.options &= ~RES_DEBUG;
-    DEBUG(D_resolver) _res.options |= RES_DEBUG;
-    }
   else
     {
     int flags = whichrrs;
   else
     {
     int flags = whichrrs;