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);
#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) /* {{{ */
{
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, 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, E_WARNING, "Host lookup failed: getaddrinfo() not available on this system");
return 0;
#endif
}
if (scope++) {
zend_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 && (zend_ulong)lval <= UINT_MAX) {
scope_id = lval;
}
} else {
php_string_to_if_index(scope, &scope_id);
}
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) /* {{{ */
{
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 = 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;
}
/* }}} */
/* 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) /* {{{ */
{
if (php_sock->type == AF_INET) {
struct sockaddr_in t = {0};
if (php_set_inet_addr(&t, string, php_sock)) {
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)) {
memcpy(ss, &t, sizeof t);
ss->ss_family = AF_INET6;
*ss_len = sizeof(t);
return 1;
}
}
#endif
else {
php_error_docref(NULL, E_WARNING,
"IP address used in the context of an unexpected type of socket");
}
return 0;
}
|