From 9b5179627264e1c2494325bbc4b575a7836c0cf4 Mon Sep 17 00:00:00 2001 From: "kurtis.heimerl" Date: Mon, 17 Dec 2012 11:22:04 +0000 Subject: [PATCH] From b453f10d65dd1ff1df0dd3747adf63f4e1fd7d30 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Sun, 16 Dec 2012 17:44:10 +0400 Subject: [PATCH] Use gethostbyname2_r() instead of gethostbyname() if available. gethostbyname() is not thread-safe. It's recommended to use gethostbyname_r() or gethostbyname2_r() instead. --- CommonLibs/Sockets.cpp | 44 +++++++++++++++++++++++++++++++++----------- configure.ac | 4 ++++ 2 files changed, 37 insertions(+), 11 deletions(-) git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@4637 19bc5d8c-e614-43d4-8b26-e1612bc8e597 --- CommonLibs/Sockets.cpp | 45 +++++++++++++++++++++++++++++++----------- configure.ac | 4 ++++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/CommonLibs/Sockets.cpp b/CommonLibs/Sockets.cpp index 9f7c24c..dc110c8 100644 --- a/CommonLibs/Sockets.cpp +++ b/CommonLibs/Sockets.cpp @@ -25,6 +25,7 @@ +#include #include #include #include @@ -40,9 +41,6 @@ #include -//mutex for protecting non-thread safe gethostbyname -static Mutex sgGethostbynameLock; - bool resolveAddress(struct sockaddr_in *address, const char *hostAndPort) { assert(address); @@ -62,16 +60,41 @@ bool resolveAddress(struct sockaddr_in *address, const char *host, unsigned shor { assert(address); assert(host); - //gethostbyname not thread safe - ScopedLock lock(sgGethostbynameLock); // FIXME -- Need to ignore leading/trailing spaces in hostname. - struct hostent *hp = gethostbyname(host); - if (hp==NULL) { - CERR("WARNING -- gethostbyname() failed for " << host << ", " << hstrerror(h_errno)); + struct hostent *hp; + int h_errno_local; +#ifdef HAVE_GETHOSTBYNAME2_R + struct hostent hostData; + char tmpBuffer[2048]; + + // There are different flavors of gethostbyname_r(), but + // latest Linux use the following form: + if (gethostbyname2_r(host, AF_INET, &hostData, tmpBuffer, sizeof(tmpBuffer), &hp, &h_errno_local)!=0) { + CERR("WARNING -- gethostbyname2_r() failed for " << host << ", " << hstrerror(h_errno_local)); return false; } - address->sin_family = AF_INET; - bcopy(hp->h_addr, &(address->sin_addr), hp->h_length); +#else + static Mutex sGethostbynameMutex; + // gethostbyname() is NOT thread-safe, so we should use a mutex here. + // Ideally it should be a global mutex for all non thread-safe socket + // operations and it should protect access to variables such as + // global h_errno. + sGethostbynameMutex.lock(); + hp = gethostbyname(host); + h_errno_local = h_errno; + sGethostbynameMutex.unlock(); +#endif + if (hp==NULL) { + CERR("WARNING -- gethostbyname() failed for " << host << ", " << hstrerror(h_errno_local)); + return false; + } + if (hp->h_addrtype != AF_INET) { + CERR("WARNING -- gethostbyname() resolved " << host << " to something other then AF_INET"); + return false; + } + address->sin_family = hp->h_addrtype; + assert(sizeof(address->sin_addr) == hp->h_length); + memcpy(&(address->sin_addr), hp->h_addr_list[0], hp->h_length); address->sin_port = htons(port); return true; } @@ -80,7 +103,7 @@ bool resolveAddress(struct sockaddr_in *address, const char *host, unsigned shor DatagramSocket::DatagramSocket() { - bzero(mDestination,sizeof(mDestination)); + memset(mDestination, 0, sizeof(mDestination)); } diff --git a/configure.ac b/configure.ac index 696bfc5..b1f99b1 100644 --- a/configure.ac +++ b/configure.ac @@ -130,6 +130,10 @@ PKG_CHECK_MODULES(LIBUSB, libusb-1.0) # Prepends -lreadline to LIBS and defines HAVE_LIBREADLINE in config.h AC_CHECK_LIB(readline, readline) +# Check for glibc-specific network functions +AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, Define if libc implements gethostbyname_r)]) +AC_CHECK_FUNC(gethostbyname2_r, [AC_DEFINE(HAVE_GETHOSTBYNAME2_R, 1, Define if libc implements gethostbyname2_r)]) + dnl Output files AC_CONFIG_FILES([\ Makefile \