From 7438de712af16995fdbf1a0c094b3b32de737a7c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Fri, 15 Mar 2019 12:13:38 +0100 Subject: [PATCH] Issue #422: Update server & client TFO Seems to work for TLS now too. At least on Linux. Thanks Craig Andrews --- ChangeLog | 3 +++ configure.ac | 30 ++++++++++++++++++++++++++---- src/server.c | 8 +++++++- src/stub.c | 50 ++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4764e9f4..3054561f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ * 2019-??-??: Version 1.?.? + * Issue #422: Enable server side and update client side TCP Fast + Open implementation. Thanks Craig Andrews * Issue #423: Fix insecure delegation detection while scheduling. + Thanks Charles Milette * Issue #419: Escape backslashed when printing in JSON format. Thanks boB Rudis * DOA rr-type diff --git a/configure.ac b/configure.ac index 0412f538..ff837502 100644 --- a/configure.ac +++ b/configure.ac @@ -302,13 +302,31 @@ if test "x$enable_tcp_fastopen" = xno; then AC_MSG_WARN([TCP Fast Open is disabled]) else case `uname` in - Linux) AC_CHECK_DECL([MSG_FASTOPEN], [AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])], - [AC_MSG_WARN([TCP Fast Open is not available, continuing without])], [#include ]) - ;; Darwin) AC_CHECK_DECL([CONNECT_RESUME_ON_READ_WRITE], [AC_DEFINE_UNQUOTED([USE_OSX_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.])], [AC_MSG_WARN([TCP Fast Open is not available, continuing without])], [#include ]) ;; - *) AC_MSG_WARN([TCP Fast Open is not available, continuing without]) + *) + AC_CHECK_HEADERS([sys/socket.h netinet/tcp.h],,, [AC_INCLUDES_DEFAULT]) + AC_CHECK_DECL([TCP_FASTOPEN], [ + AC_DEFINE_UNQUOTED([USE_TCP_FASTOPEN], [1], [Define this to enable TCP fast open.]) + AC_CHECK_DECLS([TCP_FASTOPEN,MSG_FASTOPEN,TCP_FASTOPEN_CONNECT], [], [], [AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_NETINET_TCP_H +# include +#endif +]) + ], [ + AC_MSG_WARN([TCP Fast Open is not available, continuing without]) + ], [AC_INCLUDES_DEFAULT +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_NETINET_TCP_H +# include +#endif +]) ;; esac fi @@ -1731,6 +1749,10 @@ static inline int _gldns_custom_vsnprintf(char *str, size_t size, const char *fo #include #endif +#ifdef HAVE_NETINET_TCP_H +#include +#endif + #ifdef HAVE_SYS_SELECT_H #include #endif diff --git a/src/server.c b/src/server.c index 3736a6f2..5b1edd86 100644 --- a/src/server.c +++ b/src/server.c @@ -860,9 +860,15 @@ static getdns_return_t add_listeners(listen_set *set) break; if (setsockopt(l->fd, SOL_SOCKET, SO_REUSEADDR, - &enable, sizeof(int)) < 0) { + &enable, sizeof(enable)) < 0) { ; /* Ignore */ } +#ifdef HAVE_DECL_TCP_FASTOPEN + if (setsockopt(l->fd, IPPROTO_TCP, TCP_FASTOPEN, + &enable, sizeof(enable)) < 0) { + ; /* Ignore */ + } +#endif if (bind(l->fd, (struct sockaddr *)&l->addr, l->addr_len) == -1) /* IO error */ diff --git a/src/stub.c b/src/stub.c index c5a467fe..c71ce1ca 100644 --- a/src/stub.c +++ b/src/stub.c @@ -375,22 +375,23 @@ getdns_sock_nonblock(int sockfd) static int tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) { +#if defined(TCP_FASTOPEN) || defined(TCP_FASTOPEN_CONNECT) +# ifdef USE_WINSOCK + static const char enable = 1; +# else + static const int enable = 1; +# endif +#endif int fd = -1; + + DEBUG_STUB("%s %-35s: Creating TCP connection: %p\n", STUB_DEBUG_SETUP, __FUNC__, (void*)upstream); if ((fd = socket(upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) return -1; getdns_sock_nonblock(fd); - /* Note that error detection is different with TFO. Since the handshake - doesn't start till the sendto() lack of connection is often delayed until - then or even the subsequent event depending on the error and platform.*/ -#ifdef USE_TCP_FASTOPEN - /* Leave the connect to the later call to sendto() if using TCP*/ - if (transport == GETDNS_TRANSPORT_TCP) - return fd; -#elif USE_OSX_TCP_FASTOPEN - (void)transport; +#ifdef USE_OSX_TCP_FASTOPEN sa_endpoints_t endpoints; endpoints.sae_srcif = 0; endpoints.sae_srcaddr = NULL; @@ -405,9 +406,29 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) if (_getdns_socketerror() == _getdns_EINPROGRESS || _getdns_socketerror() == _getdns_EWOULDBLOCK) return fd; -#else + (void)transport; -#endif +#else /* USE_OSX_TCP_FASTOPEN */ + /* Note that error detection is different with TFO. Since the handshake + doesn't start till the sendto() lack of connection is often delayed until + then or even the subsequent event depending on the error and platform.*/ +# ifdef HAVE_DECL_TCP_FASTOPEN_CONNECT + (void)setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT + , (void *)&enable, sizeof(enable)); +# else /* HAVE_DECL_TCP_FASTOPEN_CONNECT */ +# ifdef HAVE_DECL_TCP_FASTOPEN + (void)setsockopt( fd, IPPROTO_TCP, TCP_FASTOPEN + , (void *)&enable, sizeof(enable)); +# endif/* HAVE_DECL_TCP_FASTOPEN*/ +# endif /* HAVE_DECL_TCP_FASTOPEN_CONNECT */ +# ifdef HAVE_DECL_MSG_FASTOPEN + /* Leave the connect to the later call to sendto() if using TCP*/ + if (transport == GETDNS_TRANSPORT_TCP) + return fd; +# else /* HAVE_DECL_MSG_FASTOPEN */ + (void)transport; +# endif /* HAVE_DECL_MSG_FASTOPEN */ +#endif /* USE_OSX_TCP_FASTOPEN */ if (connect(fd, (struct sockaddr *)&upstream->addr, upstream->addr_len) == -1) { if (_getdns_socketerror() == _getdns_EINPROGRESS || @@ -739,7 +760,12 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) /* We use sendto() here which will do both a connect and send */ #ifdef USE_TCP_FASTOPEN written = sendto(fd, netreq->query - 2, pkt_len + 2, - MSG_FASTOPEN, (struct sockaddr *)&(netreq->upstream->addr), +# ifdef HAVE_DECL_MSG_FASTOPEN + MSG_FASTOPEN, +# else + 0, +# endif + (struct sockaddr *)&(netreq->upstream->addr), netreq->upstream->addr_len); /* If pipelining we will find that the connection is already up so just fall back to a 'normal' write. */