From 2b872562f56b6039179104657edddac22712d994 Mon Sep 17 00:00:00 2001 From: Manikantan Subramanian Date: Mon, 17 Sep 2018 18:54:13 -0700 Subject: Use gethostbyname_r if available Fixes #7228 The function BIO_get_host_ip uses gethostbyname, which is not thread safe and hence we grab a lock. In multi-threaded applications, this lock sometimes causes performance bottlenecks. This patch uses the function gethostbyname_r (thread safe version), when available. Reviewed-by: Paul Dale Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/7250) --- crypto/bio/b_sock.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c index 5bad0a2bad..d32b76bc8f 100644 --- a/crypto/bio/b_sock.c +++ b/crypto/bio/b_sock.c @@ -56,6 +56,9 @@ * [including the GNU Public Licence.] */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + #include #include #include @@ -83,6 +86,11 @@ NETDB_DEFINE_CONTEXT static int wsa_init_done = 0; # endif +# if defined(__GLIBC__) +# define HAVE_GETHOSTBYNAME_R +# define GETHOSTNAME_R_BUF (2 * 1024) +# endif + /* * WSAAPI specifier is required to make indirect calls to run-time * linked WinSock 2 functions used in this module, to be specific @@ -116,7 +124,12 @@ int BIO_get_host_ip(const char *str, unsigned char *ip) int i; int err = 1; int locked = 0; - struct hostent *he; + struct hostent *he = NULL; +# ifdef HAVE_GETHOSTBYNAME_R + char buf[GETHOSTNAME_R_BUF]; + struct hostent hostent; + int h_errnop; +# endif i = get_ip(str, ip); if (i < 0) { @@ -138,10 +151,18 @@ int BIO_get_host_ip(const char *str, unsigned char *ip) if (i > 0) return (1); + /* if gethostbyname_r is supported, use it. */ +# ifdef HAVE_GETHOSTBYNAME_R + memset(&hostent, 0x00, sizeof(hostent)); + /* gethostbyname_r() sets |he| to NULL on error, we check it further down */ + gethostbyname_r(str, &hostent, buf, sizeof(buf), &he, &h_errnop); +# else /* do a gethostbyname */ CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); locked = 1; he = BIO_gethostbyname(str); +# endif + if (he == NULL) { BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_BAD_HOSTNAME_LOOKUP); goto err; -- cgit v1.2.3