*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* Copyright (c) The Exim Maintainers 2020 */
/* See the file NOTICE for conditions of use and distribution. */
/* A number of functions for driving outgoing SMTP calls. */
Uskip_whitespace(&expint);
if (!*expint) return TRUE;
+/* we just tested to ensure no taint, so big_buffer is ok */
while ((iface = string_nextinlist(&expint, &sep, big_buffer,
big_buffer_size)))
{
{
# ifdef __FreeBSD__
struct tcp_info tinfo;
-int val;
-socklen_t len = sizeof(val);
+socklen_t len = sizeof(tinfo);
-/* The observability as of 12.1 is not useful as a client, only telling us that
-a TFO option was used on SYN. It could have been a TFO-R, or ignored by the
-server. */
+/* A getsockopt TCP_FASTOPEN unfortunately returns "was-used" for a TFO/R as
+well as a TFO/C. Use what we can of the Linux hack below; reliability issues ditto. */
+switch (tcp_out_fastopen)
+ {
+ case TFO_ATTEMPTED_NODATA:
+ if ( getsockopt(sock, IPPROTO_TCP, TCP_INFO, &tinfo, &len) == 0
+ && tinfo.tcpi_state == TCPS_SYN_SENT
+ && tinfo.__tcpi_unacked > 0
+ )
+ {
+ DEBUG(D_transport|D_v)
+ debug_printf("TCP_FASTOPEN tcpi_unacked %d\n", tinfo.__tcpi_unacked);
+ tcp_out_fastopen = TFO_USED_NODATA;
+ }
+ break;
+ /*
+ case TFO_ATTEMPTED_DATA:
+ case TFO_ATTEMPTED_DATA:
+ if (tinfo.tcpi_options & TCPI_OPT_SYN_DATA) XXX no equvalent as of 12.2
+ */
+ }
-/*
-if (tcp_out_fastopen == TFO_ATTEMPTED_NODATA || tcp_out_fastopen == TFO_ATTEMPTED_DATA)
- if (getsockopt(sock, IPPROTO_TCP, TCP_FASTOPEN, &val, &len) == 0 && val != 0) {}
-*/
switch (tcp_out_fastopen)
{
- case TFO_ATTEMPTED_NODATA: tcp_out_fastopen = TFO_USED_NODATA; break;
case TFO_ATTEMPTED_DATA: tcp_out_fastopen = TFO_USED_DATA; break;
default: break; /* compiler quietening */
}
HDEBUG(D_transport|D_acl|D_v)
debug_printf("sending %ld nonTFO early-data\n", (long)early_data->len);
-#ifdef TCP_QUICKACK
- (void) setsockopt(sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
-#endif
if (send(sock, early_data->data, early_data->len, 0) < 0)
save_errno = errno;
}
+#ifdef TCP_QUICKACK
+ (void) setsockopt(sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
+#endif
}
/* Either bind() or connect() failed */
{
if (host->port != PORT_NONE)
{
- HDEBUG(D_transport|D_acl|D_v)
+ HDEBUG(D_transport|D_acl|D_v) if (port != host->port)
debug_printf_indent("Transport port=%d replaced by host-specific port=%d\n", port,
host->port);
port = host->port;
0
#endif
);
+
+#if defined(__linux__)
+ /* This is a workaround for a current linux kernel bug: as of
+ 5.6.8-200.fc31.x86_64 small (<MSS) writes get delayed by about 200ms,
+ This is despite NODELAY being active.
+ https://bugzilla.redhat.com/show_bug.cgi?id=1803806 */
+
+ if (!more)
+ setsockopt(outblock->cctx->sock, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
+#endif
}
}
while (!isspace(*p)) p++;
while (isspace(*p)) p++;
}
- while (*p != 0) *p++ = '*';
+ while (*p) *p++ = '*';
}
HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> %s\n", big_buffer);