-/* $Cambridge: exim/src/src/verify.c,v 1.2 2004/11/04 12:19:48 ph10 Exp $ */
+/* $Cambridge: exim/src/src/verify.c,v 1.6 2004/11/18 11:17:33 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
uschar *address_key;
uschar *from_address;
uschar *random_local_part = NULL;
+uschar **failure_ptr = is_recipient?
+ &recipient_verify_failure : &sender_verify_failure;
open_db dbblock;
open_db *dbm_file = NULL;
dbdata_callout_cache new_domain_record;
setflag(addr, af_verify_nsfail);
addr->user_message = US"(result of an earlier callout reused).";
yield = FAIL;
+ *failure_ptr = US"mail";
goto END_CALLOUT;
}
debug_printf("callout cache: domain does not accept "
"RCPT TO:<postmaster@domain>\n");
yield = FAIL;
+ *failure_ptr = US"postmaster";
setflag(addr, af_verify_pmfail);
addr->user_message = US"(result of earlier verification reused).";
goto END_CALLOUT;
HDEBUG(D_verify)
debug_printf("callout cache: address record is negative\n");
addr->user_message = US"Previous (cached) callout verification failure";
+ *failure_ptr = US"recipient";
yield = FAIL;
}
goto END_CALLOUT;
if (!done)
{
+ *failure_ptr = US"mail";
if (errno == 0 && responsebuffer[0] == '5')
{
setflag(addr, af_verify_nsfail);
if (done)
new_address_record.result = ccache_accept;
else if (errno == 0 && responsebuffer[0] == '5')
+ {
+ *failure_ptr = US"recipient";
new_address_record.result = ccache_reject;
+ }
/* Do postmaster check if requested */
new_domain_record.postmaster_result = ccache_accept;
else if (errno == 0 && responsebuffer[0] == '5')
{
+ *failure_ptr = US"postmaster";
setflag(addr, af_verify_pmfail);
new_domain_record.postmaster_result = ccache_reject;
}
BOOL full_info = (f == NULL)? FALSE : (debug_selector != 0);
BOOL is_recipient = (options & vopt_is_recipient) != 0;
BOOL expn = (options & vopt_expn) != 0;
-
int i;
int yield = OK;
int verify_type = expn? v_expn :
address_item *addr_remote = NULL;
address_item *addr_local = NULL;
address_item *addr_succeed = NULL;
+uschar **failure_ptr = is_recipient?
+ &recipient_verify_failure : &sender_verify_failure;
uschar *ko_prefix, *cr;
uschar *address = vaddr->address;
uschar *save_sender;
uschar null_sender[] = { 0 }; /* Ensure writeable memory */
+/* Clear, just in case */
+
+*failure_ptr = NULL;
+
/* Set up a prefix and suffix for error message which allow us to use the same
output statements both in EXPN mode (where an SMTP response is needed) and when
debugging with an output file. */
if (f != NULL)
fprintf(f, "%sA domain is required for \"%s\"%s\n", ko_prefix, address,
cr);
+ *failure_ptr = US"qualify";
return FAIL;
}
address = rewrite_address_qualify(address, is_recipient);
else
{
uschar *canonical_name;
- host_item *host;
+ host_item *host, *nexthost;
host_build_hostlist(&host_list, s, tf.hosts_randomize);
/* Just ignore failures to find a host address. If we don't manage
- to find any addresses, the callout will defer. */
+ to find any addresses, the callout will defer. Note that more than
+ one address may be found for a single host, which will result in
+ additional host items being inserted into the chain. Hence we must
+ save the next host first. */
- for (host = host_list; host != NULL; host = host->next)
+ for (host = host_list; host != NULL; host = nexthost)
{
+ nexthost = host->next;
if (tf.gethostbyname || string_is_ip_address(host->name, NULL))
(void)host_find_byname(host, NULL, &canonical_name, TRUE);
else
}
}
- /* Can only do a callout if we have at least one host! */
+ /* Can only do a callout if we have at least one host! If the callout
+ fails, it will have set ${sender,recipient}_verify_failure. */
if (host_list != NULL)
{
}
}
}
+
+ /* Otherwise, any failure is a routing failure */
+
+ else *failure_ptr = US"route";
/* A router may return REROUTED if it has set up a child address as a result
of a change of domain name (typically from widening). In this case we always
}
}
-return yield; /* Will be DEFER or FAIL if any one address has */
+/* Will be DEFER or FAIL if any one address has, only for full_info (which is
+the -bv or -bt case). */
+
+return yield;
}
/* Adjust parameters for the type of lookup. For a query-style
lookup, there is no file name, and the "key" is just the query. For
a single-key lookup, the key is the current IP address, masked
- appropriately, and reconverted to text form, with the mask appended. */
+ appropriately, and reconverted to text form, with the mask appended.
+ For IPv6 addresses, specify dot separators instead of colons. */
if (mac_islookup(search_type, lookup_querystyle))
{
{
insize = host_aton(cb->host_address, incoming);
host_mask(insize, incoming, mlen);
- (void)host_nmtoa(insize, incoming, mlen, buffer);
+ (void)host_nmtoa(insize, incoming, mlen, buffer, '.');
key = buffer;
filename = semicolon + 1;
}
verify_check_this_host(uschar **listptr, unsigned int *cache_bits,
uschar *host_name, uschar *host_address, uschar **valueptr)
{
+int rc;
unsigned int *local_cache_bits = cache_bits;
+uschar *save_host_address = deliver_host_address;
check_host_block cb;
cb.host_name = host_name;
cb.host_address = host_address;
cb.host_ipv4 = (Ustrncmp(host_address, "::ffff:", 7) == 0)?
host_address + 7 : host_address;
-return match_check_list(listptr, 0, &hostlist_anchor, &local_cache_bits,
- check_host, &cb, MCL_HOST,
- (host_address == sender_host_address)? US"host" : host_address, valueptr);
+/* During the running of the check, put the IP address into $host_address. In
+the case of calls from the smtp transport, it will already be there. However,
+in other calls (e.g. when testing ignore_target_hosts), it won't. Just to be on
+the safe side, any existing setting is preserved, though as I write this
+(November 2004) I can't see any cases where it is actually needed. */
+
+deliver_host_address = host_address;
+rc = match_check_list(
+ listptr, /* the list */
+ 0, /* separator character */
+ &hostlist_anchor, /* anchor pointer */
+ &local_cache_bits, /* cache pointer */
+ check_host, /* function for testing */
+ &cb, /* argument for function */
+ MCL_HOST, /* type of check */
+ (host_address == sender_host_address)?
+ US"host" : host_address, /* text for debugging */
+ valueptr); /* where to pass back data */
+deliver_host_address = save_host_address;
+return rc;
}