* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) The Exim Maintainers 2020 - 2022 */
+/* Copyright (c) The Exim Maintainers 2020 - 2024 */
/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* A number of functions for driving outgoing SMTP calls. */
smtp_boundsock(smtp_connect_args * sc)
{
transport_instance * tb = sc->tblock;
-smtp_transport_options_block * ob =
- (smtp_transport_options_block *)tb->options_block;
+smtp_transport_options_block * ob = tb->drinst.options_block;
const uschar * dscp = ob->dscp;
int sock, dscp_value, dscp_level, dscp_option;
/* Set DSCP value, if we can. For now, if we fail to set the value, we don't
bomb out, just log it and continue in default traffic class. */
+GET_OPTION("dscp");
if (dscp && dscp_lookup(dscp, sc->host_af, &dscp_level, &dscp_option, &dscp_value))
{
HDEBUG(D_transport|D_acl|D_v)
)
{
HDEBUG(D_transport|D_acl|D_v)
- debug_printf_indent("unable to bind outgoing SMTP call to %s: %s", sc->interface,
+ debug_printf_indent("unable to bind outgoing SMTP call to %s: %s\n", sc->interface,
strerror(errno));
close(sock);
return -1;
int
smtp_sock_connect(smtp_connect_args * sc, int timeout, const blob * early_data)
{
-smtp_transport_options_block * ob =
- (smtp_transport_options_block *)sc->tblock->options_block;
+smtp_transport_options_block * ob = sc->tblock->drinst.options_block;
int sock;
int save_errno = 0;
const blob * fastopen_blob = NULL;
{
#ifdef TCP_FASTOPEN
/* See if TCP Fast Open usable. Default is a traditional 3WHS connect */
+ expand_level++;
if (verify_check_given_host(CUSS &ob->hosts_try_fastopen, sc->host) == OK)
{
if (!early_data)
}
# endif
}
+ expand_level--;
#endif
if (ip_connect(sock, sc->host_af, sc->host->address, sc->host->port, timeout, fastopen_blob) < 0)
/* Both bind() and connect() succeeded, and any early-data */
- HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" connected\n");
+ HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("connected\n");
if (getsockname(sock, (struct sockaddr *)(&interface_sock), &size) == 0)
sending_ip_address = host_ntoa(-1, &interface_sock, NULL, &sending_port);
else
#ifdef SUPPORT_SOCKS
if (ob->socks_proxy) s = string_sprintf("%svia proxy ", s);
#endif
- debug_printf_indent("Connecting to %s %s%s... ", sc->host->name, callout_address, s);
+ debug_printf_indent("Connecting to %s %s%s...\n", sc->host->name, callout_address, s);
}
/* Create and connect the socket */
static BOOL
flush_buffer(smtp_outblock * outblock, int mode)
{
-int rc;
-int n = outblock->ptr - outblock->buffer;
+int n = outblock->ptr - outblock->buffer, rc;
BOOL more = mode == SCMD_MORE;
client_conn_ctx * cctx;
+const uschar * where;
HDEBUG(D_transport|D_acl) debug_printf_indent("cmd buf flush %d bytes%s\n", n,
more ? " (more expected)" : "");
}
#ifndef DISABLE_TLS
+where = US"tls_write";
if (cctx->tls_ctx) /*XXX have seen a null cctx here, rvfy sending QUIT, hence check above */
rc = tls_write(cctx->tls_ctx, outblock->buffer, n, more);
else
requirement: TFO with data can, in rare cases, replay the data to the
receiver. */
+ where = US"smtp_connect";
if ( (cctx->sock = smtp_connect(outblock->conn_args, &early_data))
< 0)
return FALSE;
}
else
{
+ where = US"send";
rc = send(cctx->sock, outblock->buffer, n,
#ifdef MSG_MORE
more ? MSG_MORE : 0
This is despite NODELAY being active.
https://bugzilla.redhat.com/show_bug.cgi?id=1803806 */
+ where = US"cork";
if (!more)
setsockopt(cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
#endif
if (rc <= 0)
{
- HDEBUG(D_transport|D_acl) debug_printf_indent("send failed: %s\n", strerror(errno));
+ HDEBUG(D_transport|D_acl) debug_printf_indent("%s (fd %d) failed: %s\n",
+ where, cctx->sock, strerror(errno));
return FALSE;
}
-/* This might be called both due to callout and then from delivery.
-Use memory that will not be released between those phases.
-*/
-static void
-smtp_debug_resp(const uschar * buf)
-{
-#ifndef DISABLE_CLIENT_CMD_LOG
-int old_pool = store_pool;
-store_pool = POOL_PERM;
-client_cmd_log = string_append_listele_n(client_cmd_log, ':', buf,
- buf[3] == ' ' ? 3 : 4);
-store_pool = old_pool;
-#endif
-}
-
-
/*************************************************
* Write SMTP command *
*************************************************/
sx SMTP connection, contains buffer for pipelining, and socket
mode buffer, write-with-more-likely, write
format a format, starting with one of
- of HELO, MAIL FROM, RCPT TO, DATA, ".", or QUIT.
+ of HELO, MAIL FROM, RCPT TO, DATA, BDAT, ".", or QUIT.
If NULL, flush pipeline buffer only.
... data for the format
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
"SMTP");
va_end(ap);
- string_from_gstring(&gs);
if (gs.ptr > outblock->buffersize)
log_write(0, LOG_MAIN|LOG_PANIC_DIE, "overlong write_command in outgoing "
if (outblock->authenticating)
{
- uschar *p = big_buffer;
+ uschar * p = big_buffer;
if (Ustrncmp(big_buffer, "AUTH ", 5) == 0)
{
p += 5;
- while (isspace(*p)) p++;
- while (!isspace(*p)) p++;
- while (isspace(*p)) p++;
+ Uskip_whitespace(&p);
+ Uskip_nonwhite(&p);
+ Uskip_whitespace(&p);
}
while (*p) *p++ = '*';
}