diff options
author | Todd Short <tshort@akamai.com> | 2021-09-08 16:23:04 -0400 |
---|---|---|
committer | Todd Short <todd.short@me.com> | 2022-03-10 10:42:43 -0500 |
commit | a3e53d56831adb60d6875297b3339a4251f735d2 (patch) | |
tree | c931c5b2cc9a63f80e4f3ae3a366b70064b897ae /include | |
parent | 97896f744d9ee4f2e821e3383caac8e8c5f226cf (diff) |
Add TFO support to socket BIO and s_client/s_server
Supports Linux, MacOS and FreeBSD
Disabled by default, enabled via `enabled-tfo`
Some tests
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8692)
Diffstat (limited to 'include')
-rw-r--r-- | include/internal/bio_tfo.h | 151 | ||||
-rw-r--r-- | include/openssl/bio.h.in | 9 | ||||
-rw-r--r-- | include/openssl/bioerr.h | 3 |
3 files changed, 162 insertions, 1 deletions
diff --git a/include/internal/bio_tfo.h b/include/internal/bio_tfo.h new file mode 100644 index 0000000000..729e5b833d --- /dev/null +++ b/include/internal/bio_tfo.h @@ -0,0 +1,151 @@ +/* + * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Contains definitions for simplifying the use of TCP Fast Open + * (RFC7413) in OpenSSL socket BIOs. + */ + +/* If a supported OS is added here, update test/bio_tfo_test.c */ +#if defined(TCP_FASTOPEN) && !defined(OPENSSL_NO_TFO) + +# if defined(OPENSSL_SYS_MACOSX) || defined(__FreeBSD__) +# include <sys/sysctl.h> +# endif + +/* + * OSSL_TFO_SYSCTL is used to determine if TFO is supported by + * this kernel, and if supported, if it is enabled. This is more of + * a problem on FreeBSD 10.3 ~ 11.4, where TCP_FASTOPEN was defined, + * but not enabled by default in the kernel, and only for the server. + * Linux does not have sysctlbyname(), and the closest equivalent + * is to go into the /proc filesystem, but I'm not sure it's + * worthwhile. + * + * On MacOS and Linux: + * These operating systems use a single parameter to control TFO. + * The OSSL_TFO_CLIENT_FLAG and OSSL_TFO_SERVER_FLAGS are used to + * determine if TFO is enabled for the client and server respectively. + * + * OSSL_TFO_CLIENT_FLAG = 1 = client TFO enabled + * OSSL_TFO_SERVER_FLAG = 2 = server TFO enabled + * + * Such that: + * 0 = TFO disabled + * 3 = server and client TFO enabled + * + * macOS 10.14 and later support TFO. + * Linux kernel 3.6 added support for client TFO. + * Linux kernel 3.7 added support for server TFO. + * Linux kernel 3.13 enabled TFO by default. + * Linux kernel 4.11 added the TCP_FASTOPEN_CONNECT option. + * + * On FreeBSD: + * FreeBSD 10.3 ~ 11.4 uses a single sysctl for server enable. + * FreeBSD 12.0 and later uses separate sysctls for server and + * client enable. + * + * Some options are purposely NOT defined per-platform + * + * OSSL_TFO_SYSCTL + * Defined as a sysctlbyname() option to to determine if + * TFO is enabled in the kernel (macOS, FreeBSD) + * + * OSSL_TFO_SERVER_SOCKOPT + * Defined to indicate the socket option used to enable + * TFO on a server socket (all) + * + * OSSL_TFO_SERVER_SOCKOPT_VALUE + * Value to be used with OSSL_TFO_SERVER_SOCKOPT + * + * OSSL_TFO_CONNECTX + * Use the connectx() function to make a client connection + * (macOS) + * + * OSSL_TFO_CLIENT_SOCKOPT + * Defined to indicate the socket option used to enable + * TFO on a client socket (FreeBSD, Linux 4.14 and later) + * + * OSSL_TFO_SENDTO + * Defined to indicate the sendto() message type to + * be used to initiate a TFO connection (FreeBSD, + * Linux pre-4.14) + * + * OSSL_TFO_DO_NOT_CONNECT + * Defined to skip calling conect() when creating a + * client socket (macOS, FreeBSD, Linux pre-4.14) + */ + +# if defined(OPENSSL_SYS_WINDOWS) +/* + * NO WINDOWS SUPPORT + * + * But this is is what would be used on the server: + * + * define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN + * define OSSL_TFO_SERVER_SOCKOPT_VALUE 1 + * + * Still have to figure out client support + */ +# undef TCP_FASTOPEN +# endif + +/* NO VMS SUPPORT */ +# if defined(OPENSSL_SYS_VMS) +# undef TCP_FASTOPEN +# endif + +# if defined(OPENSSL_SYS_MACOSX) +# define OSSL_TFO_SYSCTL "net.inet.tcp.fastopen" +# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN +# define OSSL_TFO_SERVER_SOCKOPT_VALUE 1 +# define OSSL_TFO_CONNECTX 1 +# define OSSL_TFO_DO_NOT_CONNECT 1 +# define OSSL_TFO_CLIENT_FLAG 1 +# define OSSL_TFO_SERVER_FLAG 2 +# endif + +# if defined(__FreeBSD__) +# if defined(TCP_FASTOPEN_PSK_LEN) +/* As of 12.0 these are the SYSCTLs */ +# define OSSL_TFO_SYSCTL_SERVER "net.inet.tcp.fastopen.server_enable" +# define OSSL_TFO_SYSCTL_CLIENT "net.inet.tcp.fastopen.client_enable" +# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN +# define OSSL_TFO_SERVER_SOCKOPT_VALUE MAX_LISTEN +# define OSSL_TFO_CLIENT_SOCKOPT TCP_FASTOPEN +# define OSSL_TFO_DO_NOT_CONNECT 1 +# define OSSL_TFO_SENDTO 0 +/* These are the same because the sysctl are client/server-specific */ +# define OSSL_TFO_CLIENT_FLAG 1 +# define OSSL_TFO_SERVER_FLAG 1 +# else +/* 10.3 through 11.4 SYSCTL - ONLY SERVER SUPPORT */ +# define OSSL_TFO_SYSCTL "net.inet.tcp.fastopen.enabled" +# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN +# define OSSL_TFO_SERVER_SOCKOPT_VALUE MAX_LISTEN +# define OSSL_TFO_SERVER_FLAG 1 +# endif +# endif + +# if defined(OPENSSL_SYS_LINUX) +/* OSSL_TFO_PROC not used, but of interest */ +# define OSSL_TFO_PROC "/proc/sys/net/ipv4/tcp_fastopen" +# define OSSL_TFO_SERVER_SOCKOPT TCP_FASTOPEN +# define OSSL_TFO_SERVER_SOCKOPT_VALUE MAX_LISTEN +# if defined(TCP_FASTOPEN_CONNECT) +# define OSSL_TFO_CLIENT_SOCKOPT TCP_FASTOPEN_CONNECT +# else +# define OSSL_TFO_SENDTO MSG_FASTOPEN +# define OSSL_TFO_DO_NOT_CONNECT 1 +# endif +# define OSSL_TFO_CLIENT_FLAG 1 +# define OSSL_TFO_SERVER_FLAG 2 +# endif + +#endif diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index 686dad3099..5f79c0c9f8 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -405,10 +405,13 @@ struct bio_dgram_sctp_prinfo { # define BIO_C_SET_CONNECT_MODE 155 +# define BIO_C_SET_TFO 156 /* like BIO_C_SET_NBIO */ + # define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg) # define BIO_get_app_data(s) BIO_get_ex_data(s,0) -# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) +# define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) +# define BIO_set_tfo(b,n) BIO_ctrl(b,BIO_C_SET_TFO,(n),NULL) # ifndef OPENSSL_NO_SOCK /* IP families we support, for BIO_s_connect() and BIO_s_accept() */ @@ -429,6 +432,7 @@ struct bio_dgram_sctp_prinfo { # define BIO_get_conn_port(b) ((const char *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1)) # define BIO_get_conn_address(b) ((const BIO_ADDR *)BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2)) # define BIO_get_conn_ip_family(b) BIO_ctrl(b,BIO_C_GET_CONNECT,3,NULL) +# define BIO_get_conn_mode(b) BIO_ctrl(b,BIO_C_GET_CONNECT,4,NULL) # define BIO_set_conn_mode(b,n) BIO_ctrl(b,BIO_C_SET_CONNECT_MODE,(n),NULL) /* BIO_s_accept() */ @@ -446,6 +450,7 @@ struct bio_dgram_sctp_prinfo { (char *)(bio)) # define BIO_set_accept_ip_family(b,f) BIO_int_ctrl(b,BIO_C_SET_ACCEPT,4,f) # define BIO_get_accept_ip_family(b) BIO_ctrl(b,BIO_C_GET_ACCEPT,4,NULL) +# define BIO_set_tfo_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,5,(n)?(void *)"a":NULL) /* Aliases kept for backward compatibility */ # define BIO_BIND_NORMAL 0 @@ -703,6 +708,7 @@ int BIO_hex_string(BIO *out, int indent, int width, const void *data, # ifndef OPENSSL_NO_SOCK BIO_ADDR *BIO_ADDR_new(void); +BIO_ADDR *BIO_ADDR_dup(const BIO_ADDR *ap); int BIO_ADDR_rawmake(BIO_ADDR *ap, int family, const void *where, size_t wherelen, unsigned short port); void BIO_ADDR_free(BIO_ADDR *); @@ -765,6 +771,7 @@ int BIO_sock_info(int sock, # define BIO_SOCK_KEEPALIVE 0x04 # define BIO_SOCK_NONBLOCK 0x08 # define BIO_SOCK_NODELAY 0x10 +# define BIO_SOCK_TFO 0x20 int BIO_socket(int domain, int socktype, int protocol, int options); int BIO_connect(int sock, const BIO_ADDR *addr, int options); diff --git a/include/openssl/bioerr.h b/include/openssl/bioerr.h index 787b30afce..99247340ca 100644 --- a/include/openssl/bioerr.h +++ b/include/openssl/bioerr.h @@ -45,6 +45,8 @@ # define BIO_R_NO_PORT_DEFINED 113 # define BIO_R_NO_SUCH_FILE 128 # define BIO_R_NULL_PARAMETER 115 /* unused */ +# define BIO_R_TFO_DISABLED 106 +# define BIO_R_TFO_NO_KERNEL_SUPPORT 108 # define BIO_R_TRANSFER_ERROR 104 # define BIO_R_TRANSFER_TIMEOUT 105 # define BIO_R_UNABLE_TO_BIND_SOCKET 117 @@ -53,6 +55,7 @@ # define BIO_R_UNABLE_TO_LISTEN_SOCKET 119 # define BIO_R_UNABLE_TO_NODELAY 138 # define BIO_R_UNABLE_TO_REUSEADDR 139 +# define BIO_R_UNABLE_TO_TFO 109 # define BIO_R_UNAVAILABLE_IP_FAMILY 145 # define BIO_R_UNINITIALIZED 120 # define BIO_R_UNKNOWN_INFO_TYPE 140 |