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 \ ctime_r \
cuserid \ cuserid \
flock \ flock \
gai_strerror \
gcvt \ gcvt \
getlogin \ getlogin \
gethostbyaddr \ gethostbyaddr \

View File

@ -59,6 +59,44 @@ int inet_aton(const char *, struct in_addr *);
# define SOCK_CONN_ERR -1 # define SOCK_CONN_ERR -1
#endif #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) static void php_network_freeaddresses(struct sockaddr **sal)
{ {
struct sockaddr **sap; 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) static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
{ {
struct sockaddr **sap; struct sockaddr **sap;
if (host != NULL) { if (host == NULL) {
return -1;
}
{
#ifdef HAVE_GETADDRINFO #ifdef HAVE_GETADDRINFO
struct addrinfo hints, *res, *sai; struct addrinfo hints, *res, *sai;
int n; int n;
memset( &hints, '\0', sizeof(hints) ); memset(&hints, '\0', sizeof(hints));
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
if (getaddrinfo(host, NULL, &hints, &res)) if (n = getaddrinfo(host, NULL, &hints, &res)) {
return -1; php_error(E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
sai = res; return -1;
}
sai = res;
for (n=2; (sai = sai->ai_next) != NULL; n++); for (n=2; (sai = sai->ai_next) != NULL; n++);
*sal = emalloc(n * sizeof(*sal)); *sal = emalloc(n * sizeof(*sal));
if (*sal == NULL) sai = res;
return -1;
sai = res;
sap = *sal; sap = *sal;
do { do {
switch (sai->ai_family) { switch (sai->ai_family) {
# ifdef HAVE_IPV6 # ifdef HAVE_IPV6
case AF_INET6: { case AF_INET6:
*sap = emalloc(sizeof(struct sockaddr_in6)); *sap = emalloc(sizeof(struct sockaddr_in6));
if (*sap == NULL) {
freeaddrinfo(res);
goto errexit;
}
*(struct sockaddr_in6 *)*sap = *(struct sockaddr_in6 *)*sap =
*((struct sockaddr_in6 *)sai->ai_addr); *((struct sockaddr_in6 *)sai->ai_addr);
} break; sap++;
break;
# endif # endif
case AF_INET: { case AF_INET:
*sap = emalloc(sizeof(struct sockaddr_in)); *sap = emalloc(sizeof(struct sockaddr_in));
if (*sap == NULL) {
freeaddrinfo(res);
goto errexit;
}
*(struct sockaddr_in *)*sap = *(struct sockaddr_in *)*sap =
*((struct sockaddr_in *)sai->ai_addr); *((struct sockaddr_in *)sai->ai_addr);
} break; sap++;
default:
*sap = NULL;
break; break;
} }
sap++; } while ((sai = sai->ai_next) != NULL);
} while ((sai = sai->ai_next) != NULL); freeaddrinfo(res);
freeaddrinfo(res);
#else #else
struct hostent *host_info; struct hostent *host_info;
struct in_addr in; struct in_addr in;
@ -127,29 +159,23 @@ static int php_network_getaddresses(const char *host, struct sockaddr ***sal)
if (!inet_aton(host, &in)) { if (!inet_aton(host, &in)) {
/* XXX NOT THREAD SAFE */ /* XXX NOT THREAD SAFE */
host_info = gethostbyname(host); host_info = gethostbyname(host);
if (host_info == NULL) if (host_info == NULL) {
php_error(E_WARNING, "php_network_getaddresses: gethostbyname failed");
return -1; return -1;
}
in = *((struct in_addr *) host_info->h_addr); in = *((struct in_addr *) host_info->h_addr);
} }
*sal = emalloc(2 * sizeof(*sal)); *sal = emalloc(2 * sizeof(*sal));
if (*sal == NULL)
return -1;
sap = *sal; sap = *sal;
*sap = emalloc(sizeof(struct sockaddr_in)); *sap = emalloc(sizeof(struct sockaddr_in));
if (*sap == NULL)
goto errexit;
(*sap)->sa_family = AF_INET; (*sap)->sa_family = AF_INET;
((struct sockaddr_in *)*sap)->sin_addr = in; ((struct sockaddr_in *)*sap)->sin_addr = in;
sap++; sap++;
#endif #endif
*sap = NULL; }
return 0; *sap = NULL;
errexit: return 0;
php_network_freeaddresses(*sal);
}
return -1;
} }
/* /*
@ -199,6 +225,7 @@ int php_hostconnect(char *host, unsigned short port, int socktype, int timeout)
sal++; sal++;
} }
php_network_freeaddresses(psal); php_network_freeaddresses(psal);
php_error(E_WARNING, "php_hostconnect: connect failed");
return -1; return -1;
ok: ok: