2121 * limitations under the License.
2222 */
2323
24+ #include < openssl/opensslv.h>
25+
2426#include " P_Net.h"
2527#include " I_SocketManager.h"
2628#include " tscore/ink_assert.h"
29+ #include " tscore/ink_config.h"
2730
2831#include " BIO_fastopen.h"
2932
33+ #if defined(BORINGLIKE)
34+ #error
35+ #elif defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
36+ #define BORINGLIKE 1
37+ #else
38+ #define BORINGLIKE 0
39+ #endif
40+
41+ namespace
42+ {
43+ #if defined(HAVE_BIO_GET_EX_NEW_INDEX) && defined(HAVE_BIO_GET_EX_DATA) && defined(HAVE_BIO_SET_EX_DATA)
44+
45+ class ExData
46+ {
47+ public:
48+ // Pseudo-namespace
49+ ExData () = delete ;
50+
51+ static int
52+ idx ()
53+ {
54+ static int idx_ = []() -> int {
55+ int i = BIO_get_ex_new_index (0 , nullptr , _new, _dup, _free);
56+ ink_release_assert (i >= 0 );
57+ return i;
58+ }();
59+ return idx_;
60+ }
61+
62+ private:
63+ #if BORINGLIKE
64+ static constexpr CRYPTO_EX_unused *_new{nullptr };
65+ #else
66+ static void
67+ _new (void * /* parent */ , void * /* ptr */ , CRYPTO_EX_DATA *ad, int idx_, long /* argl */ , void * /* argp */ )
68+ {
69+ ink_release_assert (CRYPTO_set_ex_data (ad, idx_, nullptr ) == 1 );
70+ }
71+ #endif
72+
73+ #if BORINGLIKE
74+ static void
75+ _free (void * /* parent */ , void * /* ptr */ , CRYPTO_EX_DATA * /* ad */ , int /* idx_ */ , long /* argl */ , void * /* argp */ )
76+ {
77+ }
78+ #else
79+ static void
80+ _free (void * /* parent */ , void * /* ptr */ , CRYPTO_EX_DATA *ad, int idx_, long /* argl */ , void * /* argp */ )
81+ {
82+ ink_release_assert (CRYPTO_set_ex_data (ad, idx_, nullptr ) == 1 );
83+ }
84+ #endif
85+
86+ #if BORINGLIKE || (OPENSSL_VERSION_MAJOR >= 3)
87+ using _Type_from_d = void **;
88+ #else
89+ using _Type_from_d = void *;
90+ #endif
91+
92+ static int
93+ _dup (CRYPTO_EX_DATA * /* to */ , const CRYPTO_EX_DATA * /* from */ , _Type_from_d /* from_d */ , int /* idx */ , long /* argl */ ,
94+ void * /* argp */ )
95+ {
96+ ink_assert (false );
97+ return 0 ;
98+ }
99+ };
100+
101+ inline void
102+ set_dest_addr_for_bio (BIO *b, void *dest_addr)
103+ {
104+ ink_assert (BIO_set_ex_data (b, ExData::idx (), dest_addr) == 1 );
105+ }
106+
107+ inline void *
108+ get_dest_addr_for_bio (BIO *b)
109+ {
110+ return BIO_get_ex_data (b, ExData::idx ());
111+ }
112+
113+ #else // no BIO ex data in SSL library
114+
115+ // Fall back on the krufty way this was done using older SSL libraries.
116+
117+ inline void
118+ set_dest_addr_for_bio (BIO *b, void *dest_addr)
119+ {
120+ BIO_set_data (b, dest_addr);
121+ }
122+
123+ inline void *
124+ get_dest_addr_for_bio (BIO *b)
125+ {
126+ return BIO_get_data (b);
127+ }
128+
129+ #endif
130+
131+ } // end anonymous namespace
132+
30133// For BoringSSL, which for some reason doesn't have this function.
31134// (In BoringSSL, sock_read() and sock_write() use the internal
32135// bio_fd_non_fatal_error() instead.) #1437
@@ -113,13 +216,14 @@ fastopen_bwrite(BIO *bio, const char *in, int insz)
113216 int fd = BIO_get_fd (bio, nullptr );
114217 ink_assert (fd != NO_FD);
115218
116- if (BIO_get_data (bio)) {
219+ void *dst_void = get_dest_addr_for_bio (bio);
220+ if (dst_void) {
221+ auto dst = static_cast <sockaddr *>(dst_void);
117222 // On the first write only, make a TFO request if TFO is enabled.
118223 // The best documentation on the behavior of the Linux API is in
119224 // RFC 7413. If we get EINPROGRESS it means that the SYN has been
120225 // sent without data and we should retry.
121- const sockaddr *dst = reinterpret_cast <const sockaddr *>(BIO_get_data (bio));
122- ProxyMutex *mutex = this_ethread ()->mutex .get ();
226+ ProxyMutex *mutex = this_ethread ()->mutex .get ();
123227
124228 NET_INCREMENT_DYN_STAT (net_fastopen_attempts_stat);
125229
@@ -128,7 +232,7 @@ fastopen_bwrite(BIO *bio, const char *in, int insz)
128232 NET_INCREMENT_DYN_STAT (net_fastopen_successes_stat);
129233 }
130234
131- BIO_set_data (bio, nullptr );
235+ set_dest_addr_for_bio (bio, nullptr );
132236 } else {
133237 err = socketManager.write (fd, (void *)in, insz);
134238 }
@@ -166,21 +270,14 @@ fastopen_bread(BIO *bio, char *out, int outsz)
166270 return err < 0 ? -1 : err;
167271}
168272
273+ #ifndef HAVE_BIO_METH_NEW
274+
169275static long
170276fastopen_ctrl (BIO *bio, int cmd, long larg, void *ptr)
171277{
172- switch (cmd) {
173- case BIO_C_SET_CONNECT:
174- // We only support BIO_set_conn_address(), which sets a sockaddr.
175- ink_assert (larg == 2 );
176- BIO_set_data (bio, ptr);
177- return 0 ;
178- }
179-
180278 return BIO_meth_get_ctrl (const_cast <BIO_METHOD *>(BIO_s_socket ()))(bio, cmd, larg, ptr);
181279}
182280
183- #ifndef HAVE_BIO_METH_NEW
184281static const BIO_METHOD fastopen_methods[] = {{
185282 .type = BIO_TYPE_SOCKET,
186283 .name = " fastopen" ,
@@ -193,12 +290,12 @@ static const BIO_METHOD fastopen_methods[] = {{
193290 .destroy = fastopen_destroy,
194291 .callback_ctrl = nullptr ,
195292}};
196- #else
293+ #else // defined(HAVE_BIO_METH_NEW)
197294static const BIO_METHOD *fastopen_methods = [] {
198295 BIO_METHOD *methods = BIO_meth_new (BIO_TYPE_SOCKET, " fastopen" );
199296 BIO_meth_set_write (methods, fastopen_bwrite);
200297 BIO_meth_set_read (methods, fastopen_bread);
201- BIO_meth_set_ctrl (methods, fastopen_ctrl );
298+ BIO_meth_set_ctrl (methods, BIO_meth_get_ctrl ( const_cast <BIO_METHOD *>( BIO_s_socket ())) );
202299 BIO_meth_set_create (methods, fastopen_create);
203300 BIO_meth_set_destroy (methods, fastopen_destroy);
204301 return methods;
@@ -210,3 +307,9 @@ BIO_s_fastopen()
210307{
211308 return fastopen_methods;
212309}
310+
311+ void
312+ BIO_fastopen_set_dest_addr (BIO *bio, const sockaddr *dest_addr)
313+ {
314+ set_dest_addr_for_bio (bio, const_cast <sockaddr *>(dest_addr));
315+ }
0 commit comments