]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
curl_addrinfo: support operating systems with only getaddrinfo(3)
authorJonas 'Sortie' Termansen <sortie@maxsi.org>
Fri, 1 Nov 2024 22:53:00 +0000 (23:53 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Sat, 2 Nov 2024 21:28:59 +0000 (22:28 +0100)
The gethostbyname(3) family was removed in POSIX-1.2008 in favor of
getaddrinfo(3) introduced in POSIX-1.2001. Modern POSIX systems such as
Sortix does not have gethostbyname nor the related definitions and
structures.

curl already only uses getaddrinfo(3) if available and thread safe,
although there is mild breakage if the related gethostbyname definitions
are missing.

This change attempts to fix that breakage:

Remove an unnecessary configure error if gethostbyname is missing since
getaddrinfo is enough as a fallback.

Rewrite Curl_ip2addr to not use struct hostent as it no longer is
standardized and create the struct Curl_addrinfo directly.

Only define the Curl_he2ai function on non-getaddrinfo systems where it
is going to be used with struct hoestent.

Revoke the fallback logic for when it's unknown whether getaddrinfo is
thread safe. It doesn't appear to make any sense since h_errno is
unrelated to getaddrinfo. The logic prevents new POSIX.1-2024 systems
from passing the thread safety test since h_errno does not exist anymore
and POSIX already requires getaddrinfo to be thread safe. There's
already a denylist in place for operating systems with known buggy
implementations.

Closes #15475

configure.ac
lib/curl_addrinfo.c
lib/curl_addrinfo.h
lib/hostip4.c
m4/curl-functions.m4

index 58ce834eda53d81d482a5a451eebe8d5c9aaf26d..47c8353494c8a0951b8efb960a6fa4c6ffa55024 100644 (file)
@@ -1355,10 +1355,6 @@ if test "$HAVE_GETHOSTBYNAME" != "1"; then
   )
 fi
 
-if test "$HAVE_GETHOSTBYNAME" != "1"; then
-  AC_MSG_ERROR([couldn't find libraries for gethostbyname()])
-fi
-
 CURL_CHECK_LIBS_CONNECT
 
 CURL_NETWORK_LIBS=$LIBS
index 44e10e9c9ae9c8d3d02b19f99ee749ac00d5169d..a08caf3328c6bd752a712091561c876fcf7b2229 100644 (file)
@@ -252,6 +252,7 @@ Curl_getaddrinfo_ex(const char *nodename,
  *     #define h_addr  h_addr_list[0]
  */
 
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
 struct Curl_addrinfo *
 Curl_he2ai(const struct hostent *he, int port)
 {
@@ -350,19 +351,7 @@ Curl_he2ai(const struct hostent *he, int port)
 
   return firstai;
 }
-
-
-struct namebuff {
-  struct hostent hostentry;
-  union {
-    struct in_addr  ina4;
-#ifdef USE_IPV6
-    struct in6_addr ina6;
 #endif
-  } addrentry;
-  char *h_addr_list[2];
-};
-
 
 /*
  * Curl_ip2addr()
@@ -377,71 +366,68 @@ struct Curl_addrinfo *
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
 {
   struct Curl_addrinfo *ai;
-
-#if defined(__VMS) && \
-    defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
-#pragma pointer_size save
-#pragma pointer_size short
-#pragma message disable PTRMISMATCH
-#endif
-
-  struct hostent  *h;
-  struct namebuff *buf;
-  char  *addrentry;
-  char  *hoststr;
   size_t addrsize;
+  size_t namelen;
+  struct sockaddr_in *addr;
+#ifdef USE_IPV6
+  struct sockaddr_in6 *addr6;
+#endif
 
   DEBUGASSERT(inaddr && hostname);
 
-  buf = malloc(sizeof(struct namebuff));
-  if(!buf)
+  namelen = strlen(hostname) + 1;
+
+  if(af == AF_INET)
+    addrsize = sizeof(struct sockaddr_in);
+#ifdef USE_IPV6
+  else if(af == AF_INET6)
+    addrsize = sizeof(struct sockaddr_in6);
+#endif
+  else
     return NULL;
 
-  hoststr = strdup(hostname);
-  if(!hoststr) {
-    free(buf);
+  /* allocate memory to hold the struct, the address and the name */
+  ai = calloc(1, sizeof(struct Curl_addrinfo) + addrsize + namelen);
+  if(!ai)
     return NULL;
-  }
+  /* put the address after the struct */
+  ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo));
+  /* then put the name after the address */
+  ai->ai_canonname = (char *)ai->ai_addr + addrsize;
+  memcpy(ai->ai_canonname, hostname, namelen);
+  ai->ai_family = af;
+  ai->ai_socktype = SOCK_STREAM;
+  ai->ai_addrlen = (curl_socklen_t)addrsize;
+  /* leave the rest of the struct filled with zero */
 
   switch(af) {
   case AF_INET:
-    addrsize = sizeof(struct in_addr);
-    addrentry = (void *)&buf->addrentry.ina4;
-    memcpy(addrentry, inaddr, sizeof(struct in_addr));
+    addr = (void *)ai->ai_addr; /* storage area for this info */
+
+    memcpy(&addr->sin_addr, inaddr, sizeof(struct in_addr));
+#ifdef __MINGW32__
+    addr->sin_family = (short)af;
+#else
+    addr->sin_family = (CURL_SA_FAMILY_T)af;
+#endif
+    addr->sin_port = htons((unsigned short)port);
     break;
+
 #ifdef USE_IPV6
   case AF_INET6:
-    addrsize = sizeof(struct in6_addr);
-    addrentry = (void *)&buf->addrentry.ina6;
-    memcpy(addrentry, inaddr, sizeof(struct in6_addr));
+    addr6 = (void *)ai->ai_addr; /* storage area for this info */
+
+    memcpy(&addr6->sin6_addr, inaddr, sizeof(struct in6_addr));
+#ifdef __MINGW32__
+    addr6->sin6_family = (short)af;
+#else
+    addr6->sin6_family = (CURL_SA_FAMILY_T)af;
+#endif
+    addr6->sin6_port = htons((unsigned short)port);
     break;
 #endif
-  default:
-    free(hoststr);
-    free(buf);
-    return NULL;
   }
 
