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 @@ ...@@ -282,6 +282,8 @@
#cmakedefine HAVE_NETINET_IN6_H 1 #cmakedefine HAVE_NETINET_IN6_H 1
#cmakedefine HAVE_IPV6 1 #cmakedefine HAVE_IPV6 1
#cmakedefine ss_family @ss_family@ #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 HAVE_TIMESPEC_TS_SEC 1
#cmakedefine STRUCT_DIRENT_HAS_D_INO 1 #cmakedefine STRUCT_DIRENT_HAS_D_INO 1
#cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1 #cmakedefine STRUCT_DIRENT_HAS_D_NAMLEN 1
......
...@@ -1000,6 +1000,21 @@ IF(NOT HAVE_SOCKADDR_STORAGE_SS_FAMILY) ...@@ -1000,6 +1000,21 @@ IF(NOT HAVE_SOCKADDR_STORAGE_SS_FAMILY)
SET(ss_family __ss_family) SET(ss_family __ss_family)
ENDIF() ENDIF()
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) SET(CMAKE_EXTRA_INCLUDE_FILES)
CHECK_STRUCT_HAS_MEMBER("struct dirent" d_ino "dirent.h" STRUCT_DIRENT_HAS_D_INO) CHECK_STRUCT_HAS_MEMBER("struct dirent" d_ino "dirent.h" STRUCT_DIRENT_HAS_D_INO)
......
...@@ -1012,6 +1012,66 @@ else ...@@ -1012,6 +1012,66 @@ else
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
fi 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 # Check for TCP wrapper support
#-------------------------------------------------------------------- #--------------------------------------------------------------------
...@@ -3121,6 +3181,7 @@ esac ...@@ -3121,6 +3181,7 @@ esac
AC_SUBST([RDTSC_SPARC_ASSEMBLY]) AC_SUBST([RDTSC_SPARC_ASSEMBLY])
#-------------------------------------------------------------------- #--------------------------------------------------------------------
# Output results # Output results
#-------------------------------------------------------------------- #--------------------------------------------------------------------
......
...@@ -1057,9 +1057,11 @@ ssize_t vio_pending(Vio *vio) ...@@ -1057,9 +1057,11 @@ ssize_t vio_pending(Vio *vio)
/** /**
This is a wrapper for the system getnameinfo(), because different OS This is a wrapper for the system getnameinfo(), because different OS
differ in the getnameinfo() implementation. For instance, Solaris 10 differ in the getnameinfo() implementation:
requires that the 2nd argument (salen) must match the actual size of the - Solaris 10 requires that the 2nd argument (salen) must match the
struct sockaddr_storage passed to it. 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, int vio_getnameinfo(const struct sockaddr *sa,
...@@ -1072,11 +1074,17 @@ int vio_getnameinfo(const struct sockaddr *sa, ...@@ -1072,11 +1074,17 @@ int vio_getnameinfo(const struct sockaddr *sa,
switch (sa->sa_family) { switch (sa->sa_family) {
case AF_INET: case AF_INET:
sa_length= sizeof (struct sockaddr_in); 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; break;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
case AF_INET6: case AF_INET6:
sa_length= sizeof (struct sockaddr_in6); 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; break;
#endif /* HAVE_IPV6 */ #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