1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
#include <php.h>
#include <php_network.h>
#include "php_sockets.h"
#ifdef PHP_WIN32
#include "windows_common.h"
#else
#include <netdb.h>
#include <arpa/inet.h>
#endif
extern int php_string_to_if_index(const char *val, unsigned *out TSRMLS_DC);
#if 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 TSRMLS_DC) /* {{{ */
{
struct in6_addr tmp;
#if HAVE_GETADDRINFO
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));
} else {
#if HAVE_GETADDRINFO
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET6;
#if HAVE_AI_V4MAPPED
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
#else
hints.ai_flags = AI_ADDRCONFIG;
#endif
getaddrinfo(string, NULL, &hints, &addrinfo);
if (!addrinfo) {
#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 (addrinfo->ai_family != PF_INET6 || addrinfo->ai_addrlen != sizeof(struct sockaddr_in6)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: Non AF_INET6 domain returned on AF_INET6 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));
freeaddrinfo(addrinfo);
#else
/* No IPv6 specific hostname resolution is available on this system? */
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host lookup failed: getaddrinfo() not available on this system");
return 0;
#endif
}
if (scope++) {
long lval = 0;
double dval = 0;
unsigned scope_id = 0;
if (IS_LONG == is_numeric_string(scope, strlen(scope), &lval, &dval, 0)) {
if (lval > 0 && lval <= UINT_MAX) {
scope_id = lval;
}
} else {
php_string_to_if_index(scope, &scope_id TSRMLS_CC);
}
sin6->sin6_scope_id = scope_id;
}
return 1;
}
/* }}} */
#endif
/* 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 TSRMLS_DC) /* {{{ */
{
struct in_addr tmp;
struct hostent *host_entry;
if (inet_aton(string, &tmp)) {
sin->sin_addr.s_addr = tmp.s_addr;
} else {
if (strlen(string) > MAXFQDNLEN || ! (host_entry = 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 TSRMLS_CC, 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;
}
/* }}} */
/* Sets addr by hostname or by ip in string form (AF_INET or AF_INET6,
* depending on the socket) */
int php_set_inet46_addr(php_sockaddr_storage *ss, socklen_t *ss_len, char *string, php_socket *php_sock TSRMLS_DC) /* {{{ */
{
if (php_sock->type == AF_INET) {
struct sockaddr_in t = {0};
if (php_set_inet_addr(&t, string, php_sock TSRMLS_CC)) {
memcpy(ss, &t, sizeof t);
ss->ss_family = AF_INET;
*ss_len = sizeof(t);
return 1;
}
}
#if HAVE_IPV6
else if (php_sock->type == AF_INET6) {
struct sockaddr_in6 t = {0};
if (php_set_inet6_addr(&t, string, php_sock TSRMLS_CC)) {
memcpy(ss, &t, sizeof t);
ss->ss_family = AF_INET6;
*ss_len = sizeof(t);
return 1;
}
}
#endif
else {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"IP address used in the context of an unexpected type of socket");
}
return 0;
}
|