-  h = &buf->hostentry;
-  h->h_name = hoststr;
-  h->h_aliases = NULL;
-  h->h_addrtype = (short)af;
-  h->h_length = (short)addrsize;
-  h->h_addr_list = &buf->h_addr_list[0];
-  h->h_addr_list[0] = addrentry;
-  h->h_addr_list[1] = NULL; /* terminate list of entries */
-
-#if defined(__VMS) && \
-    defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
-#pragma pointer_size restore
-#pragma message enable PTRMISMATCH
-#endif
-
-  ai = Curl_he2ai(h, port);
-
-  free(hoststr);
-  free(buf);
-
   return ai;
 }
 
index 9ceac997da512d155f558882268185a62b0792f4..2303e95e314ea9c7c38bdcb3c20946ef2d957ae9 100644 (file)
@@ -71,8 +71,10 @@ Curl_getaddrinfo_ex(const char *nodename,
                     struct Curl_addrinfo **result);
 #endif
 
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
 struct Curl_addrinfo *
 Curl_he2ai(const struct hostent *he, int port);
+#endif
 
 struct Curl_addrinfo *
 Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port);
index 3bfea48d4fcc0ced739b0dfdc3816f0738c713ab..58333fbc60763bf554d9d35650a0ebceed2c1e22 100644 (file)
@@ -126,8 +126,10 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
   int res;
 #endif
   struct Curl_addrinfo *ai = NULL;
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
   struct hostent *h = NULL;
   struct hostent *buf = NULL;
+#endif
 
 #if defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)
   struct addrinfo hints;
@@ -288,12 +290,14 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
 #endif /* (HAVE_GETADDRINFO && HAVE_GETADDRINFO_THREADSAFE) ||
            HAVE_GETHOSTBYNAME_R */
 
+#if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE))
   if(h) {
     ai = Curl_he2ai(h, port);
 
     if(buf) /* used a *_r() function */
       free(buf);
   }
+#endif
 
   return ai;
 }
index 93d00dd2f266b312adb032234516ac859f644217..356c6651e5f8c2396046a73edcb7f7971fc4c338 100644 (file)
@@ -1484,52 +1484,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [
       tst_tsafe_getaddrinfo="yes"
     fi
     if test "$tst_tsafe_getaddrinfo" = "unknown"; then
-      CURL_CHECK_DEF_CC([h_errno], [
-        $curl_includes_sys_socket
-        $curl_includes_netdb
-        ], [silent])
-      if test "$curl_cv_have_def_h_errno" = "yes"; then
-        tst_h_errno_macro="yes"
-      else
-        tst_h_errno_macro="no"
-      fi
-      AC_COMPILE_IFELSE([
-        AC_LANG_PROGRAM([[
-          $curl_includes_sys_socket
-          $curl_includes_netdb
-        ]],[[
-          h_errno = 2;
-          if(0 != h_errno)
-            return 1;
-        ]])
-      ],[
-        tst_h_errno_modifiable_lvalue="yes"
-      ],[
-        tst_h_errno_modifiable_lvalue="no"
-      ])
-      AC_COMPILE_IFELSE([
-        AC_LANG_PROGRAM([[
-        ]],[[
-          #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
-            return 0;
-          #elif defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 700)
-            return 0;
-          #else
-            #error force compilation error
-          #endif
-        ]])
-      ],[
-        tst_h_errno_sbs_issue_7="yes"
-      ],[
-        tst_h_errno_sbs_issue_7="no"
-      ])
-      if test "$tst_h_errno_macro" = "no" &&
-         test "$tst_h_errno_modifiable_lvalue" = "no" &&
-         test "$tst_h_errno_sbs_issue_7" = "no"; then
-        tst_tsafe_getaddrinfo="no"
-      else
-        tst_tsafe_getaddrinfo="yes"
-      fi
+      tst_tsafe_getaddrinfo="yes"
     fi
     AC_MSG_RESULT([$tst_tsafe_getaddrinfo])
     if test "$tst_tsafe_getaddrinfo" = "yes"; then