[exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog NewSt…

Góra strony
Delete this message
Reply to this message
Autor: Philip Hazel
Data:  
Dla: exim-cvs
Temat: [exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog NewStuff exim/exim-src/src verify.c exim/exim-test-orig/AutoTest/confs 596 exim/exim-test-orig/AutoTest/log 596 exim/exim-test-orig/AutoTest/re
ph10 2004/11/22 11:30:04 GMT

  Modified files:
    exim-doc/doc-txt     ChangeLog NewStuff 
    exim-src/src         verify.c 
    exim-test-orig/AutoTest/stderr 320 
  Added files:
    exim-test-orig/AutoTest/confs 596 
    exim-test-orig/AutoTest/log 596 
    exim-test-orig/AutoTest/rejectlog 596 
    exim-test-orig/AutoTest/scripts 596 
    exim-test-orig/AutoTest/stdout 596 
  Log:
  Allow a list of IP addresses or names to follow / in a dnslists ACL
  condition.


  Revision  Changes    Path
  1.36      +4 -0      exim/exim-doc/doc-txt/ChangeLog
  1.14      +30 -0     exim/exim-doc/doc-txt/NewStuff
  1.7       +309 -232  exim/exim-src/src/verify.c
  1.1       +28 -0     exim/exim-test-orig/AutoTest/confs/596 (new)
  1.1       +3 -0      exim/exim-test-orig/AutoTest/log/596 (new)
  1.1       +1 -0      exim/exim-test-orig/AutoTest/rejectlog/596 (new)
  1.1       +3 -0      exim/exim-test-orig/AutoTest/scripts/596 (new)
  1.2       +1 -0      exim/exim-test-orig/AutoTest/stderr/320
  1.1       +1 -0      exim/exim-test-orig/AutoTest/stdout/596 (new)


  Index: ChangeLog
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
  retrieving revision 1.35
  retrieving revision 1.36
  diff -u -r1.35 -r1.36
  --- ChangeLog    19 Nov 2004 15:18:57 -0000    1.35
  +++ ChangeLog    22 Nov 2004 11:30:03 -0000    1.36
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.35 2004/11/19 15:18:57 ph10 Exp $
  +$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.36 2004/11/22 11:30:03 ph10 Exp $


Change log file for Exim from version 4.21
-------------------------------------------
@@ -159,6 +159,10 @@

       (3) It is now possible to specify the separator character for use when
           multiple records are returned.
  +
  +38. The dnslists ACL condition has been extended: it is now possible to supply
  +    a list of IP addresses and/or domains to be looked up in a particular DNS
  +    domain.



Exim version 4.43

  Index: NewStuff
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/NewStuff,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- NewStuff    19 Nov 2004 15:18:57 -0000    1.13
  +++ NewStuff    22 Nov 2004 11:30:03 -0000    1.14
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.13 2004/11/19 15:18:57 ph10 Exp $
  +$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.14 2004/11/22 11:30:03 ph10 Exp $


New Features in Exim
--------------------
@@ -165,6 +165,36 @@

       The same effect could be achieved by wrapping the lookup in ${tr...}; this
       feature is just a syntactic simplification.
  +
  +15. It is now possible to supply a list of domains and/or IP addresses to be
  +    lookup up in a DNS blacklist. Previously, only a single domain name could
  +    be given, for example:
  +
  +      dnslists = black.list.tld/$sender_host_name
  +
  +    What follows the slash can now be a list. As with all lists, the default
  +    separator is a colon. However, because this is a sublist within the list of
  +    DNS blacklist domains, it is necessary either to double the separators like
  +    this:
  +
  +      dnslists = black.list.tld/name.1::name.2
  +
  +    or to change the separator character, like this:
  +
  +      dnslists = black.list.tld/<;name.1;name.2
  +
  +    If an item in the list is an IP address, it is inverted before the DNS
  +    blacklist domain is appended. If it is not an IP address, no inversion
  +    occurs. Consider this condition:
  +
  +       dnslists = black.list.tls/<;192.168.1.2;a.domain
  +
  +    The DNS lookups that occur are for
  +
  +       2.1.168.192.black.list.tld  and  a.domain.black.list.tld
  +
  +    Once a DNS record has been found (that matches a specific IP return
  +    address, if specified), no further lookups are done.



Version 4.43

  Index: verify.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/verify.c,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- verify.c    18 Nov 2004 11:17:33 -0000    1.6
  +++ verify.c    22 Nov 2004 11:30:04 -0000    1.7
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/verify.c,v 1.6 2004/11/18 11:17:33 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/verify.c,v 1.7 2004/11/22 11:30:04 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -2184,6 +2184,254 @@



   /*************************************************
  +*          Perform a single dnsbl lookup         *
  +*************************************************/
  +
  +/* This function is called from verify_check_dnsbl() below.
  +
  +Arguments:
  +  domain         the outer dnsbl domain (for debug message)
  +  keydomain      the current keydomain (for debug message) 
  +  query          the domain to be looked up
  +  iplist         the list of matching IP addresses 
  +  bitmask        true if bitmask matching is wanted 
  +  invert_result  true if result to be inverted 
  +  defer_return   what to return for a defer 
  +
  +Returns:         OK if lookup succeeded
  +                 FAIL if not
  +*/
  +
  +static int
  +one_check_dnsbl(uschar *domain, uschar *keydomain, uschar *query, 
  +  uschar *iplist, BOOL bitmask, BOOL invert_result, int defer_return)
  +{                
  +dns_answer dnsa;
  +dns_scan dnss;
  +tree_node *t;
  +dnsbl_cache_block *cb;
  +int old_pool = store_pool;
  +
  +/* Look for this query in the cache. */
  +
  +t = tree_search(dnsbl_cache, query);
  +
  +/* If not cached from a previous lookup, we must do a DNS lookup, and
  +cache the result in permanent memory. */
  +
  +if (t == NULL)
  +  {
  +  store_pool = POOL_PERM;
  +
  +  /* Set up a tree entry to cache the lookup */
  +
  +  t = store_get(sizeof(tree_node) + Ustrlen(query));
  +  Ustrcpy(t->name, query);
  +  t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block));
  +  (void)tree_insertnode(&dnsbl_cache, t);
  +
  +  /* Do the DNS loopup . */
  +
  +  HDEBUG(D_dnsbl) debug_printf("new DNS lookup for %s\n", query);
  +  cb->rc = dns_basic_lookup(&dnsa, query, T_A);
  +  cb->text_set = FALSE;
  +  cb->text = NULL;
  +  cb->rhs = NULL;
  +
  +  /* If the lookup succeeded, cache the RHS address. The code allows for
  +  more than one address - this was for complete generality and the possible
  +  use of A6 records. However, A6 records have been reduced to experimental
  +  status (August 2001) and may die out. So they may never get used at all,
  +  let alone in dnsbl records. However, leave the code here, just in case.
  +
  +  Quite apart from one A6 RR generating multiple addresses, there are DNS
  +  lists that return more than one A record, so we must handle multiple
  +  addresses generated in that way as well. */
  +
  +  if (cb->rc == DNS_SUCCEED)
  +    {
  +    dns_record *rr;
  +    dns_address **addrp = &(cb->rhs);
  +    for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
  +         rr != NULL;
  +         rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
  +      {
  +      if (rr->type == T_A)
  +        {
  +        dns_address *da = dns_address_from_rr(&dnsa, rr);
  +        if (da != NULL)
  +          {
  +          *addrp = da;
  +          while (da->next != NULL) da = da->next;
  +          addrp = &(da->next);
  +          }
  +        }
  +      }
  +
  +    /* If we didn't find any A records, change the return code. This can
  +    happen when there is a CNAME record but there are no A records for what
  +    it points to. */
  +
  +    if (cb->rhs == NULL) cb->rc = DNS_NODATA;
  +    }
  +
  +  store_pool = old_pool;
  +  }
  +
  +/* Previous lookup was cached */
  +
  +else
  +  {
  +  HDEBUG(D_dnsbl) debug_printf("using result of previous DNS lookup\n");
  +  cb = t->data.ptr;
  +  }
  +
  +/* We now have the result of the DNS lookup, either newly done, or cached
  +from a previous call. If the lookup succeeded, check against the address
  +list if there is one. This may be a positive equality list (introduced by
  +"="), a negative equality list (introduced by "!="), a positive bitmask
  +list (introduced by "&"), or a negative bitmask list (introduced by "!&").*/
  +
  +if (cb->rc == DNS_SUCCEED)
  +  {
  +  dns_address *da = NULL;
  +  uschar *addlist = cb->rhs->address;
  +
  +  /* For A and AAAA records, there may be multiple addresses from multiple
  +  records. For A6 records (currently not expected to be used) there may be
  +  multiple addresses from a single record. */
  +
  +  for (da = cb->rhs->next; da != NULL; da = da->next)
  +    addlist = string_sprintf("%s, %s", addlist, da->address);
  +
  +  HDEBUG(D_dnsbl) debug_printf("DNS lookup for %s succeeded (yielding %s)\n",
  +    query, addlist);
  +
  +  /* Address list check; this can be either for equality, or via a bitmask.
  +  In the latter case, all the bits must match. */
  +
  +  if (iplist != NULL)
  +    {
  +    int ipsep = ',';
  +    uschar ip[46];
  +    uschar *ptr = iplist;
  +
  +    while (string_nextinlist(&ptr, &ipsep, ip, sizeof(ip)) != NULL)
  +      {
  +      /* Handle exact matching */
  +      if (!bitmask)
  +        {
  +        for (da = cb->rhs; da != NULL; da = da->next)
  +          {
  +          if (Ustrcmp(CS da->address, ip) == 0) break;
  +          }
  +        }
  +      /* Handle bitmask matching */
  +      else
  +        {
  +        int address[4];
  +        int mask = 0;
  +
  +        /* At present, all known DNS blocking lists use A records, with
  +        IPv4 addresses on the RHS encoding the information they return. I
  +        wonder if this will linger on as the last vestige of IPv4 when IPv6
  +        is ubiquitous? Anyway, for now we use paranoia code to completely
  +        ignore IPv6 addresses. The default mask is 0, which always matches.
  +        We change this only for IPv4 addresses in the list. */
  +
  +        if (host_aton(ip, address) == 1) mask = address[0];
  +
  +        /* Scan the returned addresses, skipping any that are IPv6 */
  +
  +        for (da = cb->rhs; da != NULL; da = da->next)
  +          {
  +          if (host_aton(da->address, address) != 1) continue;
  +          if ((address[0] & mask) == mask) break;
  +          }
  +        }
  +
  +      /* Break out if a match has been found */
  +
  +      if (da != NULL) break;
  +      }
  +
  +    /* If either
  +
  +       (a) No IP address in a positive list matched, or
  +       (b) An IP address in a negative list did match
  +
  +    then behave as if the DNSBL lookup had not succeeded, i.e. the host is
  +    not on the list. */
  +
  +    if (invert_result != (da == NULL))
  +      {
  +      HDEBUG(D_dnsbl)
  +        {
  +        debug_printf("=> but we are not accepting this block class because\n");
  +        debug_printf("=> there was %s match for %c%s\n",
  +          invert_result? "an exclude":"no", bitmask? '&' : '=', iplist);
  +        }
  +      return FAIL; 
  +      }
  +    }
  +
  +  /* Either there was no IP list, or the record matched. Look up a TXT record
  +  if it hasn't previously been done. */
  +
  +  if (!cb->text_set)
  +    {
  +    cb->text_set = TRUE;
  +    if (dns_basic_lookup(&dnsa, query, T_TXT) == DNS_SUCCEED)
  +      {
  +      dns_record *rr;
  +      for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
  +           rr != NULL;
  +           rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
  +        if (rr->type == T_TXT) break;
  +      if (rr != NULL)
  +        {
  +        int len = (rr->data)[0];
  +        if (len > 511) len = 127;
  +        store_pool = POOL_PERM;
  +        cb->text = string_sprintf("%.*s", len, (const uschar *)(rr->data+1));
  +        store_pool = old_pool;
  +        }
  +      }
  +    }
  +
  +  dnslist_value = addlist;
  +  dnslist_text = cb->text;
  +  return OK;
  +  }
  +
  +/* There was a problem with the DNS lookup */
  +
  +if (cb->rc != DNS_NOMATCH && cb->rc != DNS_NODATA)
  +  {
  +  log_write(L_dnslist_defer, LOG_MAIN,
  +    "DNS list lookup defer (probably timeout) for %s: %s", query,
  +    (defer_return == OK)?   US"assumed in list" :
  +    (defer_return == FAIL)? US"assumed not in list" :
  +                            US"returned DEFER");
  +  return defer_return;
  +  }
  +
  +/* No entry was found in the DNS; continue for next domain */
  +
  +HDEBUG(D_dnsbl)
  +  {
  +  debug_printf("DNS lookup for %s failed\n", query);
  +  debug_printf("=> that means %s is not listed at %s\n",
  +     keydomain, domain);
  +  }
  +
  +return FAIL;
  +}
  +
  +
  +
  +
  +/*************************************************
   *        Check host against DNS black lists      *
   *************************************************/


