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:
Stig Venaas 2001-01-13 11:48:47 +00:00
parent 5d8e3c37d9
commit 30441cda5b
2 changed files with 72 additions and 44 deletions

View File

@ -356,6 +356,7 @@ crypt \
ctime_r \
cuserid \
flock \
gai_strerror \
gcvt \
getlogin \
gethostbyaddr \

View File

@ -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: