mirror of
https://github.com/php/php-src.git
synced 2024-11-23 09:54:15 +08:00
Simplified code a bit, added detailed error reporting, and fixed a bug
when getaddrinfo returned a non-IP family before IP families
This commit is contained in:
parent
5d8e3c37d9
commit
30441cda5b
@ -356,6 +356,7 @@ crypt \
|
||||
ctime_r \
|
||||
cuserid \
|
||||
flock \
|
||||
gai_strerror \
|
||||
gcvt \
|
||||
getlogin \
|
||||
gethostbyaddr \
|
||||
|
115
main/network.c
115
main/network.c
@ -59,6 +59,44 @@ int inet_aton(const char *, struct in_addr *);
|
||||
# define SOCK_CONN_ERR -1
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GAI_STRERROR
|
||||
# define PHP_GAI_STRERROR(x) (gai_strerror(x))
|
||||
#else
|
||||
# define PHP_GAI_STRERROR(x) (php_gai_strerror(x))
|
||||
static char *php_gai_strerror(int code) {
|
||||
static struct {
|
||||
int code;
|
||||
const char *msg;
|
||||
} values[] = {
|
||||
# ifdef EAI_ADDRFAMILY
|
||||
{EAI_ADDRFAMILY, "Address family for hostname not supported"},
|
||||
# endif
|
||||
{EAI_AGAIN, "Temporary failure in name resolution"},
|
||||
{EAI_BADFLAGS, "Bad value for ai_flags"},
|
||||
{EAI_FAIL, "Non-recoverable failure in name resolution"},
|
||||
{EAI_FAMILY, "ai_family not supported"},
|
||||
{EAI_MEMORY, "Memory allocation failure"},
|
||||
# ifdef EAI_NODATA
|
||||
{EAI_NODATA, "No address associated with hostname"},
|
||||
# endif
|
||||
{EAI_NONAME, "Name or service not known"},
|
||||
{EAI_SERVICE, "Servname not supported for ai_socktype"},
|
||||
{EAI_SOCKTYPE, "ai_socktype not supported"},
|
||||
{EAI_SYSTEM, "System error"},
|
||||
{0, NULL}
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; values[i].msg != NULL; i++) {
|
||||
if (values[i].code == code) {
|
||||
return (char *)values[i].msg;
|
||||
}
|
||||
}
|
||||
|
||||
return "Unknown error";
|
||||
}
|
||||
#endif
|
||||
|
||||
static void php_network_freeaddresses(struct sockaddr **sal)
|
||||
{
|
||||
struct sockaddr **sap;
|
||||
@ -73,53 +111,47 @@ static void php_network_freeaddresses(struct sockaddr **sal)
|
||||
static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
|
||||
{
|
||||
struct sockaddr **sap;
|
||||
|
||||
if (host != NULL) {
|
||||
|
||||
if (host == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo hints, *res, *sai;
|
||||
struct addrinfo hints, *res, *sai;
|
||||
int n;
|
||||
|
||||
memset( &hints, '\0', sizeof(hints) );
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
if (getaddrinfo(host, NULL, &hints, &res))
|
||||
return -1;
|
||||
sai = res;
|
||||
memset(&hints, '\0', sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
if (n = getaddrinfo(host, NULL, &hints, &res)) {
|
||||
php_error(E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sai = res;
|
||||
for (n=2; (sai = sai->ai_next) != NULL; n++);
|
||||
*sal = emalloc(n * sizeof(*sal));
|
||||
if (*sal == NULL)
|
||||
return -1;
|
||||
|
||||
sai = res;
|
||||
sai = res;
|
||||
sap = *sal;
|
||||
do {
|
||||
switch (sai->ai_family) {
|
||||
do {
|
||||
switch (sai->ai_family) {
|
||||
# ifdef HAVE_IPV6
|
||||
case AF_INET6: {
|
||||
case AF_INET6:
|
||||
*sap = emalloc(sizeof(struct sockaddr_in6));
|
||||
if (*sap == NULL) {
|
||||
freeaddrinfo(res);
|
||||
goto errexit;
|
||||
}
|
||||
*(struct sockaddr_in6 *)*sap =
|
||||
*((struct sockaddr_in6 *)sai->ai_addr);
|
||||
} break;
|
||||
sap++;
|
||||
break;
|
||||
# endif
|
||||
case AF_INET: {
|
||||
case AF_INET:
|
||||
*sap = emalloc(sizeof(struct sockaddr_in));
|
||||
if (*sap == NULL) {
|
||||
freeaddrinfo(res);
|
||||
goto errexit;
|
||||
}
|
||||
*(struct sockaddr_in *)*sap =
|
||||
*((struct sockaddr_in *)sai->ai_addr);
|
||||
} break;
|
||||
default:
|
||||
*sap = NULL;
|
||||
sap++;
|
||||
break;
|
||||
}
|
||||
sap++;
|
||||
} while ((sai = sai->ai_next) != NULL);
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
} while ((sai = sai->ai_next) != NULL);
|
||||
freeaddrinfo(res);
|
||||
#else
|
||||
struct hostent *host_info;
|
||||
struct in_addr in;
|
||||
@ -127,29 +159,23 @@ static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
|
||||
if (!inet_aton(host, &in)) {
|
||||
/* XXX NOT THREAD SAFE */
|
||||
host_info = gethostbyname(host);
|
||||
if (host_info == NULL)
|
||||
if (host_info == NULL) {
|
||||
php_error(E_WARNING, "php_network_getaddresses: gethostbyname failed");
|
||||
return -1;
|
||||
}
|
||||
in = *((struct in_addr *) host_info->h_addr);
|
||||
}
|
||||
|
||||
*sal = emalloc(2 * sizeof(*sal));
|
||||
if (*sal == NULL)
|
||||
return -1;
|
||||
sap = *sal;
|
||||
*sap = emalloc(sizeof(struct sockaddr_in));
|
||||
if (*sap == NULL)
|
||||
goto errexit;
|
||||
|
||||
(*sap)->sa_family = AF_INET;
|
||||
((struct sockaddr_in *)*sap)->sin_addr = in;
|
||||
sap++;
|
||||
#endif
|
||||
*sap = NULL;
|
||||
return 0;
|
||||
errexit:
|
||||
php_network_freeaddresses(*sal);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
*sap = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -199,6 +225,7 @@ int php_hostconnect(char *host, unsigned short port, int socktype, int timeout)
|
||||
sal++;
|
||||
}
|
||||
php_network_freeaddresses(psal);
|
||||
php_error(E_WARNING, "php_hostconnect: connect failed");
|
||||
return -1;
|
||||
|
||||
ok:
|
||||
|
Loading…
Reference in New Issue
Block a user