wez Sat Jun 28 07:12:48 2003 EDT Modified files: /php-src/main network.c Log: Merge getaddrinfo() tidy-up from PHP_4_3 branch. Index: php-src/main/network.c diff -u php-src/main/network.c:1.100 php-src/main/network.c:1.101 --- php-src/main/network.c:1.100 Tue Jun 10 16:03:41 2003 +++ php-src/main/network.c Sat Jun 28 07:12:48 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: network.c,v 1.100 2003/06/10 20:03:41 imajes Exp $ */ +/* $Id: network.c,v 1.101 2003/06/28 11:12:48 wez Exp $ */ /*#define DEBUG_MAIN_NETWORK 1*/ @@ -164,11 +164,12 @@ /* {{{ php_network_getaddresses * Returns number of addresses, 0 for none/error */ -static int php_network_getaddresses(const char *host, struct sockaddr ***sal, char **error_string TSRMLS_DC) +static int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC) { struct sockaddr **sap; int n; #ifdef HAVE_GETADDRINFO + static int ipv6_borked = -1; /* the way this is used *is* thread safe */ struct addrinfo hints, *res, *sai; #else struct hostent *host_info; @@ -178,59 +179,59 @@ if (host == NULL) { return 0; } - #ifdef HAVE_GETADDRINFO memset(&hints, '\0', sizeof(hints)); - + + hints.ai_family = AF_INET; /* default to regular inet (see below) */ + hints.ai_socktype = socktype; + # ifdef HAVE_IPV6 - hints.ai_family = AF_UNSPEC; -# else - hints.ai_family = AF_INET; -# endif - - if ((n = getaddrinfo(host, NULL, &hints, &res)) || res == NULL) { - if (error_string) { - spprintf(error_string, 0, "getaddrinfo: %s", (res == NULL ? "null result pointer" : PHP_GAI_STRERROR(n))); + /* probe for a working IPv6 stack; even if detected as having v6 at compile + * time, at runtime some stacks are slow to resolve or have other issues + * if they are not correctly configured. + * static variable use is safe here since simple store or fetch operations + * are atomic and because the actual probe process is not in danger of + * collisions or race conditions. */ + if (ipv6_borked == -1) { + int s; + + s = socket(PF_INET6, SOCK_DGRAM, 0); + if (s == SOCK_ERR) { + ipv6_borked = 1; } else { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", (res == NULL ? "null result pointer" : PHP_GAI_STRERROR(n))); + ipv6_borked = 0; + closesocket(s); } + } + hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC; +# endif + + if ((n = getaddrinfo(host, NULL, &hints, &res))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n)); + return 0; + } else if (res == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed (null result pointer)"); return 0; } sai = res; - - for (n = 1; (sai = sai->ai_next) != NULL; n++) { + for (n = 1; (sai = sai->ai_next) != NULL; n++) ; - } - + *sal = safe_emalloc((n + 1), sizeof(*sal), 0); sai = res; sap = *sal; + do { - switch (sai->ai_family) { -# if HAVE_IPV6 - case AF_INET6: - *sap = emalloc(sizeof(struct sockaddr_in6)); - *(struct sockaddr_in6 *)*sap = - *((struct sockaddr_in6 *)sai->ai_addr); - sap++; - break; -# endif - case AF_INET: - *sap = emalloc(sizeof(struct sockaddr_in)); - *(struct sockaddr_in *)*sap = - *((struct sockaddr_in *)sai->ai_addr); - sap++; - break; - } + *sap = emalloc(sai->ai_addrlen); + memcpy(*sap, sai->ai_addr, sai->ai_addrlen); + sap++; } while ((sai = sai->ai_next) != NULL); + freeaddrinfo(res); #else - if (!inet_aton(host, &in)) { - /* XXX NOT THREAD SAFE - * (but it *is* thread safe under win32) - */ + /* XXX NOT THREAD SAFE (is safe under win32) */ host_info = gethostbyname(host); if (host_info == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: gethostbyname failed"); @@ -247,7 +248,7 @@ sap++; n = 1; #endif - + *sap = NULL; return n; } @@ -402,7 +403,7 @@ struct sockaddr **sal, **psal, *sa; socklen_t socklen; - num_addrs = php_network_getaddresses(host, &psal, error_string TSRMLS_CC); + num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC); if (num_addrs == 0) { /* could not resolve address(es) */ @@ -667,7 +668,7 @@ struct timeval limit_time, time_now; #endif - num_addrs = php_network_getaddresses(host, &psal, error_string TSRMLS_CC); + num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC); if (num_addrs == 0) { /* could not resolve address(es) */
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php