xref: /PHP-7.2/main/network.c (revision 9b1950b0)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Stig Venaas <venaas@uninett.no>                              |
16    | Streams work by Wez Furlong <wez@thebrainroom.com>                   |
17    +----------------------------------------------------------------------+
18  */
19 
20 /* $Id$ */
21 
22 /*#define DEBUG_MAIN_NETWORK 1*/
23 
24 #include "php.h"
25 
26 #include <stddef.h>
27 #include <errno.h>
28 
29 
30 #ifdef PHP_WIN32
31 # include <Ws2tcpip.h>
32 # include "win32/inet.h"
33 # define O_RDONLY _O_RDONLY
34 # include "win32/param.h"
35 #else
36 #include <sys/param.h>
37 #endif
38 
39 #include <sys/types.h>
40 #if HAVE_SYS_SOCKET_H
41 #include <sys/socket.h>
42 #endif
43 
44 #ifndef _FCNTL_H
45 #include <fcntl.h>
46 #endif
47 
48 #ifdef HAVE_SYS_SELECT_H
49 #include <sys/select.h>
50 #endif
51 #if HAVE_POLL_H
52 #include <poll.h>
53 #elif HAVE_SYS_POLL_H
54 #include <sys/poll.h>
55 #endif
56 
57 
58 #ifndef PHP_WIN32
59 #include <netinet/in.h>
60 #include <netdb.h>
61 #if HAVE_ARPA_INET_H
62 #include <arpa/inet.h>
63 #endif
64 #endif
65 
66 #ifndef HAVE_INET_ATON
67 int inet_aton(const char *, struct in_addr *);
68 #endif
69 
70 #include "php_network.h"
71 
72 #if defined(PHP_WIN32) || defined(__riscos__)
73 #undef AF_UNIX
74 #endif
75 
76 #if defined(AF_UNIX)
77 #include <sys/un.h>
78 #endif
79 
80 #include "ext/standard/file.h"
81 
82 #ifdef PHP_WIN32
83 # include "win32/time.h"
84 # define SOCK_ERR INVALID_SOCKET
85 # define SOCK_CONN_ERR SOCKET_ERROR
86 # define PHP_TIMEOUT_ERROR_VALUE		WSAETIMEDOUT
87 
88 #if HAVE_IPV6
89 const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */
90 #endif
91 
92 #else
93 # define SOCK_ERR -1
94 # define SOCK_CONN_ERR -1
95 # define PHP_TIMEOUT_ERROR_VALUE		ETIMEDOUT
96 #endif
97 
98 #if HAVE_GETADDRINFO
99 #ifdef HAVE_GAI_STRERROR
100 #  define PHP_GAI_STRERROR(x) (gai_strerror(x))
101 #else
102 #  define PHP_GAI_STRERROR(x) (php_gai_strerror(x))
103 /* {{{ php_gai_strerror
104  */
php_gai_strerror(int code)105 static const char *php_gai_strerror(int code)
106 {
107         static struct {
108                 int code;
109                 const char *msg;
110         } values[] = {
111 #  ifdef EAI_ADDRFAMILY
112                 {EAI_ADDRFAMILY, "Address family for hostname not supported"},
113 #  endif
114                 {EAI_AGAIN, "Temporary failure in name resolution"},
115                 {EAI_BADFLAGS, "Bad value for ai_flags"},
116                 {EAI_FAIL, "Non-recoverable failure in name resolution"},
117                 {EAI_FAMILY, "ai_family not supported"},
118                 {EAI_MEMORY, "Memory allocation failure"},
119 #  ifdef EAI_NODATA
120                 {EAI_NODATA, "No address associated with hostname"},
121 #  endif
122                 {EAI_NONAME, "Name or service not known"},
123                 {EAI_SERVICE, "Servname not supported for ai_socktype"},
124                 {EAI_SOCKTYPE, "ai_socktype not supported"},
125                 {EAI_SYSTEM, "System error"},
126                 {0, NULL}
127         };
128         int i;
129 
130         for (i = 0; values[i].msg != NULL; i++) {
131                 if (values[i].code == code) {
132                         return (char *)values[i].msg;
133                 }
134         }
135 
136         return "Unknown error";
137 }
138 /* }}} */
139 #endif
140 #endif
141 
142 /* {{{ php_network_freeaddresses
143  */
php_network_freeaddresses(struct sockaddr ** sal)144 PHPAPI void php_network_freeaddresses(struct sockaddr **sal)
145 {
146 	struct sockaddr **sap;
147 
148 	if (sal == NULL)
149 		return;
150 	for (sap = sal; *sap != NULL; sap++)
151 		efree(*sap);
152 	efree(sal);
153 }
154 /* }}} */
155 
156 /* {{{ php_network_getaddresses
157  * Returns number of addresses, 0 for none/error
158  */
php_network_getaddresses(const char * host,int socktype,struct sockaddr *** sal,zend_string ** error_string)159 PHPAPI int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, zend_string **error_string)
160 {
161 	struct sockaddr **sap;
162 	int n;
163 #if HAVE_GETADDRINFO
164 # if HAVE_IPV6
165 	static int ipv6_borked = -1; /* the way this is used *is* thread safe */
166 # endif
167 	struct addrinfo hints, *res, *sai;
168 #else
169 	struct hostent *host_info;
170 	struct in_addr in;
171 #endif
172 
173 	if (host == NULL) {
174 		return 0;
175 	}
176 #if HAVE_GETADDRINFO
177 	memset(&hints, '\0', sizeof(hints));
178 
179 	hints.ai_family = AF_INET; /* default to regular inet (see below) */
180 	hints.ai_socktype = socktype;
181 
182 # if HAVE_IPV6
183 	/* probe for a working IPv6 stack; even if detected as having v6 at compile
184 	 * time, at runtime some stacks are slow to resolve or have other issues
185 	 * if they are not correctly configured.
186 	 * static variable use is safe here since simple store or fetch operations
187 	 * are atomic and because the actual probe process is not in danger of
188 	 * collisions or race conditions. */
189 	if (ipv6_borked == -1) {
190 		int s;
191 
192 		s = socket(PF_INET6, SOCK_DGRAM, 0);
193 		if (s == SOCK_ERR) {
194 			ipv6_borked = 1;
195 		} else {
196 			ipv6_borked = 0;
197 			closesocket(s);
198 		}
199 	}
200 	hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC;
201 # endif
202 
203 	if ((n = getaddrinfo(host, NULL, &hints, &res))) {
204 		if (error_string) {
205 			*error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
206 			php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
207 		} else {
208 			php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
209 		}
210 		return 0;
211 	} else if (res == NULL) {
212 		if (error_string) {
213 			*error_string = strpprintf(0, "php_network_getaddresses: getaddrinfo failed (null result pointer) errno=%d", errno);
214 			php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
215 		} else {
216 			php_error_docref(NULL, E_WARNING, "php_network_getaddresses: getaddrinfo failed (null result pointer)");
217 		}
218 		return 0;
219 	}
220 
221 	sai = res;
222 	for (n = 1; (sai = sai->ai_next) != NULL; n++)
223 		;
224 
225 	*sal = safe_emalloc((n + 1), sizeof(*sal), 0);
226 	sai = res;
227 	sap = *sal;
228 
229 	do {
230 		*sap = emalloc(sai->ai_addrlen);
231 		memcpy(*sap, sai->ai_addr, sai->ai_addrlen);
232 		sap++;
233 	} while ((sai = sai->ai_next) != NULL);
234 
235 	freeaddrinfo(res);
236 #else
237 	if (!inet_aton(host, &in)) {
238 		if(strlen(host) > MAXFQDNLEN) {
239 			host_info = NULL;
240 			errno = E2BIG;
241 		} else {
242 			host_info = php_network_gethostbyname(host);
243 		}
244 		if (host_info == NULL) {
245 			if (error_string) {
246 				*error_string = strpprintf(0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
247 				php_error_docref(NULL, E_WARNING, "%s", ZSTR_VAL(*error_string));
248 			} else {
249 				php_error_docref(NULL, E_WARNING, "php_network_getaddresses: gethostbyname failed");
250 			}
251 			return 0;
252 		}
253 		in = *((struct in_addr *) host_info->h_addr);
254 	}
255 
256 	*sal = safe_emalloc(2, sizeof(*sal), 0);
257 	sap = *sal;
258 	*sap = emalloc(sizeof(struct sockaddr_in));
259 	(*sap)->sa_family = AF_INET;
260 	((struct sockaddr_in *)*sap)->sin_addr = in;
261 	sap++;
262 	n = 1;
263 #endif
264 
265 	*sap = NULL;
266 	return n;
267 }
268 /* }}} */
269 
270 #ifndef O_NONBLOCK
271 #define O_NONBLOCK O_NDELAY
272 #endif
273 
274 #if !defined(__BEOS__)
275 # define HAVE_NON_BLOCKING_CONNECT 1
276 # ifdef PHP_WIN32
277 typedef u_long php_non_blocking_flags_t;
278 #  define SET_SOCKET_BLOCKING_MODE(sock, save) \
279      save = TRUE; ioctlsocket(sock, FIONBIO, &save)
280 #  define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
281 	 ioctlsocket(sock, FIONBIO, &save)
282 # else
283 typedef int php_non_blocking_flags_t;
284 #  define SET_SOCKET_BLOCKING_MODE(sock, save) \
285 	 save = fcntl(sock, F_GETFL, 0); \
286 	 fcntl(sock, F_SETFL, save | O_NONBLOCK)
287 #  define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
288 	 fcntl(sock, F_SETFL, save)
289 # endif
290 #endif
291 
292 /* Connect to a socket using an interruptible connect with optional timeout.
293  * Optionally, the connect can be made asynchronously, which will implicitly
294  * enable non-blocking mode on the socket.
295  * */
296 /* {{{ php_network_connect_socket */
php_network_connect_socket(php_socket_t sockfd,const struct sockaddr * addr,socklen_t addrlen,int asynchronous,struct timeval * timeout,zend_string ** error_string,int * error_code)297 PHPAPI int php_network_connect_socket(php_socket_t sockfd,
298 		const struct sockaddr *addr,
299 		socklen_t addrlen,
300 		int asynchronous,
301 		struct timeval *timeout,
302 		zend_string **error_string,
303 		int *error_code)
304 {
305 #if HAVE_NON_BLOCKING_CONNECT
306 	php_non_blocking_flags_t orig_flags;
307 	int n;
308 	int error = 0;
309 	socklen_t len;
310 	int ret = 0;
311 
312 	SET_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
313 
314 	if ((n = connect(sockfd, addr, addrlen)) != 0) {
315 		error = php_socket_errno();
316 
317 		if (error_code) {
318 			*error_code = error;
319 		}
320 
321 		if (error != EINPROGRESS) {
322 			if (error_string) {
323 				*error_string = php_socket_error_str(error);
324 			}
325 
326 			return -1;
327 		}
328 		if (asynchronous && error == EINPROGRESS) {
329 			/* this is fine by us */
330 			return 0;
331 		}
332 	}
333 
334 	if (n == 0) {
335 		goto ok;
336 	}
337 # ifdef PHP_WIN32
338 	/* The documentation for connect() says in case of non-blocking connections
339 	 * the select function reports success in the writefds set and failure in
340 	 * the exceptfds set. Indeed, using PHP_POLLREADABLE results in select
341 	 * failing only due to the timeout and not immediately as would be
342 	 * expected when a connection is actively refused. This way,
343 	 * php_pollfd_for will return a mask with POLLOUT if the connection
344 	 * is successful and with POLLPRI otherwise. */
345 	if ((n = php_pollfd_for(sockfd, POLLOUT|POLLPRI, timeout)) == 0) {
346 #else
347 	if ((n = php_pollfd_for(sockfd, PHP_POLLREADABLE|POLLOUT, timeout)) == 0) {
348 #endif
349 		error = PHP_TIMEOUT_ERROR_VALUE;
350 	}
351 
352 	if (n > 0) {
353 		len = sizeof(error);
354 		/*
355 		   BSD-derived systems set errno correctly
356 		   Solaris returns -1 from getsockopt in case of error
357 		   */
358 		if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) != 0) {
359 			ret = -1;
360 		}
361 	} else {
362 		/* whoops: sockfd has disappeared */
363 		ret = -1;
364 	}
365 
366 ok:
367 	if (!asynchronous) {
368 		/* back to blocking mode */
369 		RESTORE_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
370 	}
371 
372 	if (error_code) {
373 		*error_code = error;
374 	}
375 
376 	if (error) {
377 		ret = -1;
378 		if (error_string) {
379 			*error_string = php_socket_error_str(error);
380 		}
381 	}
382 	return ret;
383 #else
384 	if (asynchronous) {
385 		php_error_docref(NULL, E_WARNING, "Asynchronous connect() not supported on this platform");
386 	}
387 	return (connect(sockfd, addr, addrlen) == 0) ? 0 : -1;
388 #endif
389 }
390 /* }}} */
391 
392 /* {{{ sub_times */
393 static inline void sub_times(struct timeval a, struct timeval b, struct timeval *result)
394 {
395 	result->tv_usec = a.tv_usec - b.tv_usec;
396 	if (result->tv_usec < 0L) {
397 		a.tv_sec--;
398 		result->tv_usec += 1000000L;
399 	}
400 	result->tv_sec = a.tv_sec - b.tv_sec;
401 	if (result->tv_sec < 0L) {
402 		result->tv_sec++;
403 		result->tv_usec -= 1000000L;
404 	}
405 }
406 /* }}} */
407 
408 /* Bind to a local IP address.
409  * Returns the bound socket, or -1 on failure.
410  * */
411 /* {{{ php_network_bind_socket_to_local_addr */
412 php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port,
413 		int socktype, long sockopts, zend_string **error_string, int *error_code
414 		)
415 {
416 	int num_addrs, n, err = 0;
417 	php_socket_t sock;
418 	struct sockaddr **sal, **psal, *sa;
419 	socklen_t socklen;
420 	int sockoptval = 1;
421 
422 	num_addrs = php_network_getaddresses(host, socktype, &psal, error_string);
423 
424 	if (num_addrs == 0) {
425 		/* could not resolve address(es) */
426 		return -1;
427 	}
428 
429 	for (sal = psal; *sal != NULL; sal++) {
430 		sa = *sal;
431 
432 		/* create a socket for this address */
433 		sock = socket(sa->sa_family, socktype, 0);
434 
435 		if (sock == SOCK_ERR) {
436 			continue;
437 		}
438 
439 		switch (sa->sa_family) {
440 #if HAVE_GETADDRINFO && HAVE_IPV6
441 			case AF_INET6:
442 				((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
443 				((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
444 				socklen = sizeof(struct sockaddr_in6);
445 				break;
446 #endif
447 			case AF_INET:
448 				((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
449 				((struct sockaddr_in *)sa)->sin_port = htons(port);
450 				socklen = sizeof(struct sockaddr_in);
451 				break;
452 			default:
453 				/* Unknown family */
454 				socklen = 0;
455 				sa = NULL;
456 		}
457 
458 		if (sa) {
459 			/* attempt to bind */
460 
461 #ifdef SO_REUSEADDR
462 			setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(sockoptval));
463 #endif
464 #ifdef IPV6_V6ONLY
465 			if (sockopts & STREAM_SOCKOP_IPV6_V6ONLY) {
466 				int ipv6_val = !!(sockopts & STREAM_SOCKOP_IPV6_V6ONLY_ENABLED);
467 				setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6_val, sizeof(sockoptval));
468 			}
469 #endif
470 #ifdef SO_REUSEPORT
471 			if (sockopts & STREAM_SOCKOP_SO_REUSEPORT) {
472 				setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char*)&sockoptval, sizeof(sockoptval));
473 			}
474 #endif
475 #ifdef SO_BROADCAST
476 			if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
477 				setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&sockoptval, sizeof(sockoptval));
478 			}
479 #endif
480 #ifdef TCP_NODELAY
481 			if (sockopts & STREAM_SOCKOP_TCP_NODELAY) {
482 				setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&sockoptval, sizeof(sockoptval));
483 			}
484 #endif
485 
486 			n = bind(sock, sa, socklen);
487 
488 			if (n != SOCK_CONN_ERR) {
489 				goto bound;
490 			}
491 
492 			err = php_socket_errno();
493 		}
494 
495 		closesocket(sock);
496 	}
497 	sock = -1;
498 
499 	if (error_code) {
500 		*error_code = err;
501 	}
502 	if (error_string) {
503 		*error_string = php_socket_error_str(err);
504 	}
505 
506 bound:
507 
508 	php_network_freeaddresses(psal);
509 
510 	return sock;
511 
512 }
513 /* }}} */
514 
515 PHPAPI int php_network_parse_network_address_with_port(const char *addr, zend_long addrlen, struct sockaddr *sa, socklen_t *sl)
516 {
517 	char *colon;
518 	char *tmp;
519 	int ret = FAILURE;
520 	short port;
521 	struct sockaddr_in *in4 = (struct sockaddr_in*)sa;
522 	struct sockaddr **psal;
523 	int n;
524 	zend_string *errstr = NULL;
525 #if HAVE_IPV6
526 	struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
527 #endif
528 
529 	memset(sa, 0, sizeof(struct sockaddr));
530 
531 	if (*addr == '[') {
532 		colon = memchr(addr + 1, ']', addrlen-1);
533 		if (!colon || colon[1] != ':') {
534 			return FAILURE;
535 		}
536 		port = atoi(colon + 2);
537 		addr++;
538 	} else {
539 		colon = memchr(addr, ':', addrlen);
540 		if (!colon) {
541 			return FAILURE;
542 		}
543 		port = atoi(colon + 1);
544 	}
545 
546 	tmp = estrndup(addr, colon - addr);
547 
548 	/* first, try interpreting the address as a numeric address */
549 
550 #if HAVE_IPV6 && HAVE_INET_PTON
551 	if (inet_pton(AF_INET6, tmp, &in6->sin6_addr) > 0) {
552 		in6->sin6_port = htons(port);
553 		in6->sin6_family = AF_INET6;
554 		*sl = sizeof(struct sockaddr_in6);
555 		ret = SUCCESS;
556 		goto out;
557 	}
558 #endif
559 	if (inet_aton(tmp, &in4->sin_addr) > 0) {
560 		in4->sin_port = htons(port);
561 		in4->sin_family = AF_INET;
562 		*sl = sizeof(struct sockaddr_in);
563 		ret = SUCCESS;
564 		goto out;
565 	}
566 
567 	/* looks like we'll need to resolve it */
568 	n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr);
569 
570 	if (n == 0) {
571 		if (errstr) {
572 			php_error_docref(NULL, E_WARNING, "Failed to resolve `%s': %s", tmp, ZSTR_VAL(errstr));
573 			zend_string_release(errstr);
574 		}
575 		goto out;
576 	}
577 
578 	/* copy the details from the first item */
579 	switch ((*psal)->sa_family) {
580 #if HAVE_GETADDRINFO && HAVE_IPV6
581 		case AF_INET6:
582 			*in6 = **(struct sockaddr_in6**)psal;
583 			in6->sin6_port = htons(port);
584 			*sl = sizeof(struct sockaddr_in6);
585 			ret = SUCCESS;
586 			break;
587 #endif
588 		case AF_INET:
589 			*in4 = **(struct sockaddr_in**)psal;
590 			in4->sin_port = htons(port);
591 			*sl = sizeof(struct sockaddr_in);
592 			ret = SUCCESS;
593 			break;
594 	}
595 
596 	php_network_freeaddresses(psal);
597 
598 out:
599 	efree(tmp);
600 	return ret;
601 }
602 
603 
604 PHPAPI void php_network_populate_name_from_sockaddr(
605 		/* input address */
606 		struct sockaddr *sa, socklen_t sl,
607 		/* output readable address */
608 		zend_string **textaddr,
609 		/* output address */
610 		struct sockaddr **addr,
611 		socklen_t *addrlen
612 		)
613 {
614 	if (addr) {
615 		*addr = emalloc(sl);
616 		memcpy(*addr, sa, sl);
617 		*addrlen = sl;
618 	}
619 
620 	if (textaddr) {
621 #if HAVE_IPV6 && HAVE_INET_NTOP
622 		char abuf[256];
623 #endif
624 		char *buf = NULL;
625 
626 		switch (sa->sa_family) {
627 			case AF_INET:
628 				/* generally not thread safe, but it *is* thread safe under win32 */
629 				buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr);
630 				if (buf) {
631 					*textaddr = strpprintf(0, "%s:%d",
632 						buf, ntohs(((struct sockaddr_in*)sa)->sin_port));
633 				}
634 
635 				break;
636 
637 #if HAVE_IPV6 && HAVE_INET_NTOP
638 			case AF_INET6:
639 				buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
640 				if (buf) {
641 					*textaddr = strpprintf(0, "%s:%d",
642 						buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port));
643 				}
644 
645 				break;
646 #endif
647 #ifdef AF_UNIX
648 			case AF_UNIX:
649 				{
650 					struct sockaddr_un *ua = (struct sockaddr_un*)sa;
651 
652 					if (ua->sun_path[0] == '\0') {
653 						/* abstract name */
654 						int len = sl - sizeof(sa_family_t);
655 						*textaddr = zend_string_init((char*)ua->sun_path, len, 0);
656 					} else {
657 						int len = strlen(ua->sun_path);
658 						*textaddr = zend_string_init((char*)ua->sun_path, len, 0);
659 					}
660 				}
661 				break;
662 #endif
663 
664 		}
665 
666 	}
667 }
668 
669 PHPAPI int php_network_get_peer_name(php_socket_t sock,
670 		zend_string **textaddr,
671 		struct sockaddr **addr,
672 		socklen_t *addrlen
673 		)
674 {
675 	php_sockaddr_storage sa;
676 	socklen_t sl = sizeof(sa);
677 	memset(&sa, 0, sizeof(sa));
678 
679 	if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
680 		php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
681 				textaddr,
682 				addr, addrlen
683 				);
684 		return 0;
685 	}
686 	return -1;
687 }
688 
689 PHPAPI int php_network_get_sock_name(php_socket_t sock,
690 		zend_string **textaddr,
691 		struct sockaddr **addr,
692 		socklen_t *addrlen
693 		)
694 {
695 	php_sockaddr_storage sa;
696 	socklen_t sl = sizeof(sa);
697 	memset(&sa, 0, sizeof(sa));
698 
699 	if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
700 		php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
701 				textaddr,
702 				addr, addrlen
703 				);
704 		return 0;
705 	}
706 	return -1;
707 
708 }
709 
710 
711 /* Accept a client connection from a server socket,
712  * using an optional timeout.
713  * Returns the peer address in addr/addrlen (it will emalloc
714  * these, so be sure to efree the result).
715  * If you specify textaddr, a text-printable
716  * version of the address will be emalloc'd and returned.
717  * */
718 
719 /* {{{ php_network_accept_incoming */
720 PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
721 		zend_string **textaddr,
722 		struct sockaddr **addr,
723 		socklen_t *addrlen,
724 		struct timeval *timeout,
725 		zend_string **error_string,
726 		int *error_code,
727 		int tcp_nodelay
728 		)
729 {
730 	php_socket_t clisock = -1;
731 	int error = 0, n;
732 	php_sockaddr_storage sa;
733 	socklen_t sl;
734 
735 	n = php_pollfd_for(srvsock, PHP_POLLREADABLE, timeout);
736 
737 	if (n == 0) {
738 		error = PHP_TIMEOUT_ERROR_VALUE;
739 	} else if (n == -1) {
740 		error = php_socket_errno();
741 	} else {
742 		sl = sizeof(sa);
743 
744 		clisock = accept(srvsock, (struct sockaddr*)&sa, &sl);
745 
746 		if (clisock != SOCK_ERR) {
747 			php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
748 					textaddr,
749 					addr, addrlen
750 					);
751 			if (tcp_nodelay) {
752 #ifdef TCP_NODELAY
753 				setsockopt(clisock, IPPROTO_TCP, TCP_NODELAY, (char*)&tcp_nodelay, sizeof(tcp_nodelay));
754 #endif
755 			}
756 		} else {
757 			error = php_socket_errno();
758 		}
759 	}
760 
761 	if (error_code) {
762 		*error_code = error;
763 	}
764 	if (error_string) {
765 		*error_string = php_socket_error_str(error);
766 	}
767 
768 	return clisock;
769 }
770 /* }}} */
771 
772 
773 /* Connect to a remote host using an interruptible connect with optional timeout.
774  * Optionally, the connect can be made asynchronously, which will implicitly
775  * enable non-blocking mode on the socket.
776  * Returns the connected (or connecting) socket, or -1 on failure.
777  * */
778 
779 /* {{{ php_network_connect_socket_to_host */
780 php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port,
781 		int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string,
782 		int *error_code, char *bindto, unsigned short bindport, long sockopts
783 		)
784 {
785 	int num_addrs, n, fatal = 0;
786 	php_socket_t sock;
787 	struct sockaddr **sal, **psal, *sa;
788 	struct timeval working_timeout;
789 	socklen_t socklen;
790 #if HAVE_GETTIMEOFDAY
791 	struct timeval limit_time, time_now;
792 #endif
793 
794 	num_addrs = php_network_getaddresses(host, socktype, &psal, error_string);
795 
796 	if (num_addrs == 0) {
797 		/* could not resolve address(es) */
798 		return -1;
799 	}
800 
801 	if (timeout) {
802 		memcpy(&working_timeout, timeout, sizeof(working_timeout));
803 #if HAVE_GETTIMEOFDAY
804 		gettimeofday(&limit_time, NULL);
805 		limit_time.tv_sec += working_timeout.tv_sec;
806 		limit_time.tv_usec += working_timeout.tv_usec;
807 		if (limit_time.tv_usec >= 1000000) {
808 			limit_time.tv_usec -= 1000000;
809 			limit_time.tv_sec++;
810 		}
811 #endif
812 	}
813 
814 	for (sal = psal; !fatal && *sal != NULL; sal++) {
815 		sa = *sal;
816 
817 		/* create a socket for this address */
818 		sock = socket(sa->sa_family, socktype, 0);
819 
820 		if (sock == SOCK_ERR) {
821 			continue;
822 		}
823 
824 		switch (sa->sa_family) {
825 #if HAVE_GETADDRINFO && HAVE_IPV6
826 			case AF_INET6:
827 				if (!bindto || strchr(bindto, ':')) {
828 					((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
829 					((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
830 					socklen = sizeof(struct sockaddr_in6);
831 				} else {
832 					socklen = 0;
833 					sa = NULL;
834 				}
835 				break;
836 #endif
837 			case AF_INET:
838 				((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
839 				((struct sockaddr_in *)sa)->sin_port = htons(port);
840 				socklen = sizeof(struct sockaddr_in);
841 				break;
842 			default:
843 				/* Unknown family */
844 				socklen = 0;
845 				sa = NULL;
846 		}
847 
848 		if (sa) {
849 			/* make a connection attempt */
850 
851 			if (bindto) {
852 				struct sockaddr *local_address = NULL;
853 				int local_address_len = 0;
854 
855 				if (sa->sa_family == AF_INET) {
856 					if (strchr(bindto,':')) {
857 						goto skip_bind;
858 					}
859 					struct sockaddr_in *in4 = emalloc(sizeof(struct sockaddr_in));
860 
861 					local_address = (struct sockaddr*)in4;
862 					local_address_len = sizeof(struct sockaddr_in);
863 
864 					in4->sin_family = sa->sa_family;
865 					in4->sin_port = htons(bindport);
866 					if (!inet_aton(bindto, &in4->sin_addr)) {
867 						php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
868 						goto skip_bind;
869 					}
870 					memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
871 				}
872 #if HAVE_IPV6 && HAVE_INET_PTON
873 				 else { /* IPV6 */
874 					struct sockaddr_in6 *in6 = emalloc(sizeof(struct sockaddr_in6));
875 
876 					local_address = (struct sockaddr*)in6;
877 					local_address_len = sizeof(struct sockaddr_in6);
878 
879 					in6->sin6_family = sa->sa_family;
880 					in6->sin6_port = htons(bindport);
881 					if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
882 						php_error_docref(NULL, E_WARNING, "Invalid IP Address: %s", bindto);
883 						goto skip_bind;
884 					}
885 				}
886 #endif
887 
888 				if (!local_address || bind(sock, local_address, local_address_len)) {
889 					php_error_docref(NULL, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
890 				}
891 skip_bind:
892 				if (local_address) {
893 					efree(local_address);
894 				}
895 			}
896 			/* free error string received during previous iteration (if any) */
897 			if (error_string && *error_string) {
898 				zend_string_release(*error_string);
899 				*error_string = NULL;
900 			}
901 
902 #ifdef SO_BROADCAST
903 			{
904 				int val = 1;
905 				if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
906 					setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof(val));
907 				}
908 			}
909 #endif
910 
911 #ifdef TCP_NODELAY
912 			{
913 				int val = 1;
914 				if (sockopts & STREAM_SOCKOP_TCP_NODELAY) {
915 					setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val));
916 				}
917 			}
918 #endif
919 			n = php_network_connect_socket(sock, sa, socklen, asynchronous,
920 					timeout ? &working_timeout : NULL,
921 					error_string, error_code);
922 
923 			if (n != -1) {
924 				goto connected;
925 			}
926 
927 			/* adjust timeout for next attempt */
928 #if HAVE_GETTIMEOFDAY
929 			if (timeout) {
930 				gettimeofday(&time_now, NULL);
931 
932 				if (timercmp(&time_now, &limit_time, >=)) {
933 					/* time limit expired; don't attempt any further connections */
934 					fatal = 1;
935 				} else {
936 					/* work out remaining time */
937 					sub_times(limit_time, time_now, &working_timeout);
938 				}
939 			}
940 #else
941 			if (error_code && *error_code == PHP_TIMEOUT_ERROR_VALUE) {
942 				/* Don't even bother trying to connect to the next alternative;
943 				 * we have no way to determine how long we have already taken
944 				 * and it is quite likely that the next attempt will fail too. */
945 				fatal = 1;
946 			} else {
947 				/* re-use the same initial timeout.
948 				 * Not the best thing, but in practice it should be good-enough */
949 				if (timeout) {
950 					memcpy(&working_timeout, timeout, sizeof(working_timeout));
951 				}
952 			}
953 #endif
954 		}
955 
956 		closesocket(sock);
957 	}
958 	sock = -1;
959 
960 connected:
961 
962 	php_network_freeaddresses(psal);
963 
964 	return sock;
965 }
966 /* }}} */
967 
968 /* {{{ php_any_addr
969  * Fills the any (wildcard) address into php_sockaddr_storage
970  */
971 PHPAPI void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
972 {
973 	memset(addr, 0, sizeof(php_sockaddr_storage));
974 	switch (family) {
975 #if HAVE_IPV6
976 	case AF_INET6: {
977 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
978 		sin6->sin6_family = AF_INET6;
979 		sin6->sin6_port = htons(port);
980 		sin6->sin6_addr = in6addr_any;
981 		break;
982 	}
983 #endif
984 	case AF_INET: {
985 		struct sockaddr_in *sin = (struct sockaddr_in *) addr;
986 		sin->sin_family = AF_INET;
987 		sin->sin_port = htons(port);
988 		sin->sin_addr.s_addr = htonl(INADDR_ANY);
989 		break;
990 	}
991 	}
992 }
993 /* }}} */
994 
995 /* {{{ php_sockaddr_size
996  * Returns the size of struct sockaddr_xx for the family
997  */
998 PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
999 {
1000 	switch (((struct sockaddr *)addr)->sa_family) {
1001 	case AF_INET:
1002 		return sizeof(struct sockaddr_in);
1003 #if HAVE_IPV6
1004 	case AF_INET6:
1005 		return sizeof(struct sockaddr_in6);
1006 #endif
1007 #ifdef AF_UNIX
1008 	case AF_UNIX:
1009 		return sizeof(struct sockaddr_un);
1010 #endif
1011 	default:
1012 		return 0;
1013 	}
1014 }
1015 /* }}} */
1016 
1017 /* Given a socket error code, if buf == NULL:
1018  *   emallocs storage for the error message and returns
1019  * else
1020  *   sprintf message into provided buffer and returns buf
1021  */
1022 /* {{{ php_socket_strerror */
1023 PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
1024 {
1025 #ifndef PHP_WIN32
1026 	char *errstr;
1027 
1028 	errstr = strerror(err);
1029 	if (buf == NULL) {
1030 		buf = estrdup(errstr);
1031 	} else {
1032 		strncpy(buf, errstr, bufsize);
1033 		buf[bufsize?(bufsize-1):0] = 0;
1034 	}
1035 	return buf;
1036 #else
1037 	char *sysbuf;
1038 	int free_it = 1;
1039 
1040 	if (!FormatMessage(
1041 				FORMAT_MESSAGE_ALLOCATE_BUFFER |
1042 				FORMAT_MESSAGE_FROM_SYSTEM |
1043 				FORMAT_MESSAGE_IGNORE_INSERTS,
1044 				NULL,
1045 				err,
1046 				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1047 				(LPTSTR)&sysbuf,
1048 				0,
1049 				NULL)) {
1050 		free_it = 0;
1051 		sysbuf = "Unknown Error";
1052 	}
1053 
1054 	if (buf == NULL) {
1055 		buf = estrdup(sysbuf);
1056 	} else {
1057 		strncpy(buf, sysbuf, bufsize);
1058 		buf[bufsize?(bufsize-1):0] = 0;
1059 	}
1060 
1061 	if (free_it) {
1062 		LocalFree(sysbuf);
1063 	}
1064 
1065 	return buf;
1066 #endif
1067 }
1068 /* }}} */
1069 
1070 /* {{{ php_socket_error_str */
1071 PHPAPI zend_string *php_socket_error_str(long err)
1072 {
1073 #ifndef PHP_WIN32
1074 	char *errstr;
1075 
1076 	errstr = strerror(err);
1077 	return zend_string_init(errstr, strlen(errstr), 0);
1078 #else
1079 	zend_string *ret;
1080 	char *sysbuf;
1081 	int free_it = 1;
1082 
1083 	if (!FormatMessage(
1084 				FORMAT_MESSAGE_ALLOCATE_BUFFER |
1085 				FORMAT_MESSAGE_FROM_SYSTEM |
1086 				FORMAT_MESSAGE_IGNORE_INSERTS,
1087 				NULL,
1088 				err,
1089 				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1090 				(LPTSTR)&sysbuf,
1091 				0,
1092 				NULL)) {
1093 		free_it = 0;
1094 		sysbuf = "Unknown Error";
1095 	}
1096 
1097 	ret = zend_string_init(sysbuf, strlen(sysbuf), 0);
1098 
1099 	if (free_it) {
1100 		LocalFree(sysbuf);
1101 	}
1102 
1103 	return ret;
1104 #endif
1105 }
1106 /* }}} */
1107 
1108 /* deprecated */
1109 PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC)
1110 {
1111 	php_stream *stream;
1112 	php_netstream_data_t *sock;
1113 
1114 	sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0);
1115 	memset(sock, 0, sizeof(php_netstream_data_t));
1116 
1117 	sock->is_blocked = 1;
1118 	sock->timeout.tv_sec = FG(default_socket_timeout);
1119 	sock->timeout.tv_usec = 0;
1120 	sock->socket = socket;
1121 
1122 	stream = php_stream_alloc_rel(&php_stream_generic_socket_ops, sock, persistent_id, "r+");
1123 
1124 	if (stream == NULL) {
1125 		pefree(sock, persistent_id ? 1 : 0);
1126 	} else {
1127 		stream->flags |= PHP_STREAM_FLAG_AVOID_BLOCKING;
1128 	}
1129 
1130 	return stream;
1131 }
1132 
1133 PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short port,
1134 		int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC)
1135 {
1136 	char *res;
1137 	zend_long reslen;
1138 	php_stream *stream;
1139 
1140 	reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);
1141 
1142 	stream = php_stream_xport_create(res, reslen, REPORT_ERRORS,
1143 			STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, persistent_id, timeout, NULL, NULL, NULL);
1144 
1145 	efree(res);
1146 
1147 	return stream;
1148 }
1149 
1150 PHPAPI int php_set_sock_blocking(php_socket_t socketd, int block)
1151 {
1152 	int ret = SUCCESS;
1153 
1154 #ifdef PHP_WIN32
1155 	u_long flags;
1156 
1157 	/* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */
1158 	flags = !block;
1159 	if (ioctlsocket(socketd, FIONBIO, &flags) == SOCKET_ERROR) {
1160 		ret = FAILURE;
1161 	}
1162 #else
1163 	int myflag = 0;
1164 	int flags = fcntl(socketd, F_GETFL);
1165 
1166 #ifdef O_NONBLOCK
1167 	myflag = O_NONBLOCK; /* POSIX version */
1168 #elif defined(O_NDELAY)
1169 	myflag = O_NDELAY;   /* old non-POSIX version */
1170 #endif
1171 	if (!block) {
1172 		flags |= myflag;
1173 	} else {
1174 		flags &= ~myflag;
1175 	}
1176 	if (fcntl(socketd, F_SETFL, flags) == -1) {
1177 		ret = FAILURE;
1178 	}
1179 #endif
1180 	return ret;
1181 }
1182 
1183 PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
1184 {
1185 
1186 #ifdef PHP_WIN32
1187 	php_error_docref(NULL, E_WARNING,
1188 		"PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
1189 		"If this binary is from an official www.php.net package, file a bug report\n"
1190 		"at http://bugs.php.net, including the following information:\n"
1191 		"FD_SETSIZE=%d, but you are using %d.\n"
1192 		" --enable-fd-setsize=%d is recommended, but you may want to set it\n"
1193 		"to match to maximum number of sockets each script will work with at\n"
1194 		"one time, in order to avoid seeing this error again at a later date.",
1195 		FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
1196 #else
1197 	php_error_docref(NULL, E_WARNING,
1198 		"You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
1199 		"It is set to %d, but you have descriptors numbered at least as high as %d.\n"
1200 		" --enable-fd-setsize=%d is recommended, but you may want to set it\n"
1201 		"to equal the maximum number of open files supported by your system,\n"
1202 		"in order to avoid seeing this error again at a later date.",
1203 		FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023);
1204 #endif
1205 }
1206 
1207 #if defined(PHP_USE_POLL_2_EMULATION)
1208 
1209 /* emulate poll(2) using select(2), safely. */
1210 
1211 PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
1212 {
1213 	fd_set rset, wset, eset;
1214 	php_socket_t max_fd = SOCK_ERR;
1215 	unsigned int i;
1216 	int n;
1217 	struct timeval tv;
1218 
1219 	/* check the highest numbered descriptor */
1220 	for (i = 0; i < nfds; i++) {
1221 		if (ufds[i].fd > max_fd)
1222 			max_fd = ufds[i].fd;
1223 	}
1224 
1225 	PHP_SAFE_MAX_FD(max_fd, nfds + 1);
1226 
1227 	FD_ZERO(&rset);
1228 	FD_ZERO(&wset);
1229 	FD_ZERO(&eset);
1230 
1231 	for (i = 0; i < nfds; i++) {
1232 		if (ufds[i].events & PHP_POLLREADABLE) {
1233 			PHP_SAFE_FD_SET(ufds[i].fd, &rset);
1234 		}
1235 		if (ufds[i].events & POLLOUT) {
1236 			PHP_SAFE_FD_SET(ufds[i].fd, &wset);
1237 		}
1238 		if (ufds[i].events & POLLPRI) {
1239 			PHP_SAFE_FD_SET(ufds[i].fd, &eset);
1240 		}
1241 	}
1242 
1243 	if (timeout >= 0) {
1244 		tv.tv_sec = timeout / 1000;
1245 		tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
1246 	}
1247 /* Reseting/initializing */
1248 #ifdef PHP_WIN32
1249 	WSASetLastError(0);
1250 #else
1251 	errno = 0;
1252 #endif
1253 	n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &tv : NULL);
1254 
1255 	if (n >= 0) {
1256 		for (i = 0; i < nfds; i++) {
1257 			ufds[i].revents = 0;
1258 
1259 			if (PHP_SAFE_FD_ISSET(ufds[i].fd, &rset)) {
1260 				/* could be POLLERR or POLLHUP but can't tell without probing */
1261 				ufds[i].revents |= POLLIN;
1262 			}
1263 			if (PHP_SAFE_FD_ISSET(ufds[i].fd, &wset)) {
1264 				ufds[i].revents |= POLLOUT;
1265 			}
1266 			if (PHP_SAFE_FD_ISSET(ufds[i].fd, &eset)) {
1267 				ufds[i].revents |= POLLPRI;
1268 			}
1269 		}
1270 	}
1271 	return n;
1272 }
1273 #endif
1274 
1275 #if defined(HAVE_GETHOSTBYNAME_R)
1276 #ifdef HAVE_FUNC_GETHOSTBYNAME_R_6
1277 struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
1278 {
1279 	struct hostent *hp;
1280 	int herr,res;
1281 
1282 	if (*hstbuflen == 0) {
1283 		*hstbuflen = 1024;
1284 		*tmphstbuf = (char *)malloc (*hstbuflen);
1285 	}
1286 
1287 	while (( res =
1288 		gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&hp,&herr))
1289 		&& (errno == ERANGE)) {
1290 		/* Enlarge the buffer. */
1291 		*hstbuflen *= 2;
1292 		*tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
1293 	}
1294 
1295 	if (res != SUCCESS) {
1296 		return NULL;
1297 	}
1298 
1299 	return hp;
1300 }
1301 #endif
1302 #ifdef HAVE_FUNC_GETHOSTBYNAME_R_5
1303 struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
1304 {
1305 	struct hostent *hp;
1306 	int herr;
1307 
1308 	if (*hstbuflen == 0) {
1309 		*hstbuflen = 1024;
1310 		*tmphstbuf = (char *)malloc (*hstbuflen);
1311 	}
1312 
1313 	while ((NULL == ( hp =
1314 		gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&herr)))
1315 		&& (errno == ERANGE)) {
1316 		/* Enlarge the buffer. */
1317 		*hstbuflen *= 2;
1318 		*tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
1319 	}
1320 	return hp;
1321 }
1322 #endif
1323 #ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
1324 struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
1325 {
1326 	if (*hstbuflen == 0) {
1327 		*hstbuflen = sizeof(struct hostent_data);
1328 		*tmphstbuf = (char *)malloc (*hstbuflen);
1329 	} else {
1330 		if (*hstbuflen < sizeof(struct hostent_data)) {
1331 			*hstbuflen = sizeof(struct hostent_data);
1332 			*tmphstbuf = (char *)realloc(*tmphstbuf, *hstbuflen);
1333 		}
1334 	}
1335 	memset((void *)(*tmphstbuf),0,*hstbuflen);
1336 
1337 	if (SUCCESS != gethostbyname_r(host,hostbuf,(struct hostent_data *)*tmphstbuf)) {
1338 		return NULL;
1339 	}
1340 
1341 	return hostbuf;
1342 }
1343 #endif
1344 #endif
1345 
1346 PHPAPI struct hostent*	php_network_gethostbyname(char *name) {
1347 #if !defined(HAVE_GETHOSTBYNAME_R)
1348 	return gethostbyname(name);
1349 #else
1350 	if (FG(tmp_host_buf)) {
1351 		free(FG(tmp_host_buf));
1352 	}
1353 
1354 	FG(tmp_host_buf) = NULL;
1355 	FG(tmp_host_buf_len) = 0;
1356 
1357 	memset(&FG(tmp_host_info), 0, sizeof(struct hostent));
1358 
1359 	return gethostname_re(name, &FG(tmp_host_info), &FG(tmp_host_buf), &FG(tmp_host_buf_len));
1360 #endif
1361 }
1362 
1363 /*
1364  * Local variables:
1365  * tab-width: 8
1366  * c-basic-offset: 8
1367  * End:
1368  * vim600: sw=4 ts=4 fdm=marker
1369  * vim<600: sw=4 ts=4
1370  */
1371