summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorManikantan Subramanian <mani.on.gtalk@gmail.com>2018-09-17 18:54:13 -0700
committerRichard Levitte <levitte@openssl.org>2018-09-26 08:37:59 +0200
commit2b872562f56b6039179104657edddac22712d994 (patch)
tree92a8d76d18784278d7996151a876cd5fddabc5c1 /crypto
parent7a6d121e9d7bbd3a0db0a7b8020cfa224fe3aaa5 (diff)
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 <paul.dale@oracle.com> Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/7250)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/bio/b_sock.c23
1 files changed, 22 insertions, 1 deletions
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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
@@ -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;