@@ -2227,7 +2475,6 @@
{
int sep = 0;
int defer_return = FAIL;
-int old_pool = store_pool;
BOOL invert_result = FALSE;
uschar *list = *listptr;
uschar *domain;
@@ -2240,18 +2487,19 @@

revadd[0] = 0;

+/* In case this is the first time the DNS resolver is being used. */
+
+dns_init(FALSE, FALSE);
+
/* Loop through all the domains supplied, until something matches */

   while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
     {
  +  int rc;
     BOOL frc;
     BOOL bitmask = FALSE;
  -  dns_answer dnsa;
  -  dns_scan dnss;
     uschar *iplist;
     uschar *key;
  -  tree_node *t;
  -  dnsbl_cache_block *cb;


     HDEBUG(D_dnsbl) debug_printf("DNS list check: %s\n", domain);


  @@ -2310,251 +2558,80 @@
         }
       }


  -  /* Construct the query by adding the domain onto either the sending host
  -  address, or the given key string. */
  -
  +  /* If there is no key string, construct the query by adding the domain name 
  +  onto the inverted host address, and perform a single DNS lookup. */
  +  
     if (key == NULL)
       {
       if (sender_host_address == NULL) return FAIL;    /* can never match */
       if (revadd[0] == 0) invert_address(revadd, sender_host_address);
       frc = string_format(query, sizeof(query), "%s%s", revadd, domain);
  -    }
  -  else
  -    {
  -    frc = string_format(query, sizeof(query), "%s.%s", key, domain);
  -    }
  -
  -  if (!frc)
  -    {
  -    log_write(0, LOG_MAIN|LOG_PANIC, "dnslist query is too long "
  -      "(ignored): %s...", query);
  -    continue;
  -    }
  -
  -  /* Look for this query in the cache. */
  -
  -  t = tree_search(dnsbl_cache, query);
  -
  -  /* If not cached from a previous lookup, we must do a DNS lookup, and
  -  cache the result in permanent memory. */
  -
  -  if (t == NULL)
  -    {
  -    store_pool = POOL_PERM;
  -
  -    /* In case this is the first time the DNS resolver is being used. */
  -
  -    dns_init(FALSE, FALSE);
  -
  -    /* Set up a tree entry to cache the lookup */
  -
  -    t = store_get(sizeof(tree_node) + Ustrlen(query));
  -    Ustrcpy(t->name, query);
  -    t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block));
  -    (void)tree_insertnode(&dnsbl_cache, t);
  -
  -    /* Do the DNS loopup . */
  -
  -    HDEBUG(D_dnsbl) debug_printf("new DNS lookup for %s\n", query);
  -    cb->rc = dns_basic_lookup(&dnsa, query, T_A);
  -    cb->text_set = FALSE;
  -    cb->text = NULL;
  -    cb->rhs = NULL;
  -
  -    /* If the lookup succeeded, cache the RHS address. The code allows for
  -    more than one address - this was for complete generality and the possible
  -    use of A6 records. However, A6 records have been reduced to experimental
  -    status (August 2001) and may die out. So they may never get used at all,
  -    let alone in dnsbl records. However, leave the code here, just in case.
  -
  -    Quite apart from one A6 RR generating multiple addresses, there are DNS
  -    lists that return more than one A record, so we must handle multiple
  -    addresses generated in that way as well. */
  -
  -    if (cb->rc == DNS_SUCCEED)
  +    
  +    if (!frc)
         {
  -      dns_record *rr;
  -      dns_address **addrp = &(cb->rhs);
  -      for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
  -           rr != NULL;
  -           rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
  -        {
  -        if (rr->type == T_A)
  -          {
  -          dns_address *da = dns_address_from_rr(&dnsa, rr);
  -          if (da != NULL)
  -            {
  -            *addrp = da;
  -            while (da->next != NULL) da = da->next;
  -            addrp = &(da->next);
  -            }
  -          }
  -        }
  -
  -      /* If we didn't find any A records, change the return code. This can
  -      happen when there is a CNAME record but there are no A records for what
  -      it points to. */
  -
  -      if (cb->rhs == NULL) cb->rc = DNS_NODATA;
  +      log_write(0, LOG_MAIN|LOG_PANIC, "dnslist query is too long "
  +        "(ignored): %s...", query);
  +      continue;
  +      }
  +      
  +    rc = one_check_dnsbl(domain, sender_host_address, query, iplist, bitmask, 
  +      invert_result, defer_return);
  +       
  +    if (rc == OK)
  +      {
  +      dnslist_domain = string_copy(domain);
  +      HDEBUG(D_dnsbl) debug_printf("=> that means %s is listed at %s\n", 
  +        sender_host_address, domain);
         }
  -
  -    store_pool = old_pool;
  +       
  +    if (rc != FAIL) return rc;     /* OK or DEFER */
       }
  -
  -  /* Previous lookup was cached */
  -
  +    
  +  /* If there is a key string, it can be a list of domains or IP addresses to 
  +  be concatenated with the main domain. */
  + 
     else
       {
  -    HDEBUG(D_dnsbl) debug_printf("using result of previous DNS lookup\n");
  -    cb = t->data.ptr;
  -    }
  -
  -  /* We now have the result of the DNS lookup, either newly done, or cached
  -  from a previous call. If the lookup succeeded, check against the address
  -  list if there is one. This may be a positive equality list (introduced by
  -  "="), a negative equality list (introduced by "!="), a positive bitmask
  -  list (introduced by "&"), or a negative bitmask list (introduced by "!&").*/
  -
  -  if (cb->rc == DNS_SUCCEED)
  -    {
  -    dns_address *da = NULL;
  -    uschar *addlist = cb->rhs->address;
  -
  -    /* For A and AAAA records, there may be multiple addresses from multiple
  -    records. For A6 records (currently not expected to be used) there may be
  -    multiple addresses from a single record. */
  -
  -    for (da = cb->rhs->next; da != NULL; da = da->next)
  -      addlist = string_sprintf("%s, %s", addlist, da->address);
  -
  -    HDEBUG(D_dnsbl) debug_printf("DNS lookup for %s succeeded (yielding %s)\n",
  -      query, addlist);
  -
  -    /* Address list check; this can be either for equality, or via a bitmask.
  -    In the latter case, all the bits must match. */
  -
  -    if (iplist != NULL)
  -      {
  -      int ipsep = ',';
  -      uschar ip[46];
  -      uschar *ptr = iplist;
  -
  -      while (string_nextinlist(&ptr, &ipsep, ip, sizeof(ip)) != NULL)
  -        {
  -        /* Handle exact matching */
  -        if (!bitmask)
  -          {
  -          for (da = cb->rhs; da != NULL; da = da->next)
  -            {
  -            if (Ustrcmp(CS da->address, ip) == 0) break;
  -            }
  -          }
  -        /* Handle bitmask matching */
  -        else
  -          {
  -          int address[4];
  -          int mask = 0;
  -
  -          /* At present, all known DNS blocking lists use A records, with
  -          IPv4 addresses on the RHS encoding the information they return. I
  -          wonder if this will linger on as the last vestige of IPv4 when IPv6
  -          is ubiquitous? Anyway, for now we use paranoia code to completely
  -          ignore IPv6 addresses. The default mask is 0, which always matches.
  -          We change this only for IPv4 addresses in the list. */
  -
  -          if (host_aton(ip, address) == 1) mask = address[0];
  -
  -          /* Scan the returned addresses, skipping any that are IPv6 */
  -
  -          for (da = cb->rhs; da != NULL; da = da->next)
  -            {
  -            if (host_aton(da->address, address) != 1) continue;
  -            if ((address[0] & mask) == mask) break;
  -            }
  -          }
  -
  -        /* Break out if a match has been found */
  -
  -        if (da != NULL) break;
  +    int keysep = 0;
  +    uschar *keydomain; 
  +    uschar keybuffer[256];
  +  
  +    while ((keydomain = string_nextinlist(&key, &keysep, keybuffer, 
  +            sizeof(keybuffer))) != NULL)
  +      {       
  +      if (string_is_ip_address(keydomain, NULL))
  +        {
  +        uschar keyrevadd[128];
  +        invert_address(keyrevadd, keydomain);
  +        frc = string_format(query, sizeof(query), "%s%s", keyrevadd, domain); 
  +        }
  +      else
  +        { 
  +        frc = string_format(query, sizeof(query), "%s.%s", keydomain, domain);
           }


  -      /* If either
  -
  -         (a) No IP address in a positive list matched, or
  -         (b) An IP address in a negative list did match
  -
  -      then behave as if the DNSBL lookup had not succeeded, i.e. the host is
  -      not on the list. */
  -
  -      if (invert_result != (da == NULL))
  +      if (!frc)
           {
  -        HDEBUG(D_dnsbl)
  -          {
  -          debug_printf("=> but we are not accepting this block class because\n");
  -          debug_printf("=> there was %s match for %c%s\n",
  -            invert_result? "an exclude":"no", bitmask? '&' : '=', iplist);
  -          }
  -        continue;   /* With next DNSBL domain */
  +        log_write(0, LOG_MAIN|LOG_PANIC, "dnslist query is too long "
  +          "(ignored): %s...", query);
  +        continue;
           }
  -      }
  -
  -  /* Either there was no IP list, or the record matched. Look up a TXT record
  -    if it hasn't previously been done. */
  -
  -    if (!cb->text_set)
  -      {
  -      cb->text_set = TRUE;
  -      if (dns_basic_lookup(&dnsa, query, T_TXT) == DNS_SUCCEED)
  +        
  +      rc = one_check_dnsbl(domain, keydomain, query, iplist, bitmask, 
  +        invert_result, defer_return);
  +         
  +      if (rc == OK)
           {
  -        dns_record *rr;
  -        for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS);
  -             rr != NULL;
  -             rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT))
  -          if (rr->type == T_TXT) break;
  -        if (rr != NULL)
  -          {
  -          int len = (rr->data)[0];
  -          if (len > 511) len = 127;
  -          store_pool = POOL_PERM;
  -          cb->text = string_sprintf("%.*s", len, (const uschar *)(rr->data+1));
  -          store_pool = old_pool;
  -          }
  +        dnslist_domain = string_copy(domain);
  +        HDEBUG(D_dnsbl) debug_printf("=> that means %s is listed at %s\n", 
  +          keydomain, domain);
           }
  -      }
  +         
  +      if (rc != FAIL) return rc;   /* OK or DEFER */


  -    HDEBUG(D_dnsbl)
  -      {
  -      debug_printf("=> that means %s is listed at %s\n",
  -        (key == NULL)? sender_host_address : key, domain);
  -      }
  -
  -    dnslist_domain = string_copy(domain);
  -    dnslist_value = addlist;
  -    dnslist_text = cb->text;
  -    return OK;
  -    }
  -
  -  /* There was a problem with the DNS lookup */
  -
  -  if (cb->rc != DNS_NOMATCH && cb->rc != DNS_NODATA)
  -    {
  -    log_write(L_dnslist_defer, LOG_MAIN,
  -      "DNS list lookup defer (probably timeout) for %s: %s", query,
  -      (defer_return == OK)?   US"assumed in list" :
  -      (defer_return == FAIL)? US"assumed not in list" :
  -                              US"returned DEFER");
  -    return defer_return;
  -    }
  -
  -  /* No entry was found in the DNS; continue for next domain */
  -
  -  HDEBUG(D_dnsbl)
  -    {
  -    debug_printf("DNS lookup for %s failed\n", query);
  -    debug_printf("=> that means %s is not listed at %s\n",
  -      (key == NULL)? sender_host_address : key, domain);
  -    }
  -  }      /* Continue with next domain */
  +      }    /* continue with next keystring domain/address */
  +    }  
  +  }        /* continue with next dnsdb outer domain */


