From 80963d1ed93049909ca33d0357547212fe1b465b Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Tue, 16 Nov 2010 21:01:36 +0300 Subject: [PATCH] common libs: Use gethostbyname2_r() instead of gethostbyname() if available. gethostbyname() is not thread-safe. It's recommended to use gethostbyname_r() or gethostbyname2_r() instead. (cherry picked from commit f27e9581cdb6837f83d0aab467f0e5f83e814e7b) --- public-trunk/CommonLibs/Sockets.cpp | 36 +++++++++++++++++++++++++---- public-trunk/configure.ac | 3 +++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/public-trunk/CommonLibs/Sockets.cpp b/public-trunk/CommonLibs/Sockets.cpp index e4951a1..0fe71e2 100644 --- a/public-trunk/CommonLibs/Sockets.cpp +++ b/public-trunk/CommonLibs/Sockets.cpp @@ -23,7 +23,7 @@ */ - +#include #include #include #include @@ -43,13 +43,39 @@ bool resolveAddress(struct sockaddr_in *address, const char *host, unsigned short port) { // FIXME -- Need to ignore leading/trailing spaces in hostname. - struct hostent *hp = gethostbyname(host); + struct hostent *hp; +#ifdef HAVE_GETHOSTBYNAME2_R + struct hostent hostData; + char tmpBuffer[2048]; + int h_errno; + + // 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)!=0) { + CERR("WARNING -- gethostbyname() failed for " << host << ", " << hstrerror(h_errno)); + return false; + } +#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); + sGethostbynameMutex.unlock(); +#endif if (hp==NULL) { CERR("WARNING -- gethostbyname() failed for " << host << ", " << hstrerror(h_errno)); return false; } - address->sin_family = AF_INET; - bcopy(hp->h_addr, &(address->sin_addr), hp->h_length); + 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; } @@ -58,7 +84,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/public-trunk/configure.ac b/public-trunk/configure.ac index f60e56e..3b85066 100644 --- a/public-trunk/configure.ac +++ b/public-trunk/configure.ac @@ -76,6 +76,9 @@ PKG_CHECK_MODULES(ORTP, ortp) # 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([\