X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/0ab63f3dea522591218c0d65c78a686b7fa64db6..6372d4c990f39ba6ad84a91af0a3a61a63bd50a3:/src/src/smtp_out.c diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c index 9221aa868..c968f70e2 100644 --- a/src/src/smtp_out.c +++ b/src/src/smtp_out.c @@ -2,7 +2,7 @@ * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2016 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* A number of functions for driving outgoing SMTP calls. */ @@ -150,14 +150,44 @@ socklen_t len = sizeof(tinfo); if (getsockopt(sock, IPPROTO_TCP, TCP_INFO, &tinfo, &len) == 0) { - /* This is a somewhat dubious detection method; totally undocumented so likely - to fail in future kernels. There seems to be no documented way. */ - - if (tinfo.tcpi_unacked > 1) + switch (tcp_out_fastopen) { - DEBUG(D_transport|D_v) debug_printf("TCP_FASTOPEN mode connection\n"); - tcp_out_fastopen = TRUE; + /* This is a somewhat dubious detection method; totally undocumented so likely + to fail in future kernels. There seems to be no documented way. What we really + want to know is if the server sent smtp-banner data before our ACK of his SYN,ACK + hit him. What this (possibly?) detects is whether we sent a TFO cookie with our + SYN, as distinct from a TFO request. This gets a false-positive when the server + key is rotated; we send the old one (which this test sees) but the server returns + the new one and does not send its SMTP banner before we ACK his SYN,ACK. + To force that rotation case: + '# echo -n "00000000-00000000-00000000-0000000" >/proc/sys/net/ipv4/tcp_fastopen_key' + The kernel seems to be counting unack'd packets. */ + + case 1: + if (tinfo.tcpi_unacked > 1) + { + DEBUG(D_transport|D_v) + debug_printf("TCP_FASTOPEN tcpi_unacked %d\n", tinfo.tcpi_unacked); + tcp_out_fastopen = 2; + } + break; + +#ifdef notdef /* This seems to always fire, meaning that we cannot tell + whether the server accepted data we sent. For now assume + that it did. */ + + /* If there was data-on-SYN but we had to retrasnmit it, declare no TFO */ + + case 2: + if (!(tinfo.tcpi_options & TCPI_OPT_SYN_DATA)) + { + DEBUG(D_transport|D_v) debug_printf("TFO: had to retransmit\n"); + tcp_out_fastopen = 0; + } + break; +#endif } + } # endif } @@ -182,6 +212,8 @@ int dscp_level; int dscp_option; int sock; int save_errno = 0; +const blob * fastopen_blob = NULL; + #ifndef DISABLE_EVENT deliver_host_address = host->address; @@ -231,16 +263,14 @@ requested some early-data then include that in the TFO request. */ else { - const blob * fastopen = NULL; - #ifdef TCP_FASTOPEN if (verify_check_given_host(&ob->hosts_try_fastopen, host) == OK) - fastopen = early_data ? early_data : &tcp_fastopen_nodata; + fastopen_blob = early_data ? early_data : &tcp_fastopen_nodata; #endif - if (ip_connect(sock, host_af, host->address, port, timeout, fastopen) < 0) + if (ip_connect(sock, host_af, host->address, port, timeout, fastopen_blob) < 0) save_errno = errno; - else if (early_data && !fastopen && early_data->data && early_data->len) + else if (early_data && !fastopen_blob && early_data->data && early_data->len) if (send(sock, early_data->data, early_data->len, 0) < 0) save_errno = errno; } @@ -279,7 +309,7 @@ else } if (ob->keepalive) ip_keepalive(sock, host->address, TRUE); #ifdef TCP_FASTOPEN - tfo_out_check(sock); + if (fastopen_blob) tfo_out_check(sock); #endif return sock; }