+#ifdef TCP_FASTOPEN
+static void
+tfo_out_check(int sock)
+{
+# if defined(TCP_INFO) && defined(EXIM_HAVE_TCPI_UNACKED)
+struct tcp_info tinfo;
+socklen_t len = sizeof(tinfo);
+
+if (getsockopt(sock, IPPROTO_TCP, TCP_INFO, &tinfo, &len) == 0)
+ switch (tcp_out_fastopen)
+ {
+ /* 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 TFO_ATTEMPTED:
+ if (tinfo.tcpi_unacked > 1)
+ {
+ DEBUG(D_transport|D_v)
+ debug_printf("TCP_FASTOPEN tcpi_unacked %d\n", tinfo.tcpi_unacked);
+ tcp_out_fastopen = TFO_USED;
+ }
+ 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 TFO_USED:
+ if (!(tinfo.tcpi_options & TCPI_OPT_SYN_DATA))
+ {
+ DEBUG(D_transport|D_v) debug_printf("TFO: had to retransmit\n");
+ tcp_out_fastopen = TFO_NOT_USED;
+ }
+ break;
+
+ default: break; /* compiler quietening */
+# endif
+ }
+# endif
+}
+#endif
+
+
+/* Arguments as for smtp_connect(), plus
+ early_data if non-NULL, idenmpotent data to be sent -
+ preferably in the TCP SYN segment
+
+Returns: connected socket number, or -1 with errno set
+*/
+