curl_addrinfo: support operating systems with only getaddrinfo(3)
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
This commit is contained in:
parent
25025419c9
commit
78c3172921
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user