-
Notifications
You must be signed in to change notification settings - Fork 7.9k
getaddrinfo conversion #15555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
getaddrinfo conversion #15555
Changes from 8 commits
005addf
d5b3cfe
b7b5028
84b8214
5dcd076
c8d649e
68d1e19
6253129
8556fdf
16cd84a
41c590b
c4efccd
b6c219b
500f68c
8fb9002
3dbfdf5
7267213
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,24 +11,24 @@ | |
|
||
extern zend_result php_string_to_if_index(const char *val, unsigned *out); | ||
|
||
#ifdef HAVE_IPV6 | ||
/* Sets addr by hostname, or by ip in string form (AF_INET6) */ | ||
int php_set_inet6_addr(struct sockaddr_in6 *sin6, char *string, php_socket *php_sock) /* {{{ */ | ||
int php_set_common_addr(struct sockaddr *sin, int family, char *string, php_socket *php_sock) /* {{{ */ | ||
{ | ||
struct in6_addr tmp; | ||
#ifdef HAVE_GETADDRINFO | ||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sin; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it might be possible to factorise it further via macro to avoid this double assignation and the family conditions below, wdyt ? |
||
struct sockaddr_in *sin4 = (struct sockaddr_in*)sin; | ||
struct in6_addr tmp6; | ||
struct in_addr tmp4; | ||
|
||
struct addrinfo hints; | ||
struct addrinfo *addrinfo = NULL; | ||
#endif | ||
char *scope = strchr(string, '%'); | ||
|
||
if (inet_pton(AF_INET6, string, &tmp)) { | ||
memcpy(&(sin6->sin6_addr.s6_addr), &(tmp.s6_addr), sizeof(struct in6_addr)); | ||
if (family == AF_INET6 && inet_pton(AF_INET6, string, &tmp6)) { | ||
memcpy(&(sin6->sin6_addr.s6_addr), &(tmp6.s6_addr), sizeof(struct in6_addr)); | ||
} else if (family == AF_INET && inet_pton(AF_INET, string, &tmp4)) { | ||
sin4->sin_addr.s_addr = tmp4.s_addr; | ||
} else { | ||
#ifdef HAVE_GETADDRINFO | ||
|
||
memset(&hints, 0, sizeof(struct addrinfo)); | ||
hints.ai_family = AF_INET6; | ||
hints.ai_family = family; | ||
#ifdef AI_V4MAPPED | ||
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; | ||
#else | ||
|
@@ -43,21 +43,37 @@ int php_set_inet6_addr(struct sockaddr_in6 *sin6, char *string, php_socket *php_ | |
#endif | ||
return 0; | ||
} | ||
if (addrinfo->ai_family != PF_INET6 || addrinfo->ai_addrlen != sizeof(struct sockaddr_in6)) { | ||
php_error_docref(NULL, E_WARNING, "Host lookup failed: Non AF_INET6 domain returned on AF_INET6 socket"); | ||
if (addrinfo->ai_family != family) { | ||
php_error_docref(NULL, E_WARNING, "Host lookup failed: Wrong address family returned for socket"); | ||
freeaddrinfo(addrinfo); | ||
return 0; | ||
} | ||
|
||
memcpy(&(sin6->sin6_addr.s6_addr), ((struct sockaddr_in6*)(addrinfo->ai_addr))->sin6_addr.s6_addr, sizeof(struct in6_addr)); | ||
if (addrinfo->ai_family == AF_INET6) { | ||
memcpy(&(sin6->sin6_addr.s6_addr), ((struct sockaddr_in6*)(addrinfo->ai_addr))->sin6_addr.s6_addr, sizeof(struct in6_addr)); | ||
} else if (addrinfo->ai_family == AF_INET) { | ||
memcpy(&(sin4->sin_addr.s_addr), &((struct sockaddr_in*)(addrinfo->ai_addr))->sin_addr.s_addr, sizeof(struct in_addr)); | ||
} | ||
freeaddrinfo(addrinfo); | ||
} | ||
|
||
return 1; | ||
#else | ||
/* No IPv6 specific hostname resolution is available on this system? */ | ||
php_error_docref(NULL, E_WARNING, "Host lookup failed: getaddrinfo() not available on this system"); | ||
return 0; | ||
php_error_docref(NULL, E_WARNING, "Host lookup failed: getaddrinfo() not available on this system"); | ||
return 0; | ||
#endif | ||
} | ||
/* }}} */ | ||
|
||
#ifdef HAVE_IPV6 | ||
/* Sets addr by hostname, or by ip in string form (AF_INET6) */ | ||
int php_set_inet6_addr(struct sockaddr_in6 *sin6, char *string, php_socket *php_sock) /* {{{ */ | ||
{ | ||
char *scope = strchr(string, '%'); | ||
|
||
int ret = php_set_common_addr((struct sockaddr*)sin6, AF_INET6, string, php_sock); | ||
if (!ret) { | ||
return 0; | ||
} | ||
|
||
if (scope) { | ||
|
@@ -86,29 +102,7 @@ int php_set_inet6_addr(struct sockaddr_in6 *sin6, char *string, php_socket *php_ | |
/* Sets addr by hostname, or by ip in string form (AF_INET) */ | ||
int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *php_sock) /* {{{ */ | ||
NattyNarwhal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
struct in_addr tmp; | ||
struct hostent *host_entry; | ||
|
||
if (inet_pton(AF_INET, string, &tmp)) { | ||
sin->sin_addr.s_addr = tmp.s_addr; | ||
} else { | ||
if (strlen(string) > MAXFQDNLEN || ! (host_entry = php_network_gethostbyname(string))) { | ||
/* Note: < -10000 indicates a host lookup error */ | ||
#ifdef PHP_WIN32 | ||
PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError()); | ||
#else | ||
PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno)); | ||
#endif | ||
return 0; | ||
} | ||
if (host_entry->h_addrtype != AF_INET) { | ||
php_error_docref(NULL, E_WARNING, "Host lookup failed: Non AF_INET domain returned on AF_INET socket"); | ||
return 0; | ||
} | ||
memcpy(&(sin->sin_addr.s_addr), host_entry->h_addr_list[0], host_entry->h_length); | ||
} | ||
|
||
return 1; | ||
return php_set_common_addr((struct sockaddr*)sin, AF_INET, string, php_sock); | ||
} | ||
/* }}} */ | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,7 +118,6 @@ extern void __res_ndestroy(res_state statp); | |
/* }}} */ | ||
|
||
static zend_string *php_gethostbyaddr(char *ip); | ||
static zend_string *php_gethostbyname(char *name); | ||
|
||
#ifdef HAVE_GETHOSTNAME | ||
/* {{{ Get the host name of the current machine */ | ||
|
@@ -220,7 +219,8 @@ PHP_FUNCTION(gethostbyname) | |
{ | ||
char *hostname; | ||
size_t hostname_len; | ||
zend_string *ipaddr; | ||
char addr4[INET_ADDRSTRLEN]; | ||
zend_string *ipaddr_zs = NULL; | ||
|
||
ZEND_PARSE_PARAMETERS_START(1, 1) | ||
Z_PARAM_PATH(hostname, hostname_len) | ||
|
@@ -232,11 +232,28 @@ PHP_FUNCTION(gethostbyname) | |
RETURN_STRINGL(hostname, hostname_len); | ||
} | ||
|
||
if (!(ipaddr = php_gethostbyname(hostname))) { | ||
php_sockaddr_storage resolved; | ||
int address_count = php_network_getaddress(&resolved, hostname, 0, AF_INET, 0, NULL); | ||
if (address_count == 0) { | ||
/* don't need to docref here, getaddresses E_WARNINGs for us */ | ||
RETURN_STRINGL(hostname, hostname_len); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unrelated optimization, but if we would use |
||
} | ||
|
||
/* | ||
* Future behaviour change: This function is documented as only returning IPv4 | ||
* addresses. We should change this to return IPv6 addresses as well. | ||
*/ | ||
struct sockaddr_in *address4 = (struct sockaddr_in*)&resolved; | ||
const char *ipaddr; | ||
if (resolved.ss_family == AF_INET && (ipaddr = inet_ntop(AF_INET, &address4->sin_addr, addr4, INET_ADDRSTRLEN))) { | ||
ipaddr_zs = zend_string_init(ipaddr, strlen(ipaddr), 0); | ||
} | ||
|
||
if (ipaddr_zs == NULL) { | ||
php_error_docref(NULL, E_WARNING, "Host name to ip failed %s", hostname); | ||
RETURN_STRINGL(hostname, hostname_len); | ||
} else { | ||
RETURN_STR(ipaddr); | ||
RETURN_STR(ipaddr_zs); | ||
} | ||
} | ||
/* }}} */ | ||
|
@@ -246,9 +263,6 @@ PHP_FUNCTION(gethostbynamel) | |
{ | ||
char *hostname; | ||
size_t hostname_len; | ||
struct hostent *hp; | ||
struct in_addr in; | ||
int i; | ||
char addr4[INET_ADDRSTRLEN]; | ||
|
||
ZEND_PARSE_PARAMETERS_START(1, 1) | ||
|
@@ -261,61 +275,38 @@ PHP_FUNCTION(gethostbynamel) | |
RETURN_FALSE; | ||
} | ||
|
||
hp = php_network_gethostbyname(hostname); | ||
if (!hp) { | ||
struct sockaddr **addresses = NULL; | ||
int address_count = php_network_getaddresses(hostname, 0, &addresses, NULL); | ||
if (address_count == 0) { | ||
/* don't need to docref here, getaddresses E_WARNINGs for us */ | ||
RETURN_FALSE; | ||
} | ||
|
||
array_init(return_value); | ||
|
||
for (i = 0;; i++) { | ||
/* On macos h_addr_list entries may be misaligned. */ | ||
const char *ipaddr; | ||
struct in_addr *h_addr_entry; /* Don't call this h_addr, it's a macro! */ | ||
memcpy(&h_addr_entry, &hp->h_addr_list[i], sizeof(struct in_addr *)); | ||
if (!h_addr_entry) { | ||
return; | ||
/* | ||
* Future behaviour change: This function is documented as only returning IPv4 | ||
* addresses. We should change this to return IPv6 addresses as well. | ||
*/ | ||
for (struct sockaddr **address_p = addresses; *address_p != NULL; address_p++) { | ||
struct sockaddr *address = *address_p; | ||
|
||
if (address->sa_family != AF_INET) { | ||
continue; | ||
} | ||
|
||
in = *h_addr_entry; | ||
if (!(ipaddr = inet_ntop(AF_INET, &in, addr4, INET_ADDRSTRLEN))) { | ||
struct sockaddr_in *address4 = (struct sockaddr_in*)address; | ||
const char *ipaddr; | ||
if (!(ipaddr = inet_ntop(AF_INET, &address4->sin_addr, addr4, INET_ADDRSTRLEN))) { | ||
/* unlikely regarding (too) long hostname and protocols but checking still */ | ||
php_error_docref(NULL, E_WARNING, "Host name to ip failed %s", hostname); | ||
continue; | ||
} else { | ||
add_next_index_string(return_value, ipaddr); | ||
} | ||
} | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ php_gethostbyname */ | ||
static zend_string *php_gethostbyname(char *name) | ||
{ | ||
struct hostent *hp; | ||
struct in_addr *h_addr_0; /* Don't call this h_addr, it's a macro! */ | ||
struct in_addr in; | ||
char addr4[INET_ADDRSTRLEN]; | ||
const char *address; | ||
|
||
hp = php_network_gethostbyname(name); | ||
if (!hp) { | ||
return zend_string_init(name, strlen(name), 0); | ||
} | ||
|
||
/* On macos h_addr_list entries may be misaligned. */ | ||
memcpy(&h_addr_0, &hp->h_addr_list[0], sizeof(struct in_addr *)); | ||
if (!h_addr_0) { | ||
return zend_string_init(name, strlen(name), 0); | ||
} | ||
|
||
memcpy(&in.s_addr, h_addr_0, sizeof(in.s_addr)); | ||
|
||
if (!(address = inet_ntop(AF_INET, &in, addr4, INET_ADDRSTRLEN))) { | ||
return NULL; | ||
} | ||
|
||
return zend_string_init(address, strlen(address), 0); | ||
php_network_freeaddresses(addresses); | ||
} | ||
/* }}} */ | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.