Skip to content

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

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 34 additions & 40 deletions ext/sockets/sockaddr_conv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The 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
Expand All @@ -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) {
Expand Down Expand Up @@ -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) /* {{{ */
{
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);
}
/* }}} */

Expand Down