Commit 75e552d5 authored by Alexander Nozdrin's avatar Alexander Nozdrin

Fix for Bug#52923 (Inadequate documentation of "Can't get hostname for your address" error).

The thing is that on some platforms (e.g. Mac OS X) sockaddr_in / sockaddr_in6
contain a non-standard field (sin_len / sin6_len), that must be set.

The problem was that only standard fields were set, thus getnameinfo() returned
EAI_SYSTEM instead of EAI_NONAME.

The fix is to introduce configure-time checks (for GNU auto-tools and CMake) for
those additional fields and to set them if they are available.
parent 534b3a52
......@@ -282,6 +282,8 @@
#cmakedefine HAVE_NETINET_IN6_H 1
#cmakedefine HAVE_IPV6 1
#cmakedefine ss_family @ss_family@
#cmakedefine HAVE_SOCKADDR_IN_SIN_LEN 1
#cmakedefine HAVE_SOCKADDR_IN6_SIN6_LEN 1
#cmakedefine HAVE_TIMESPEC_TS_SEC 1
#cmakedefine STRUCT_DIRENT_HAS_D_INO 1
#cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1
......
......@@ -1000,6 +1000,21 @@ IF(NOT HAVE_SOCKADDR_STORAGE_SS_FAMILY)
SET(ss_family __ss_family)
ENDIF()
ENDIF()
#
# Check if struct sockaddr_in::sin_len is available.
#
CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in" sin_len
"${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_SOCKADDR_IN_SIN_LEN)
#
# Check if struct sockaddr_in6::sin6_len is available.
#
CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in6" sin6_len
"${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_SOCKADDR_IN6_SIN6_LEN)
SET(CMAKE_EXTRA_INCLUDE_FILES)
CHECK_STRUCT_HAS_MEMBER("struct dirent" d_ino "dirent.h" STRUCT_DIRENT_HAS_D_INO)
......
......@@ -1012,6 +1012,66 @@ else
AC_MSG_RESULT([yes])
fi
#--------------------------------------------------------------------------
# Check if struct sockaddr_in::sin_len is available
#--------------------------------------------------------------------------
AC_CACHE_CHECK(
[if sockaddr_in::sin_len is available],
mysql_cv_have_sockaddr_in_sin_len,
AC_TRY_COMPILE(
[
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
],
[unsigned int i = sizeof(((struct sockaddr_in *) 0)->sin_len)],
mysql_cv_have_sockaddr_in_sin_len=yes,
mysql_cv_have_sockaddr_in_sin_len=no))
if test "$mysql_cv_have_sockaddr_in_sin_len" = "yes"; then
AC_DEFINE(
[HAVE_SOCKADDR_IN_SIN_LEN],
[1],
[If sockaddr_in::sin_len is available])
fi
#--------------------------------------------------------------------------
# Check if struct sockaddr_in6::sin6_len is available
#--------------------------------------------------------------------------
AC_CACHE_CHECK(
[if sockaddr_in6::sin6_len is available],
mysql_cv_have_sockaddr_in6_sin6_len,
AC_TRY_COMPILE(
[
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
],
[unsigned int i = sizeof(((struct sockaddr_in6 *) 0)->sin6_len)],
mysql_cv_have_sockaddr_in6_sin6_len=yes,
mysql_cv_have_sockaddr_in6_sin6_len=no))
if test "$mysql_cv_have_sockaddr_in_sin6_len" = "yes"; then
AC_DEFINE(
[HAVE_SOCKADDR_IN6_SIN6_LEN],
[1],
[If sockaddr_in6::sin6_len is available])
fi
#--------------------------------------------------------------------
# Check for TCP wrapper support
#--------------------------------------------------------------------
......@@ -3121,6 +3181,7 @@ esac
AC_SUBST([RDTSC_SPARC_ASSEMBLY])
#--------------------------------------------------------------------
# Output results
#--------------------------------------------------------------------
......
......@@ -1057,9 +1057,11 @@ ssize_t vio_pending(Vio *vio)
/**
This is a wrapper for the system getnameinfo(), because different OS
differ in the getnameinfo() implementation. For instance, Solaris 10
requires that the 2nd argument (salen) must match the actual size of the
struct sockaddr_storage passed to it.
differ in the getnameinfo() implementation:
- Solaris 10 requires that the 2nd argument (salen) must match the
actual size of the struct sockaddr_storage passed to it;
- Mac OS X has sockaddr_in::sin_len and sockaddr_in6::sin6_len and
requires them to be filled.
*/
int vio_getnameinfo(const struct sockaddr *sa,
......@@ -1072,11 +1074,17 @@ int vio_getnameinfo(const struct sockaddr *sa,
switch (sa->sa_family) {
case AF_INET:
sa_length= sizeof (struct sockaddr_in);
#ifdef HAVE_SOCKADDR_IN_SIN_LEN
((struct sockaddr_in *) sa)->sin_len= sa_length;
#endif /* HAVE_SOCKADDR_IN_SIN_LEN */
break;
#ifdef HAVE_IPV6
case AF_INET6:
sa_length= sizeof (struct sockaddr_in6);
# ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
((struct sockaddr_in6 *) sa)->sin6_len= sa_length;
# endif /* HAVE_SOCKADDR_IN6_SIN6_LEN */
break;
#endif /* HAVE_IPV6 */
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment