You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1192 lines
29 KiB

25 years ago
24 years ago
19 years ago
20 years ago
21 years ago
20 years ago
25 years ago
24 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
19 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2009 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. /* $Id$ */
  20. /*#define DEBUG_MAIN_NETWORK 1*/
  21. #include "php.h"
  22. #include <stddef.h>
  23. #ifdef PHP_WIN32
  24. # include "win32/inet.h"
  25. # define O_RDONLY _O_RDONLY
  26. # include "win32/param.h"
  27. #elif defined(NETWARE)
  28. #include <sys/timeval.h>
  29. #include <sys/param.h>
  30. #else
  31. #include <sys/param.h>
  32. #endif
  33. #include <sys/types.h>
  34. #if HAVE_SYS_SOCKET_H
  35. #include <sys/socket.h>
  36. #endif
  37. #ifndef _FCNTL_H
  38. #include <fcntl.h>
  39. #endif
  40. #ifdef HAVE_SYS_SELECT_H
  41. #include <sys/select.h>
  42. #endif
  43. #if HAVE_SYS_POLL_H
  44. #include <sys/poll.h>
  45. #endif
  46. #if defined(NETWARE)
  47. #ifdef USE_WINSOCK
  48. #include <novsock2.h>
  49. #else
  50. #include <arpa/inet.h>
  51. #include <netinet/in.h>
  52. #include <netdb.h>
  53. #include <sys/select.h>
  54. #include <sys/socket.h>
  55. #endif
  56. #elif !defined(PHP_WIN32)
  57. #include <netinet/in.h>
  58. #include <netdb.h>
  59. #if HAVE_ARPA_INET_H
  60. #include <arpa/inet.h>
  61. #endif
  62. #endif
  63. #ifndef HAVE_INET_ATON
  64. int inet_aton(const char *, struct in_addr *);
  65. #endif
  66. #include "php_network.h"
  67. #if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE)
  68. #undef AF_UNIX
  69. #endif
  70. #if defined(AF_UNIX)
  71. #include <sys/un.h>
  72. #endif
  73. #include "ext/standard/file.h"
  74. #ifdef PHP_WIN32
  75. # include "win32/time.h"
  76. # define SOCK_ERR INVALID_SOCKET
  77. # define SOCK_CONN_ERR SOCKET_ERROR
  78. # define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT
  79. #if HAVE_IPV6
  80. const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */
  81. #endif
  82. #else
  83. # define SOCK_ERR -1
  84. # define SOCK_CONN_ERR -1
  85. # define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT
  86. #endif
  87. #if HAVE_GETADDRINFO
  88. #ifdef HAVE_GAI_STRERROR
  89. # define PHP_GAI_STRERROR(x) (gai_strerror(x))
  90. #else
  91. # define PHP_GAI_STRERROR(x) (php_gai_strerror(x))
  92. /* {{{ php_gai_strerror
  93. */
  94. static const char *php_gai_strerror(int code)
  95. {
  96. static struct {
  97. int code;
  98. const char *msg;
  99. } values[] = {
  100. # ifdef EAI_ADDRFAMILY
  101. {EAI_ADDRFAMILY, "Address family for hostname not supported"},
  102. # endif
  103. {EAI_AGAIN, "Temporary failure in name resolution"},
  104. {EAI_BADFLAGS, "Bad value for ai_flags"},
  105. {EAI_FAIL, "Non-recoverable failure in name resolution"},
  106. {EAI_FAMILY, "ai_family not supported"},
  107. {EAI_MEMORY, "Memory allocation failure"},
  108. # ifdef EAI_NODATA
  109. {EAI_NODATA, "No address associated with hostname"},
  110. # endif
  111. {EAI_NONAME, "Name or service not known"},
  112. {EAI_SERVICE, "Servname not supported for ai_socktype"},
  113. {EAI_SOCKTYPE, "ai_socktype not supported"},
  114. {EAI_SYSTEM, "System error"},
  115. {0, NULL}
  116. };
  117. int i;
  118. for (i = 0; values[i].msg != NULL; i++) {
  119. if (values[i].code == code) {
  120. return (char *)values[i].msg;
  121. }
  122. }
  123. return "Unknown error";
  124. }
  125. /* }}} */
  126. #endif
  127. #endif
  128. /* {{{ php_network_freeaddresses
  129. */
  130. static void php_network_freeaddresses(struct sockaddr **sal)
  131. {
  132. struct sockaddr **sap;
  133. if (sal == NULL)
  134. return;
  135. for (sap = sal; *sap != NULL; sap++)
  136. efree(*sap);
  137. efree(sal);
  138. }
  139. /* }}} */
  140. /* {{{ php_network_getaddresses
  141. * Returns number of addresses, 0 for none/error
  142. */
  143. static int php_network_getaddresses(const char *host, int socktype, struct sockaddr ***sal, char **error_string TSRMLS_DC)
  144. {
  145. struct sockaddr **sap;
  146. int n;
  147. #if HAVE_GETADDRINFO
  148. # if HAVE_IPV6
  149. static int ipv6_borked = -1; /* the way this is used *is* thread safe */
  150. # endif
  151. struct addrinfo hints, *res, *sai;
  152. #else
  153. struct hostent *host_info;
  154. struct in_addr in;
  155. #endif
  156. if (host == NULL) {
  157. return 0;
  158. }
  159. #if HAVE_GETADDRINFO
  160. memset(&hints, '\0', sizeof(hints));
  161. hints.ai_family = AF_INET; /* default to regular inet (see below) */
  162. hints.ai_socktype = socktype;
  163. # if HAVE_IPV6
  164. /* probe for a working IPv6 stack; even if detected as having v6 at compile
  165. * time, at runtime some stacks are slow to resolve or have other issues
  166. * if they are not correctly configured.
  167. * static variable use is safe here since simple store or fetch operations
  168. * are atomic and because the actual probe process is not in danger of
  169. * collisions or race conditions. */
  170. if (ipv6_borked == -1) {
  171. int s;
  172. s = socket(PF_INET6, SOCK_DGRAM, 0);
  173. if (s == SOCK_ERR) {
  174. ipv6_borked = 1;
  175. } else {
  176. ipv6_borked = 0;
  177. closesocket(s);
  178. }
  179. }
  180. hints.ai_family = ipv6_borked ? AF_INET : AF_UNSPEC;
  181. # endif
  182. if ((n = getaddrinfo(host, NULL, &hints, &res))) {
  183. if (error_string) {
  184. spprintf(error_string, 0, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
  185. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
  186. } else {
  187. php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed: %s", PHP_GAI_STRERROR(n));
  188. }
  189. return 0;
  190. } else if (res == NULL) {
  191. if (error_string) {
  192. spprintf(error_string, 0, "php_network_getaddresses: getaddrinfo failed (null result pointer) errno=%d", errno);
  193. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
  194. } else {
  195. php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: getaddrinfo failed (null result pointer)");
  196. }
  197. return 0;
  198. }
  199. sai = res;
  200. for (n = 1; (sai = sai->ai_next) != NULL; n++)
  201. ;
  202. *sal = safe_emalloc((n + 1), sizeof(*sal), 0);
  203. sai = res;
  204. sap = *sal;
  205. do {
  206. *sap = emalloc(sai->ai_addrlen);
  207. memcpy(*sap, sai->ai_addr, sai->ai_addrlen);
  208. sap++;
  209. } while ((sai = sai->ai_next) != NULL);
  210. freeaddrinfo(res);
  211. #else
  212. if (!inet_aton(host, &in)) {
  213. /* XXX NOT THREAD SAFE (is safe under win32) */
  214. host_info = gethostbyname(host);
  215. if (host_info == NULL) {
  216. if (error_string) {
  217. spprintf(error_string, 0, "php_network_getaddresses: gethostbyname failed. errno=%d", errno);
  218. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", *error_string);
  219. } else {
  220. php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_network_getaddresses: gethostbyname failed");
  221. }
  222. return 0;
  223. }
  224. in = *((struct in_addr *) host_info->h_addr);
  225. }
  226. *sal = safe_emalloc(2, sizeof(*sal), 0);
  227. sap = *sal;
  228. *sap = emalloc(sizeof(struct sockaddr_in));
  229. (*sap)->sa_family = AF_INET;
  230. ((struct sockaddr_in *)*sap)->sin_addr = in;
  231. sap++;
  232. n = 1;
  233. #endif
  234. *sap = NULL;
  235. return n;
  236. }
  237. /* }}} */
  238. #ifndef O_NONBLOCK
  239. #define O_NONBLOCK O_NDELAY
  240. #endif
  241. #if !defined(__BEOS__)
  242. # define HAVE_NON_BLOCKING_CONNECT 1
  243. # ifdef PHP_WIN32
  244. typedef u_long php_non_blocking_flags_t;
  245. # define SET_SOCKET_BLOCKING_MODE(sock, save) \
  246. save = TRUE; ioctlsocket(sock, FIONBIO, &save)
  247. # define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
  248. ioctlsocket(sock, FIONBIO, &save)
  249. # else
  250. typedef int php_non_blocking_flags_t;
  251. # define SET_SOCKET_BLOCKING_MODE(sock, save) \
  252. save = fcntl(sock, F_GETFL, 0); \
  253. fcntl(sock, F_SETFL, save | O_NONBLOCK)
  254. # define RESTORE_SOCKET_BLOCKING_MODE(sock, save) \
  255. fcntl(sock, F_SETFL, save)
  256. # endif
  257. #endif
  258. /* Connect to a socket using an interruptible connect with optional timeout.
  259. * Optionally, the connect can be made asynchronously, which will implicitly
  260. * enable non-blocking mode on the socket.
  261. * */
  262. /* {{{ php_network_connect_socket */
  263. PHPAPI int php_network_connect_socket(php_socket_t sockfd,
  264. const struct sockaddr *addr,
  265. socklen_t addrlen,
  266. int asynchronous,
  267. struct timeval *timeout,
  268. char **error_string,
  269. int *error_code)
  270. {
  271. #if HAVE_NON_BLOCKING_CONNECT
  272. php_non_blocking_flags_t orig_flags;
  273. int n;
  274. int error = 0;
  275. socklen_t len;
  276. int ret = 0;
  277. SET_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
  278. if ((n = connect(sockfd, addr, addrlen)) < 0) {
  279. error = php_socket_errno();
  280. if (error_code) {
  281. *error_code = error;
  282. }
  283. if (error != EINPROGRESS) {
  284. if (error_string) {
  285. *error_string = php_socket_strerror(error, NULL, 0);
  286. }
  287. return -1;
  288. }
  289. if (asynchronous && error == EINPROGRESS) {
  290. /* this is fine by us */
  291. return 0;
  292. }
  293. }
  294. if (n == 0) {
  295. goto ok;
  296. }
  297. if ((n = php_pollfd_for(sockfd, PHP_POLLREADABLE|POLLOUT, timeout)) == 0) {
  298. error = PHP_TIMEOUT_ERROR_VALUE;
  299. }
  300. if (n > 0) {
  301. len = sizeof(error);
  302. /*
  303. BSD-derived systems set errno correctly
  304. Solaris returns -1 from getsockopt in case of error
  305. */
  306. if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) < 0) {
  307. ret = -1;
  308. }
  309. } else {
  310. /* whoops: sockfd has disappeared */
  311. ret = -1;
  312. }
  313. ok:
  314. if (!asynchronous) {
  315. /* back to blocking mode */
  316. RESTORE_SOCKET_BLOCKING_MODE(sockfd, orig_flags);
  317. }
  318. if (error_code) {
  319. *error_code = error;
  320. }
  321. if (error && error_string) {
  322. *error_string = php_socket_strerror(error, NULL, 0);
  323. ret = -1;
  324. }
  325. return ret;
  326. #else
  327. if (asynchronous) {
  328. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Asynchronous connect() not supported on this platform");
  329. }
  330. return connect(sockfd, addr, addrlen);
  331. #endif
  332. }
  333. /* }}} */
  334. /* {{{ sub_times */
  335. static inline void sub_times(struct timeval a, struct timeval b, struct timeval *result)
  336. {
  337. result->tv_usec = a.tv_usec - b.tv_usec;
  338. if (result->tv_usec < 0L) {
  339. a.tv_sec--;
  340. result->tv_usec += 1000000L;
  341. }
  342. result->tv_sec = a.tv_sec - b.tv_sec;
  343. if (result->tv_sec < 0L) {
  344. result->tv_sec++;
  345. result->tv_usec -= 1000000L;
  346. }
  347. }
  348. /* }}} */
  349. /* Bind to a local IP address.
  350. * Returns the bound socket, or -1 on failure.
  351. * */
  352. /* {{{ php_network_bind_socket_to_local_addr */
  353. php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port,
  354. int socktype, char **error_string, int *error_code
  355. TSRMLS_DC)
  356. {
  357. int num_addrs, n, err = 0;
  358. php_socket_t sock;
  359. struct sockaddr **sal, **psal, *sa;
  360. socklen_t socklen;
  361. num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
  362. if (num_addrs == 0) {
  363. /* could not resolve address(es) */
  364. return -1;
  365. }
  366. for (sal = psal; *sal != NULL; sal++) {
  367. sa = *sal;
  368. /* create a socket for this address */
  369. sock = socket(sa->sa_family, socktype, 0);
  370. if (sock == SOCK_ERR) {
  371. continue;
  372. }
  373. switch (sa->sa_family) {
  374. #if HAVE_GETADDRINFO && HAVE_IPV6
  375. case AF_INET6:
  376. ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
  377. ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
  378. socklen = sizeof(struct sockaddr_in6);
  379. break;
  380. #endif
  381. case AF_INET:
  382. ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
  383. ((struct sockaddr_in *)sa)->sin_port = htons(port);
  384. socklen = sizeof(struct sockaddr_in);
  385. break;
  386. default:
  387. /* Unknown family */
  388. socklen = 0;
  389. sa = NULL;
  390. }
  391. if (sa) {
  392. /* attempt to bind */
  393. #ifdef SO_REUSEADDR
  394. {
  395. int val = 1;
  396. setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
  397. }
  398. #endif
  399. n = bind(sock, sa, socklen);
  400. if (n != SOCK_CONN_ERR) {
  401. goto bound;
  402. }
  403. err = php_socket_errno();
  404. }
  405. closesocket(sock);
  406. }
  407. sock = -1;
  408. if (error_code) {
  409. *error_code = err;
  410. }
  411. if (error_string) {
  412. *error_string = php_socket_strerror(err, NULL, 0);
  413. }
  414. bound:
  415. php_network_freeaddresses(psal);
  416. return sock;
  417. }
  418. /* }}} */
  419. PHPAPI int php_network_parse_network_address_with_port(const char *addr, long addrlen, struct sockaddr *sa, socklen_t *sl TSRMLS_DC)
  420. {
  421. char *colon;
  422. char *tmp;
  423. int ret = FAILURE;
  424. short port;
  425. struct sockaddr_in *in4 = (struct sockaddr_in*)sa;
  426. struct sockaddr **psal;
  427. int n;
  428. char *errstr = NULL;
  429. #if HAVE_IPV6
  430. struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
  431. #endif
  432. if (*addr == '[') {
  433. colon = memchr(addr + 1, ']', addrlen-1);
  434. if (!colon || colon[1] != ':') {
  435. return FAILURE;
  436. }
  437. port = atoi(colon + 2);
  438. addr++;
  439. } else {
  440. colon = memchr(addr, ':', addrlen);
  441. if (!colon) {
  442. return FAILURE;
  443. }
  444. port = atoi(colon + 1);
  445. }
  446. tmp = estrndup(addr, colon - addr);
  447. /* first, try interpreting the address as a numeric address */
  448. #if HAVE_IPV6 && HAVE_INET_PTON
  449. if (inet_pton(AF_INET6, tmp, &in6->sin6_addr) > 0) {
  450. in6->sin6_port = htons(port);
  451. in6->sin6_family = AF_INET6;
  452. *sl = sizeof(struct sockaddr_in6);
  453. ret = SUCCESS;
  454. goto out;
  455. }
  456. #endif
  457. if (inet_aton(tmp, &in4->sin_addr) > 0) {
  458. in4->sin_port = htons(port);
  459. in4->sin_family = AF_INET;
  460. *sl = sizeof(struct sockaddr_in);
  461. ret = SUCCESS;
  462. goto out;
  463. }
  464. /* looks like we'll need to resolve it */
  465. n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr TSRMLS_CC);
  466. if (n == 0) {
  467. if (errstr) {
  468. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to resolve `%s': %s", tmp, errstr);
  469. STR_FREE(errstr);
  470. }
  471. goto out;
  472. }
  473. /* copy the details from the first item */
  474. switch ((*psal)->sa_family) {
  475. #if HAVE_GETADDRINFO && HAVE_IPV6
  476. case AF_INET6:
  477. *in6 = **(struct sockaddr_in6**)psal;
  478. in6->sin6_port = htons(port);
  479. *sl = sizeof(struct sockaddr_in6);
  480. ret = SUCCESS;
  481. break;
  482. #endif
  483. case AF_INET:
  484. *in4 = **(struct sockaddr_in**)psal;
  485. in4->sin_port = htons(port);
  486. *sl = sizeof(struct sockaddr_in);
  487. ret = SUCCESS;
  488. break;
  489. }
  490. php_network_freeaddresses(psal);
  491. out:
  492. STR_FREE(tmp);
  493. return ret;
  494. }
  495. PHPAPI void php_network_populate_name_from_sockaddr(
  496. /* input address */
  497. struct sockaddr *sa, socklen_t sl,
  498. /* output readable address */
  499. char **textaddr, long *textaddrlen,
  500. /* output address */
  501. struct sockaddr **addr,
  502. socklen_t *addrlen
  503. TSRMLS_DC)
  504. {
  505. if (addr) {
  506. *addr = emalloc(sl);
  507. memcpy(*addr, sa, sl);
  508. *addrlen = sl;
  509. }
  510. if (textaddr) {
  511. #if HAVE_IPV6 && HAVE_INET_NTOP
  512. char abuf[256];
  513. #endif
  514. char *buf = NULL;
  515. switch (sa->sa_family) {
  516. case AF_INET:
  517. /* generally not thread safe, but it *is* thread safe under win32 */
  518. buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr);
  519. if (buf) {
  520. *textaddrlen = spprintf(textaddr, 0, "%s:%d",
  521. buf, ntohs(((struct sockaddr_in*)sa)->sin_port));
  522. }
  523. break;
  524. #if HAVE_IPV6 && HAVE_INET_NTOP
  525. case AF_INET6:
  526. buf = (char*)inet_ntop(sa->sa_family, &((struct sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
  527. if (buf) {
  528. *textaddrlen = spprintf(textaddr, 0, "%s:%d",
  529. buf, ntohs(((struct sockaddr_in6*)sa)->sin6_port));
  530. }
  531. break;
  532. #endif
  533. #ifdef AF_UNIX
  534. case AF_UNIX:
  535. {
  536. struct sockaddr_un *ua = (struct sockaddr_un*)sa;
  537. if (ua->sun_path[0] == '\0') {
  538. /* abstract name */
  539. int len = strlen(ua->sun_path + 1) + 1;
  540. *textaddrlen = len;
  541. *textaddr = emalloc(len + 1);
  542. memcpy(*textaddr, ua->sun_path, len);
  543. (*textaddr)[len] = '\0';
  544. } else {
  545. *textaddrlen = strlen(ua->sun_path);
  546. *textaddr = estrndup(ua->sun_path, *textaddrlen);
  547. }
  548. }
  549. break;
  550. #endif
  551. }
  552. }
  553. }
  554. PHPAPI int php_network_get_peer_name(php_socket_t sock,
  555. char **textaddr, long *textaddrlen,
  556. struct sockaddr **addr,
  557. socklen_t *addrlen
  558. TSRMLS_DC)
  559. {
  560. php_sockaddr_storage sa;
  561. socklen_t sl = sizeof(sa);
  562. memset(&sa, 0, sizeof(sa));
  563. if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
  564. php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
  565. textaddr, textaddrlen,
  566. addr, addrlen
  567. TSRMLS_CC);
  568. return 0;
  569. }
  570. return -1;
  571. }
  572. PHPAPI int php_network_get_sock_name(php_socket_t sock,
  573. char **textaddr, long *textaddrlen,
  574. struct sockaddr **addr,
  575. socklen_t *addrlen
  576. TSRMLS_DC)
  577. {
  578. php_sockaddr_storage sa;
  579. socklen_t sl = sizeof(sa);
  580. memset(&sa, 0, sizeof(sa));
  581. if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
  582. php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
  583. textaddr, textaddrlen,
  584. addr, addrlen
  585. TSRMLS_CC);
  586. return 0;
  587. }
  588. return -1;
  589. }
  590. /* Accept a client connection from a server socket,
  591. * using an optional timeout.
  592. * Returns the peer address in addr/addrlen (it will emalloc
  593. * these, so be sure to efree the result).
  594. * If you specify textaddr/textaddrlen, a text-printable
  595. * version of the address will be emalloc'd and returned.
  596. * */
  597. /* {{{ php_network_accept_incoming */
  598. PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
  599. char **textaddr, long *textaddrlen,
  600. struct sockaddr **addr,
  601. socklen_t *addrlen,
  602. struct timeval *timeout,
  603. char **error_string,
  604. int *error_code
  605. TSRMLS_DC)
  606. {
  607. php_socket_t clisock = -1;
  608. int error = 0, n;
  609. php_sockaddr_storage sa;
  610. socklen_t sl;
  611. n = php_pollfd_for(srvsock, PHP_POLLREADABLE, timeout);
  612. if (n == 0) {
  613. error = PHP_TIMEOUT_ERROR_VALUE;
  614. } else if (n == -1) {
  615. error = php_socket_errno();
  616. } else {
  617. sl = sizeof(sa);
  618. clisock = accept(srvsock, (struct sockaddr*)&sa, &sl);
  619. if (clisock >= 0) {
  620. php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
  621. textaddr, textaddrlen,
  622. addr, addrlen
  623. TSRMLS_CC);
  624. } else {
  625. error = php_socket_errno();
  626. }
  627. }
  628. if (error_code) {
  629. *error_code = error;
  630. }
  631. if (error_string) {
  632. *error_string = php_socket_strerror(error, NULL, 0);
  633. }
  634. return clisock;
  635. }
  636. /* }}} */
  637. /* Connect to a remote host using an interruptible connect with optional timeout.
  638. * Optionally, the connect can be made asynchronously, which will implicitly
  639. * enable non-blocking mode on the socket.
  640. * Returns the connected (or connecting) socket, or -1 on failure.
  641. * */
  642. /* {{{ php_network_connect_socket_to_host */
  643. php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port,
  644. int socktype, int asynchronous, struct timeval *timeout, char **error_string,
  645. int *error_code, char *bindto, unsigned short bindport
  646. TSRMLS_DC)
  647. {
  648. int num_addrs, n, fatal = 0;
  649. php_socket_t sock;
  650. struct sockaddr **sal, **psal, *sa;
  651. struct timeval working_timeout;
  652. socklen_t socklen;
  653. #if HAVE_GETTIMEOFDAY
  654. struct timeval limit_time, time_now;
  655. #endif
  656. num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
  657. if (num_addrs == 0) {
  658. /* could not resolve address(es) */
  659. return -1;
  660. }
  661. if (timeout) {
  662. memcpy(&working_timeout, timeout, sizeof(working_timeout));
  663. #if HAVE_GETTIMEOFDAY
  664. gettimeofday(&limit_time, NULL);
  665. limit_time.tv_sec += working_timeout.tv_sec;
  666. limit_time.tv_usec += working_timeout.tv_usec;
  667. if (limit_time.tv_usec >= 1000000) {
  668. limit_time.tv_usec -= 1000000;
  669. limit_time.tv_sec++;
  670. }
  671. #endif
  672. }
  673. for (sal = psal; !fatal && *sal != NULL; sal++) {
  674. sa = *sal;
  675. /* create a socket for this address */
  676. sock = socket(sa->sa_family, socktype, 0);
  677. if (sock == SOCK_ERR) {
  678. continue;
  679. }
  680. switch (sa->sa_family) {
  681. #if HAVE_GETADDRINFO && HAVE_IPV6
  682. case AF_INET6:
  683. if (bindto && strchr(bindto, ':')) {
  684. ((struct sockaddr_in6 *)sa)->sin6_family = sa->sa_family;
  685. ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
  686. socklen = sizeof(struct sockaddr_in6);
  687. } else {
  688. socklen = 0;
  689. sa = NULL;
  690. }
  691. break;
  692. #endif
  693. case AF_INET:
  694. ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
  695. ((struct sockaddr_in *)sa)->sin_port = htons(port);
  696. socklen = sizeof(struct sockaddr_in);
  697. break;
  698. default:
  699. /* Unknown family */
  700. socklen = 0;
  701. sa = NULL;
  702. }
  703. if (sa) {
  704. /* make a connection attempt */
  705. if (bindto) {
  706. struct sockaddr *local_address = NULL;
  707. int local_address_len = 0;
  708. if (sa->sa_family == AF_INET) {
  709. struct sockaddr_in *in4 = emalloc(sizeof(struct sockaddr_in));
  710. local_address = (struct sockaddr*)in4;
  711. local_address_len = sizeof(struct sockaddr_in);
  712. in4->sin_family = sa->sa_family;
  713. in4->sin_port = htons(bindport);
  714. if (!inet_aton(bindto, &in4->sin_addr)) {
  715. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
  716. goto skip_bind;
  717. }
  718. memset(&(in4->sin_zero), 0, sizeof(in4->sin_zero));
  719. }
  720. #if HAVE_IPV6 && HAVE_INET_PTON
  721. else { /* IPV6 */
  722. struct sockaddr_in6 *in6 = emalloc(sizeof(struct sockaddr_in6));
  723. local_address = (struct sockaddr*)in6;
  724. local_address_len = sizeof(struct sockaddr_in6);
  725. in6->sin6_family = sa->sa_family;
  726. in6->sin6_port = htons(bindport);
  727. if (inet_pton(AF_INET6, bindto, &in6->sin6_addr) < 1) {
  728. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid IP Address: %s", bindto);
  729. goto skip_bind;
  730. }
  731. }
  732. #endif
  733. if (!local_address || bind(sock, local_address, local_address_len)) {
  734. php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to bind to '%s:%d', system said: %s", bindto, bindport, strerror(errno));
  735. }
  736. skip_bind:
  737. if (local_address) {
  738. efree(local_address);
  739. }
  740. }
  741. /* free error string recieved during previous iteration (if any) */
  742. if (error_string && *error_string) {
  743. efree(*error_string);
  744. *error_string = NULL;
  745. }
  746. n = php_network_connect_socket(sock, sa, socklen, asynchronous,
  747. timeout ? &working_timeout : NULL,
  748. error_string, error_code);
  749. if (n != SOCK_CONN_ERR) {
  750. goto connected;
  751. }
  752. /* adjust timeout for next attempt */
  753. #if HAVE_GETTIMEOFDAY
  754. if (timeout) {
  755. gettimeofday(&time_now, NULL);
  756. if (timercmp(&time_now, &limit_time, >=)) {
  757. /* time limit expired; don't attempt any further connections */
  758. fatal = 1;
  759. } else {
  760. /* work out remaining time */
  761. sub_times(limit_time, time_now, &working_timeout);
  762. }
  763. }
  764. #else
  765. if (error_code && *error_code == PHP_TIMEOUT_ERROR_VALUE) {
  766. /* Don't even bother trying to connect to the next alternative;
  767. * we have no way to determine how long we have already taken
  768. * and it is quite likely that the next attempt will fail too. */
  769. fatal = 1;
  770. } else {
  771. /* re-use the same initial timeout.
  772. * Not the best thing, but in practice it should be good-enough */
  773. if (timeout) {
  774. memcpy(&working_timeout, timeout, sizeof(working_timeout));
  775. }
  776. }
  777. #endif
  778. }
  779. closesocket(sock);
  780. }
  781. sock = -1;
  782. connected:
  783. php_network_freeaddresses(psal);
  784. return sock;
  785. }
  786. /* }}} */
  787. /* {{{ php_any_addr
  788. * Fills the any (wildcard) address into php_sockaddr_storage
  789. */
  790. PHPAPI void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port)
  791. {
  792. memset(addr, 0, sizeof(php_sockaddr_storage));
  793. switch (family) {
  794. #if HAVE_IPV6
  795. case AF_INET6: {
  796. struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) addr;
  797. sin6->sin6_family = AF_INET6;
  798. sin6->sin6_port = htons(port);
  799. sin6->sin6_addr = in6addr_any;
  800. break;
  801. }
  802. #endif
  803. case AF_INET: {
  804. struct sockaddr_in *sin = (struct sockaddr_in *) addr;
  805. sin->sin_family = AF_INET;
  806. sin->sin_port = htons(port);
  807. sin->sin_addr.s_addr = htonl(INADDR_ANY);
  808. break;
  809. }
  810. }
  811. }
  812. /* }}} */
  813. /* {{{ php_sockaddr_size
  814. * Returns the size of struct sockaddr_xx for the family
  815. */
  816. PHPAPI int php_sockaddr_size(php_sockaddr_storage *addr)
  817. {
  818. switch (((struct sockaddr *)addr)->sa_family) {
  819. case AF_INET:
  820. return sizeof(struct sockaddr_in);
  821. #if HAVE_IPV6
  822. case AF_INET6:
  823. return sizeof(struct sockaddr_in6);
  824. #endif
  825. #ifdef AF_UNIX
  826. case AF_UNIX:
  827. return sizeof(struct sockaddr_un);
  828. #endif
  829. default:
  830. return 0;
  831. }
  832. }
  833. /* }}} */
  834. /* Given a socket error code, if buf == NULL:
  835. * emallocs storage for the error message and returns
  836. * else
  837. * sprintf message into provided buffer and returns buf
  838. */
  839. /* {{{ php_socket_strerror */
  840. PHPAPI char *php_socket_strerror(long err, char *buf, size_t bufsize)
  841. {
  842. #ifndef PHP_WIN32
  843. char *errstr;
  844. errstr = strerror(err);
  845. if (buf == NULL) {
  846. buf = estrdup(errstr);
  847. } else {
  848. strncpy(buf, errstr, bufsize);
  849. }
  850. return buf;
  851. #else
  852. char *sysbuf;
  853. int free_it = 1;
  854. if (!FormatMessage(
  855. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  856. FORMAT_MESSAGE_FROM_SYSTEM |
  857. FORMAT_MESSAGE_IGNORE_INSERTS,
  858. NULL,
  859. err,
  860. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  861. (LPTSTR)&sysbuf,
  862. 0,
  863. NULL)) {
  864. free_it = 0;
  865. sysbuf = "Unknown Error";
  866. }
  867. if (buf == NULL) {
  868. buf = estrdup(sysbuf);
  869. } else {
  870. strncpy(buf, sysbuf, bufsize);
  871. }
  872. if (free_it) {
  873. LocalFree(sysbuf);
  874. }
  875. return buf;
  876. #endif
  877. }
  878. /* }}} */
  879. /* deprecated */
  880. PHPAPI php_stream *_php_stream_sock_open_from_socket(php_socket_t socket, const char *persistent_id STREAMS_DC TSRMLS_DC)
  881. {
  882. php_stream *stream;
  883. php_netstream_data_t *sock;
  884. sock = pemalloc(sizeof(php_netstream_data_t), persistent_id ? 1 : 0);
  885. memset(sock, 0, sizeof(php_netstream_data_t));
  886. sock->is_blocked = 1;
  887. sock->timeout.tv_sec = FG(default_socket_timeout);
  888. sock->timeout.tv_usec = 0;
  889. sock->socket = socket;
  890. stream = php_stream_alloc_rel(&php_stream_generic_socket_ops, sock, persistent_id, "r+");
  891. if (stream == NULL) {
  892. pefree(sock, persistent_id ? 1 : 0);
  893. } else {
  894. stream->flags |= PHP_STREAM_FLAG_AVOID_BLOCKING;
  895. }
  896. return stream;
  897. }
  898. PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short port,
  899. int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC TSRMLS_DC)
  900. {
  901. char *res;
  902. long reslen;
  903. php_stream *stream;
  904. reslen = spprintf(&res, 0, "tcp://%s:%d", host, port);
  905. stream = php_stream_xport_create(res, reslen, ENFORCE_SAFE_MODE | REPORT_ERRORS,
  906. STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, persistent_id, timeout, NULL, NULL, NULL);
  907. efree(res);
  908. return stream;
  909. }
  910. PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC)
  911. {
  912. int ret = SUCCESS;
  913. int flags;
  914. int myflag = 0;
  915. #ifdef PHP_WIN32
  916. /* with ioctlsocket, a non-zero sets nonblocking, a zero sets blocking */
  917. flags = !block;
  918. if (ioctlsocket(socketd, FIONBIO, &flags) == SOCKET_ERROR) {
  919. char *error_string;
  920. error_string = php_socket_strerror(WSAGetLastError(), NULL, 0);
  921. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", error_string);
  922. efree(error_string);
  923. ret = FAILURE;
  924. }
  925. #else
  926. flags = fcntl(socketd, F_GETFL);
  927. #ifdef O_NONBLOCK
  928. myflag = O_NONBLOCK; /* POSIX version */
  929. #elif defined(O_NDELAY)
  930. myflag = O_NDELAY; /* old non-POSIX version */
  931. #endif
  932. if (!block) {
  933. flags |= myflag;
  934. } else {
  935. flags &= ~myflag;
  936. }
  937. fcntl(socketd, F_SETFL, flags);
  938. #endif
  939. return ret;
  940. }
  941. PHPAPI void _php_emit_fd_setsize_warning(int max_fd)
  942. {
  943. TSRMLS_FETCH();
  944. #ifdef PHP_WIN32
  945. php_error_docref(NULL TSRMLS_CC, E_WARNING,
  946. "PHP needs to be recompiled with a larger value of FD_SETSIZE.\n"
  947. "If this binary is from an official www.php.net package, file a bug report\n"
  948. "at http://bugs.php.net, including the following information:\n"
  949. "FD_SETSIZE=%d, but you are using %d.\n"
  950. " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
  951. "to match to maximum number of sockets each script will work with at\n"
  952. "one time, in order to avoid seeing this error again at a later date.",
  953. FD_SETSIZE, max_fd, (max_fd + 128) & ~127);
  954. #else
  955. php_error_docref(NULL TSRMLS_CC, E_WARNING,
  956. "You MUST recompile PHP with a larger value of FD_SETSIZE.\n"
  957. "It is set to %d, but you have descriptors numbered at least as high as %d.\n"
  958. " --enable-fd-setsize=%d is recommended, but you may want to set it\n"
  959. "to equal the maximum number of open files supported by your system,\n"
  960. "in order to avoid seeing this error again at a later date.",
  961. FD_SETSIZE, max_fd, (max_fd + 1024) & ~1023);
  962. #endif
  963. }
  964. #if defined(PHP_USE_POLL_2_EMULATION)
  965. /* emulate poll(2) using select(2), safely. */
  966. PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
  967. {
  968. fd_set rset, wset, eset;
  969. php_socket_t max_fd = SOCK_ERR;
  970. unsigned int i, n;
  971. struct timeval tv;
  972. /* check the highest numbered descriptor */
  973. for (i = 0; i < nfds; i++) {
  974. if (ufds[i].fd > max_fd)
  975. max_fd = ufds[i].fd;
  976. }
  977. PHP_SAFE_MAX_FD(max_fd, nfds + 1);
  978. FD_ZERO(&rset);
  979. FD_ZERO(&wset);
  980. FD_ZERO(&eset);
  981. for (i = 0; i < nfds; i++) {
  982. if (ufds[i].events & PHP_POLLREADABLE) {
  983. PHP_SAFE_FD_SET(ufds[i].fd, &rset);
  984. }
  985. if (ufds[i].events & POLLOUT) {
  986. PHP_SAFE_FD_SET(ufds[i].fd, &wset);
  987. }
  988. if (ufds[i].events & POLLPRI) {
  989. PHP_SAFE_FD_SET(ufds[i].fd, &eset);
  990. }
  991. }
  992. if (timeout >= 0) {
  993. tv.tv_sec = timeout / 1000;
  994. tv.tv_usec = (timeout - (tv.tv_sec * 1000)) * 1000;
  995. }
  996. /* Reseting/initializing */
  997. #ifdef PHP_WIN32
  998. WSASetLastError(0);
  999. #else
  1000. errno = 0;
  1001. #endif
  1002. n = select(max_fd + 1, &rset, &wset, &eset, timeout >= 0 ? &tv : NULL);
  1003. if (n >= 0) {
  1004. for (i = 0; i < nfds; i++) {
  1005. ufds[i].revents = 0;
  1006. if (PHP_SAFE_FD_ISSET(ufds[i].fd, &rset)) {
  1007. /* could be POLLERR or POLLHUP but can't tell without probing */
  1008. ufds[i].revents |= POLLIN;
  1009. }
  1010. if (PHP_SAFE_FD_ISSET(ufds[i].fd, &wset)) {
  1011. ufds[i].revents |= POLLOUT;
  1012. }
  1013. if (PHP_SAFE_FD_ISSET(ufds[i].fd, &eset)) {
  1014. ufds[i].revents |= POLLPRI;
  1015. }
  1016. }
  1017. }
  1018. return n;
  1019. }
  1020. #endif
  1021. /*
  1022. * Local variables:
  1023. * tab-width: 8
  1024. * c-basic-offset: 8
  1025. * End:
  1026. * vim600: sw=4 ts=4 fdm=marker
  1027. * vim<600: sw=4 ts=4
  1028. */