php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
net.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Sara Golemon <pollita@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17#include "php.h"
18#include "php_network.h"
19
20#ifdef HAVE_ARPA_INET_H
21# include <arpa/inet.h>
22#endif
23
24#ifdef HAVE_NET_IF_H
25# include <net/if.h>
26#endif
27
28#ifdef HAVE_GETIFADDRS
29# include <ifaddrs.h>
30#elif defined(__PASE__)
31/* IBM i implements getifaddrs, but under its own name */
32#include <as400_protos.h>
33#define getifaddrs Qp2getifaddrs
34#define freeifaddrs Qp2freeifaddrs
35#define ifaddrs ifaddrs_pase
36#endif
37
38#ifdef PHP_WIN32
39# ifndef __clang__
40# include <intrin.h>
41# endif
42# include <winsock2.h>
43# include <ws2ipdef.h>
44# include <Ws2tcpip.h>
45# include <iphlpapi.h>
46#else
47# include <netdb.h>
48#endif
49
50PHPAPI zend_string* php_inet_ntop(const struct sockaddr *addr) {
51 socklen_t addrlen = sizeof(struct sockaddr_in);
52
53 if (!addr) { return NULL; }
54
55 switch (addr->sa_family) {
56#ifdef AF_INET6
57 case AF_INET6: {
58 zend_string *ret = zend_string_alloc(INET6_ADDRSTRLEN, 0);
59 if (inet_ntop(AF_INET6, &(((struct sockaddr_in6*)addr)->sin6_addr), ZSTR_VAL(ret), INET6_ADDRSTRLEN)) {
60 ZSTR_LEN(ret) = strlen(ZSTR_VAL(ret));
61 return ret;
62 }
63 zend_string_efree(ret);
64 break;
65 }
66#endif
67 case AF_INET: {
68 zend_string *ret = zend_string_alloc(INET_ADDRSTRLEN, 0);
69 if (inet_ntop(AF_INET, &(((struct sockaddr_in*)addr)->sin_addr), ZSTR_VAL(ret), INET_ADDRSTRLEN)) {
70 ZSTR_LEN(ret) = strlen(ZSTR_VAL(ret));
71 return ret;
72 }
73 zend_string_efree(ret);
74 break;
75 }
76 }
77
78 /* Fallback on getnameinfo() */
79 switch (addr->sa_family) {
80#ifdef AF_INET6
81 case AF_INET6:
82 addrlen = sizeof(struct sockaddr_in6);
83 ZEND_FALLTHROUGH;
84#endif
85 case AF_INET: {
86 zend_string *ret = zend_string_alloc(NI_MAXHOST, 0);
87 if (getnameinfo(addr, addrlen, ZSTR_VAL(ret), NI_MAXHOST, NULL, 0, NI_NUMERICHOST) == SUCCESS) {
88 /* Also demangle numeric host with %name suffix */
89 char *colon = strchr(ZSTR_VAL(ret), '%');
90 if (colon) { *colon = 0; }
91 ZSTR_LEN(ret) = strlen(ZSTR_VAL(ret));
92 return ret;
93 }
94 zend_string_efree(ret);
95 break;
96 }
97 }
98
99 return NULL;
100}
101
102#if defined(PHP_WIN32) || defined(HAVE_GETIFADDRS) || defined(__PASE__)
103static void iface_append_unicast(zval *unicast, zend_long flags,
104 struct sockaddr *addr, struct sockaddr *netmask,
105 struct sockaddr *broadcast, struct sockaddr *ptp) {
106 zend_string *host;
107 zval u;
108
109 array_init(&u);
110 add_assoc_long(&u, "flags", flags);
111
112 if (addr) {
113 add_assoc_long(&u, "family", addr->sa_family);
114 if ((host = php_inet_ntop(addr))) {
115 add_assoc_str(&u, "address", host);
116 }
117 }
118 if ((host = php_inet_ntop(netmask))) {
119 add_assoc_str(&u, "netmask", host);
120 }
121
122 if ((host = php_inet_ntop(broadcast))) {
123 add_assoc_str(&u, "broadcast", host);
124 }
125
126 if ((host = php_inet_ntop(ptp))) {
127 add_assoc_str(&u, "ptp", host);
128 }
129
130 add_next_index_zval(unicast, &u);
131}
132
133/* {{{ Returns an array in the form:
134array(
135 'ifacename' => array(
136 'description' => 'Awesome interface', // Win32 only
137 'mac' => '00:11:22:33:44:55', // Win32 only
138 'mtu' => 1234, // Win32 only
139 'unicast' => array(
140 0 => array(
141 'family' => 2, // e.g. AF_INET, AF_INET6, AF_PACKET
142 'address' => '127.0.0.1',
143 'netmnask' => '255.0.0.0',
144 'broadcast' => '127.255.255.255', // POSIX only
145 'ptp' => '127.0.0.2', // POSIX only
146 ), // etc...
147 ),
148 ), // etc...
149)
150*/
152#ifdef PHP_WIN32
153# define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
154# define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
155 ULONG family = AF_UNSPEC;
156 ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
157 PIP_ADAPTER_ADDRESSES pAddresses = NULL, p;
158 PIP_ADAPTER_UNICAST_ADDRESS u = NULL;
159 ULONG outBufLen = 0;
160 DWORD dwRetVal = 0;
161
163
164 // Make an initial call to GetAdaptersAddresses to get the
165 // size needed into the outBufLen variable
166 if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
167 FREE(pAddresses);
168 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
169 }
170
171 if (pAddresses == NULL) {
172 zend_error(E_WARNING, "Memory allocation failed for IP_ADAPTER_ADDRESSES struct");
174 }
175
176 dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
177
178 if (NO_ERROR != dwRetVal) {
179 char *buf = php_win32_error_to_msg(GetLastError());
180 zend_error(E_WARNING, "GetAdaptersAddresses failed: %s", buf);
182 FREE(pAddresses);
184 }
185
187 for (p = pAddresses; p; p = p->Next) {
188 zval iface, unicast;
189
190 if ((IF_TYPE_ETHERNET_CSMACD != p->IfType) && (IF_TYPE_IEEE80211 != p->IfType) && (IF_TYPE_SOFTWARE_LOOPBACK != p->IfType)) {
191 continue;
192 }
193
194 array_init(&iface);
195
196 if (p->Description) {
197 char tmp[256];
198 memset(tmp, 0, sizeof(tmp));
199 wcstombs(tmp, p->Description, sizeof(tmp));
200 add_assoc_string(&iface, "description", tmp);
201 }
202
203 if (p->PhysicalAddressLength > 0) {
204 zend_string *mac = zend_string_alloc(p->PhysicalAddressLength * 3, 0);
205 char *s = ZSTR_VAL(mac);
206 ULONG i;
207 for (i = 0; i < p->PhysicalAddressLength; ++i) {
208 s += snprintf(s, 4, "%02X:", p->PhysicalAddress[i]);
209 }
210 *(--s) = 0;
211 ZSTR_LEN(mac) = s - ZSTR_VAL(mac);
212 add_assoc_str(&iface, "mac", mac);
213 }
214
215 /* Flags could be placed at this level,
216 * but we repeat it in the unicast subarray
217 * for consistency with the POSIX version.
218 */
219 add_assoc_long(&iface, "mtu", p->Mtu);
220
221 array_init(&unicast);
222 for (u = p->FirstUnicastAddress; u; u = u->Next) {
223 switch (u->Address.lpSockaddr->sa_family) {
224 case AF_INET: {
225 ULONG mask;
226 struct sockaddr_in sin_mask;
227
228 ConvertLengthToIpv4Mask(u->OnLinkPrefixLength, &mask);
229 sin_mask.sin_family = AF_INET;
230 sin_mask.sin_addr.s_addr = mask;
231
232 iface_append_unicast(&unicast, p->Flags,
233 (struct sockaddr*)u->Address.lpSockaddr,
234 (struct sockaddr*)&sin_mask, NULL, NULL);
235 break;
236 }
237 case AF_INET6: {
238 ULONG i, j;
239 struct sockaddr_in6 sin6_mask;
240
241 memset(&sin6_mask, 0, sizeof(sin6_mask));
242 sin6_mask.sin6_family = AF_INET6;
243 for (i = u->OnLinkPrefixLength, j = 0; i > 0; i -= 8, ++j) {
244 sin6_mask.sin6_addr.s6_addr[j] = (i >= 8) ? 0xff : ((ULONG)((0xffU << (8 - i)) & 0xffU));
245 }
246
247 iface_append_unicast(&unicast, p->Flags,
248 (struct sockaddr*)u->Address.lpSockaddr,
249 (struct sockaddr*)&sin6_mask, NULL, NULL);
250 break;
251 }
252 }
253 }
254 add_assoc_zval(&iface, "unicast", &unicast);
255
256 add_assoc_bool(&iface, "up", (p->OperStatus == IfOperStatusUp));
257
258 add_assoc_zval(return_value, p->AdapterName, &iface);
259 }
260
261 FREE(pAddresses);
262#undef MALLOC
263#undef FREE
264#elif defined(HAVE_GETIFADDRS) || defined(__PASE__) /* !PHP_WIN32 */
265 struct ifaddrs *addrs = NULL, *p;
266
268
269 if (getifaddrs(&addrs)) {
270 php_error(E_WARNING, "getifaddrs() failed %d: %s", errno, strerror(errno));
272 }
273
275 for (p = addrs; p; p = p->ifa_next) {
276 zval *iface = zend_hash_str_find(Z_ARR_P(return_value), p->ifa_name, strlen(p->ifa_name));
277 zval *unicast, *status;
278
279 if (!iface) {
280 zval newif;
281 array_init(&newif);
282 iface = zend_hash_str_add(Z_ARR_P(return_value), p->ifa_name, strlen(p->ifa_name), &newif);
283 }
284
285 unicast = zend_hash_str_find(Z_ARR_P(iface), "unicast", sizeof("unicast") - 1);
286 if (!unicast) {
287 zval newuni;
288 array_init(&newuni);
289 unicast = zend_hash_str_add(Z_ARR_P(iface), "unicast", sizeof("unicast") - 1, &newuni);
290 }
291
292 iface_append_unicast(unicast,
293 p->ifa_flags,
294 p->ifa_addr, p->ifa_netmask,
295 (p->ifa_flags & IFF_BROADCAST) ? p->ifa_broadaddr : NULL,
296 (p->ifa_flags & IFF_POINTOPOINT) ? p->ifa_dstaddr : NULL);
297 status = zend_hash_str_find(Z_ARR_P(iface), "up", sizeof("up") - 1);
298 if (!status) {
299 add_assoc_bool(iface, "up", ((p->ifa_flags & IFF_UP) != 0));
300 }
301 }
302
303 freeifaddrs(addrs);
304#else
305 /* Should never happen as we never register the function */
307#endif
308}
309#endif
310/* }}} */
char s[4]
Definition cdf.c:77
uint32_t u
Definition cdf.c:78
DNS_STATUS status
Definition dns_win32.c:49
#define DWORD
Definition exif.c:1762
unsigned int socklen_t
Definition fastcgi.c:87
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
#define NULL
Definition gdcache.h:45
again j
PHPAPI zend_string * php_inet_ntop(const struct sockaddr *addr)
Definition net.c:50
#define PHP_FUNCTION
Definition php.h:364
#define PHPAPI
Definition php.h:71
#define php_error
Definition php.h:310
#define zend_hash_str_add(...)
Definition phpdbg.h:77
p
Definition session.c:1105
const AF_INET
const AF_INET6
#define errno
PHP_WINUTIL_API char * php_win32_error_to_msg(HRESULT error)
Definition winutil.c:25
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
Definition winutil.c:50
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
#define RETURN_FALSE
Definition zend_API.h:1058
#define ZEND_PARSE_PARAMETERS_NONE()
Definition zend_API.h:1623
#define array_init(arg)
Definition zend_API.h:537
struct _zval_struct zval
strlen(string $string)
#define snprintf
#define E_WARNING
Definition zend_errors.h:24
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define ZEND_UNREACHABLE()
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define MALLOC
#define FREE
#define Z_ARR_P(zval_p)
Definition zend_types.h:984
zval * return_value
zval * ret