return FAIL;
}

Index: 596
====================================================================
# Exim test configuration 596

# Macros are set externally in order to get the path
# of the Exim that is being tested, and the directory
# in which the test data lives.

exim_path = EXIM_PATH
primary_hostname = myhost.test.ex
spool_directory = DIR/spool


# ----- Main settings -----

acl_smtp_connect = check_connect


# ----- ACL -----

begin acl

  check_connect:
     warn  dnslists = rbl.test.ex/<;1.2.3.4;10.11.12.13
           logwrite = rbl.test.ex/<;1.2.3.4;10.11.12.13 


     warn  dnslists = test.ex/a.b.c.d::ten-1
           logwrite = test.ex/a.b.c.d::ten-1


# End

Index: 596
====================================================================
1999-03-02 09:44:33 rbl.test.ex/<;1.2.3.4;10.11.12.13
1999-03-02 09:44:33 test.ex/a.b.c.d::ten-1
1999-03-02 09:44:33 U=ph10 rejected connection in "connect" ACL

Index: 596
====================================================================
1999-03-02 09:44:33 U=ph10 rejected connection in "connect" ACL

Index: 596
====================================================================
0 list of keys in dnslists
exim -bs
****

  Index: 320
  ===================================================================
  RCS file: /home/cvs/exim/exim-test-orig/AutoTest/stderr/320,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- 320    8 Oct 2004 14:50:08 -0000    1.1
  +++ 320    22 Nov 2004 11:30:04 -0000    1.2
  @@ -1269,6 +1269,7 @@
   >>> DNS list check: test.again.dns
   >>> using result of previous DNS lookup
   LOG: DNS list lookup defer (probably timeout) for 44.44.44.44.test.again.dns: assumed in list
  +>>> => that means 44.44.44.44 is listed at test.again.dns
   >>> warn: condition test succeeded
   >>> processing "warn"
   >>> check dnslists = +exclude_unknown : test.again.dns


Index: 596
====================================================================
550 Administrative prohibition