瀏覽代碼

Snarf some logic from python, adapted to our own needs, to handle gethostbyname_r correctly across platforms.

svn:r3649
Nick Mathewson 20 年之前
父節點
當前提交
d060f845f2
共有 2 個文件被更改,包括 79 次插入5 次删除
  1. 56 1
      configure.in
  2. 23 4
      src/common/compat.c

+ 56 - 1
configure.in

@@ -151,7 +151,7 @@ dnl These headers are not essential
 
 AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h pthread.h stddef.h inttypes.h)
 
-AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit setrlimit strlcat strlcpy strtoull getpwnam ftello pthread_create gethostbyname_r getaddrinfo)
+AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit setrlimit strlcat strlcpy strtoull getpwnam ftello pthread_create getaddrinfo)
 AC_FUNC_FSEEKO
 
 AC_CHECK_MEMBERS([struct timeval.tv_sec])
@@ -246,6 +246,61 @@ if [[ $dmalloc -eq 1 ]]; then
   AC_DEFINE(DMALLOC_FUNC_CHECK, 1, [Enable dmalloc's malloc function check])
 fi
 
+# Check for gethostbyname_r in all its glorious incompatible versions.
+#   (This logic is based on that in Python's configure.in)
+AH_TEMPLATE(HAVE_GETHOSTBYNAME_R,
+  [Define this if you have any gethostbyname_r()])
+
+AC_CHECK_FUNC(gethostbyname_r, [
+  AC_MSG_CHECKING([how many arguments gethostbyname_r() wants])
+  OLD_CFLAGS=$CFLAGS
+  CFLAGS="$CFLAGS $MY_CPPFLAGS $MY_THREAD_CPPFLAGS $MY_CFLAGS"
+  AC_TRY_COMPILE([
+#include <netdb.h>
+  ], [
+    char *cp1, *cp2;
+    struct hostent *h1, *h2;
+    int i1, i2;
+    (void)gethostbyname_r(cp1,h1,cp2,i1,&h2,&i2);
+  ], [
+    AC_DEFINE(HAVE_GETHOSTBYNAME_R)
+    AC_DEFINE(HAVE_GETHOSTBYNAME_R_6_ARG, 1,
+     [Define this if gethostbyname_r takes 6 arguments])
+    AC_MSG_RESULT(6)
+  ], [
+    AC_TRY_COMPILE([
+#include <netdb.h>
+    ], [
+      char *cp1, *cp2;
+      struct hostent *h1;
+      int i1, i2;
+      (void)gethostbyname_r(cp1,h1,cp2,i1,&i2);
+    ], [
+      AC_DEFINE(HAVE_GETHOSTBYNAME_R)
+      AC_DEFINE(HAVE_GETHOSTBYNAME_R_5_ARG, 1,
+        [Define this if gethostbyname_r takes 5 arguments])
+      AC_MSG_RESULT(5)
+   ], [
+      AC_TRY_COMPILE([
+#include <netdb.h>
+     ], [
+       char *cp1;
+       struct hostent *h1;
+       struct hostent_data hd;
+       (void) gethostbyname_r(cp1,h1,&hd);
+     ], [
+       AC_DEFINE(HAVE_GETHOSTBYNAME_R)
+       AC_DEFINE(HAVE_GETHOSTBYNAME_R_3_ARG, 1,
+         [Define this if gethostbyname_r takes 3 arguments])
+       AC_MSG_RESULT(3)
+     ], [
+       AC_MSG_RESULT(0)
+     ])
+  ])
+ ])
+ CFLAGS=$OLD_CFLAGS
+])
+
 # $prefix stores the value of the --prefix command line option, or
 # NONE if the option wasn't set.  In the case that it wasn't set, make
 # it be the default, so that we can use it to expand directories now.

+ 23 - 4
src/common/compat.c

@@ -530,10 +530,29 @@ int tor_lookup_hostname(const char *name, uint32_t *addr)
     return (err == EAI_AGAIN) ? 1 : -1;
 #else
     struct hostent *ent;
-#ifdef HAVE_GETHOSTBYNAME_R
-    ent = gethostbyname_r(name);
+    int err;
+#ifdef HAVE_GETHOSTBYNAME_R_6_ARG
+    char buf[2048];
+    struct hostent hostent;
+    int r;
+    r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
+#elif defined(HAVE_GETHOSTBYNAME_R_5_ARG);
+    char buf[2048];
+    struct hostent hostent;
+    ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
+#elif defined(HAVE_GETHOSTBYNAME_R_3_ARG);
+    struct hostent_data data;
+    struct hostent hent;
+    memset(&data, 0, sizeof(data));
+    err = gethostbyname_r(name, &hent, &data);
+    ent = err ? NULL : &hent;
 #else
     ent = gethostbyname(name);
+#ifdef MS_WINDOWS
+    err = WSAGetLastError();
+#else
+    err = h_errno;
+#endif
 #endif
     if (ent) {
       /* break to remind us if we move away from IPv4 */
@@ -543,9 +562,9 @@ int tor_lookup_hostname(const char *name, uint32_t *addr)
     }
     memset(addr, 0, 4);
 #ifdef MS_WINDOWS
-    return (WSAGetLastError() == WSATRY_AGAIN) ? 1 : -1;
+    return (err == WSATRY_AGAIN) ? 1 : -1;
 #else
-    return (h_errno == TRY_AGAIN) ? 1 : -1;
+    return (err == TRY_AGAIN) ? 1 : -1;
 #endif
 #endif
   }