time_t now;
dbdata_callout_cache *cache_record;
-cache_record = dbfn_read_with_length(dbm_file, key, &length);
-
-if (cache_record == NULL)
+if (!(cache_record = dbfn_read_with_length(dbm_file, key, &length)))
{
HDEBUG(D_verify) debug_printf("callout cache: no %s record found for %s\n", type, key);
return NULL;
/* Match! Send the RCPT TO, set done from the response */
done =
- smtp_write_command(&ctblock, FALSE, "RCPT TO:<%.1000s>\r\n",
+ smtp_write_command(&ctblock, SCMD_FLUSH, "RCPT TO:<%.1000s>\r\n",
transport_rcpt_address(addr,
addr->transport->rcpt_include_affixes)) >= 0 &&
cutthrough_response(cutthrough.fd, '2', &resp, CUTTHROUGH_DATA_TIMEOUT) == '2';
postmaster-verify.
The sync_responses() would need to be taught about it and we'd
need another return code filtering out to here.
+
+ Avoid using a SIZE option on the MAIL for all randon-rcpt checks.
*/
+ sx.avoid_option = OPTION_SIZE;
+
/* Remember when we last did a random test */
new_domain_record.random_stamp = time(NULL);
if (smtp_write_mail_and_rcpt_cmds(&sx, &yield) == 0)
switch(addr->transport_return)
{
- case PENDING_OK:
+ case PENDING_OK: /* random was accepted, unfortunately */
new_domain_record.random_result = ccache_accept;
- break;
- case FAIL:
+ yield = OK; /* Only usable verify result we can return */
+ done = TRUE;
+ goto no_conn;
+ case FAIL: /* rejected: the preferred result */
new_domain_record.random_result = ccache_reject;
+ sx.avoid_option = 0;
/* Between each check, issue RSET, because some servers accept only
one recipient after MAIL FROM:<>.
XXX We don't care about that for postmaster_full. Should we? */
if ((done =
- smtp_write_command(&sx.outblock, FALSE, "RSET\r\n") >= 0 &&
+ smtp_write_command(&sx.outblock, SCMD_FLUSH, "RSET\r\n") >= 0 &&
smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer),
'2', callout)))
break;
sx.send_rset = TRUE;
sx.completed_addr = FALSE;
goto tls_retry_connection;
+ case DEFER: /* 4xx response to random */
+ break; /* Just to be clear. ccache_unknown, !done. */
}
/* Re-setup for main verify, or for the error message when failing */
else
done = TRUE;
- /* Main verify. If the host is accepting all local parts, as determined
- by the "random" check, we don't need to waste time doing any further
- checking. */
+ /* Main verify. For rcpt-verify use SIZE if we know it and we're not cacheing;
+ for sndr-verify never use it. */
if (done)
{
+ if (!(options & vopt_is_recipient && options & vopt_callout_no_cache))
+ sx.avoid_option = OPTION_SIZE;
+
done = FALSE;
switch(smtp_write_mail_and_rcpt_cmds(&sx, &yield))
{
case PENDING_OK: done = TRUE;
new_address_record.result = ccache_accept;
break;
- case FAIL: done = TRUE;
+ case FAIL: done = TRUE;
yield = FAIL;
*failure_ptr = US"recipient";
new_address_record.result = ccache_reject;
break;
- default: break;
+ default: break;
}
break;
cancel_cutthrough_connection(TRUE, US"postmaster verify");
HDEBUG(D_acl|D_v) debug_printf_indent("Cutthrough cancelled by presence of postmaster verify\n");
- done = smtp_write_command(&sx.outblock, FALSE, "RSET\r\n") >= 0
+ done = smtp_write_command(&sx.outblock, SCMD_FLUSH, "RSET\r\n") >= 0
&& smtp_read_response(&sx.inblock, sx.buffer,
sizeof(sx.buffer), '2', callout);
sx.ok = FALSE;
sx.send_rset = TRUE;
sx.completed_addr = FALSE;
+ sx.avoid_option = OPTION_SIZE;
if( smtp_write_mail_and_rcpt_cmds(&sx, &yield) == 0
&& addr->transport_return == PENDING_OK
done = TRUE;
else
done = (options & vopt_callout_fullpm) != 0
- && smtp_write_command(&sx.outblock, FALSE,
+ && smtp_write_command(&sx.outblock, SCMD_FLUSH,
"RCPT TO:<postmaster>\r\n") >= 0
&& smtp_read_response(&sx.inblock, sx.buffer,
sizeof(sx.buffer), '2', callout);
if (*sx.buffer == 0) Ustrcpy(sx.buffer, US"connection dropped");
/*XXX test here is ugly; seem to have a split of responsibility for
- building this message. Need to reationalise. Where is it done
+ building this message. Need to rationalise. Where is it done
before here, and when not?
Not == 5xx resp to MAIL on main-verify
*/
cancel_cutthrough_connection(TRUE, US"not usable for cutthrough");
if (sx.send_quit)
{
- (void) smtp_write_command(&sx.outblock, FALSE, "QUIT\r\n");
+ (void) smtp_write_command(&sx.outblock, SCMD_FLUSH, "QUIT\r\n");
/* Wait a short time for response, and discard it */
smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer),
if(
#ifdef SUPPORT_TLS
- (tls_out.active == cutthrough.fd) ? tls_write(FALSE, ctblock.buffer, n) :
+ tls_out.active == cutthrough.fd ? tls_write(FALSE, ctblock.buffer, n, FALSE) :
#endif
send(cutthrough.fd, ctblock.buffer, n, 0) > 0
)
}
-/* fd and tctx args only to match write_chunk() */
+/* tctx arg only to match write_chunk() */
static BOOL
-cutthrough_write_chunk(int fd, transport_ctx * tctx, uschar * s, int len)
+cutthrough_write_chunk(transport_ctx * tctx, uschar * s, int len)
{
uschar * s2;
while(s && (s2 = Ustrchr(s, '\n')))
*/
HDEBUG(D_acl) debug_printf_indent("----------- start cutthrough headers send -----------\n");
+tctx.u.fd = cutthrough.fd;
tctx.tblock = cutthrough.addr.transport;
tctx.addr = &cutthrough.addr;
tctx.check_string = US".";
tctx.escape_string = US"..";
+/*XXX check under spool_files_wireformat. Might be irrelevant */
tctx.options = topt_use_crlf;
-if (!transport_headers_send(cutthrough.fd, &tctx, &cutthrough_write_chunk))
+if (!transport_headers_send(&tctx, &cutthrough_write_chunk))
return FALSE;
HDEBUG(D_acl) debug_printf_indent("----------- done cutthrough headers send ------------\n");
void
release_cutthrough_connection(const uschar * why)
{
+if (cutthrough.fd < 0) return;
HDEBUG(D_acl) debug_printf_indent("release cutthrough conn: %s\n", why);
cutthrough.fd = -1;
cutthrough.delivery = cutthrough.callout_hold_only = FALSE;
va_start(ap, format);
if (smtp_out && (f == smtp_out))
- smtp_vprintf(format, ap);
+ smtp_vprintf(format, FALSE, ap);
else
vfprintf(f, format, ap);
va_end(ap);
transport. */
transport_feedback tf = {
- NULL, /* interface (=> any) */
- US"smtp", /* port */
- US"smtp", /* protocol */
- NULL, /* hosts */
- US"$smtp_active_hostname", /* helo_data */
- FALSE, /* hosts_override */
- FALSE, /* hosts_randomize */
- FALSE, /* gethostbyname */
- TRUE, /* qualify_single */
- FALSE /* search_parents */
+ .interface = NULL, /* interface (=> any) */
+ .port = US"smtp",
+ .protocol = US"smtp",
+ .hosts = NULL,
+ .helo_data = US"$smtp_active_hostname",
+ .hosts_override = FALSE,
+ .hosts_randomize = FALSE,
+ .gethostbyname = FALSE,
+ .qualify_single = TRUE,
+ .search_parents = FALSE
};
/* If verification yielded a remote transport, we want to use that
goto END_OFF;
}
+/*XXX could take advantage of TFO early-data. Hmm, what are the
+error returns; can we differentiate connect from data fails?
+Do we need to? */
if (ip_connect(sock, host_af, sender_host_address, port,
- rfc1413_query_timeout, TRUE) < 0)
+ rfc1413_query_timeout, &tcp_fastopen_nodata) < 0)
{
if (errno == ETIMEDOUT && LOGGING(ident_timeout))
log_write(0, LOG_MAIN, "ident connection to %s timed out",
int rc;
unsigned int *local_cache_bits = cache_bits;
const uschar *save_host_address = deliver_host_address;
-check_host_block cb;
-cb.host_name = host_name;
-cb.host_address = host_address;
+check_host_block cb = { .host_name = host_name, .host_address = host_address };
-if (valueptr != NULL) *valueptr = NULL;
+if (valueptr) *valueptr = NULL;
/* If the host address starts off ::ffff: it is an IPv6 address in
IPv4-compatible mode. Find the IPv4 part for checking against IPv4
addresses. */
-cb.host_ipv4 = (Ustrncmp(host_address, "::ffff:", 7) == 0)?
- host_address + 7 : host_address;
+cb.host_ipv4 = Ustrncmp(host_address, "::ffff:", 7) == 0
+ ? host_address + 7 : host_address;
/* 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,