Browse Source

add IPv6 support to php-fpm

pull/870/head
Robin Gloster 12 years ago
committed by Ferenc Kovacs
parent
commit
15ba757a2b
  1. 85
      sapi/fpm/fpm/fpm_sockets.c
  2. 6
      sapi/fpm/fpm/fpm_sockets.h
  3. 2
      sapi/fpm/php-fpm.conf.in
  4. 53
      sapi/fpm/tests/003.phpt

85
sapi/fpm/fpm/fpm_sockets.c

@ -39,29 +39,6 @@ struct listening_socket_s {
static struct fpm_array_s sockets_list;
static int fpm_sockets_resolve_af_inet(char *node, char *service, struct sockaddr_in *addr) /* {{{ */
{
struct addrinfo *res;
struct addrinfo hints;
int ret;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
ret = getaddrinfo(node, service, &hints, &res);
if (ret != 0) {
zlog(ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n",
node, service ? ":" : "", service ? service : "",
gai_strerror(ret), ret == EAI_SYSTEM ? ", system error: " : "", ret == EAI_SYSTEM ? strerror(errno) : "");
return -1;
}
*addr = *(struct sockaddr_in *) res->ai_addr;
freeaddrinfo(res);
return 0;
}
/* }}} */
enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 };
static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
@ -98,14 +75,23 @@ static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
}
/* }}} */
static void *fpm_get_in_addr(struct sockaddr *sa) /* {{{ */
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
/* }}} */
static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op) /* {{{ */
{
if (key == NULL) {
switch (type) {
case FPM_AF_INET : {
struct sockaddr_in *sa_in = (struct sockaddr_in *) sa;
key = alloca(sizeof("xxx.xxx.xxx.xxx:ppppp"));
sprintf(key, "%u.%u.%u.%u:%u", IPQUAD(&sa_in->sin_addr), (unsigned int) ntohs(sa_in->sin_port));
key = alloca(INET6_ADDRSTRLEN);
inet_ntop(sa->sa_family, fpm_get_in_addr(sa), key, sizeof key);
break;
}
@ -254,11 +240,14 @@ enum fpm_address_domain fpm_sockets_domain_from_address(char *address) /* {{{ */
static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /* {{{ */
{
struct sockaddr_in sa_in;
struct addrinfo hints, *servinfo, *p;
char *dup_address = strdup(wp->config->listen_address);
char *port_str = strchr(dup_address, ':');
char *port_str = strrchr(dup_address, ':');
char *addr = NULL;
int addr_len;
int port = 0;
int sock;
int status;
if (port_str) { /* this is host:port pair */
*port_str++ = '\0';
@ -274,23 +263,35 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
return -1;
}
memset(&sa_in, 0, sizeof(sa_in));
if (addr) {
sa_in.sin_addr.s_addr = inet_addr(addr);
if (sa_in.sin_addr.s_addr == INADDR_NONE) { /* do resolve */
if (0 > fpm_sockets_resolve_af_inet(addr, NULL, &sa_in)) {
return -1;
}
zlog(ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr));
// strip brackets from address for getaddrinfo
if (addr != NULL) {
addr_len = strlen(addr);
if (addr[0] == '[' && addr[addr_len - 1] == ']') {
addr[addr_len - 1] = '\0';
addr++;
}
} else {
sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
}
sa_in.sin_family = AF_INET;
sa_in.sin_port = htons(port);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((status = getaddrinfo(addr, port_str, &hints, &servinfo)) != 0) {
zlog(ZLOG_ERROR, "getaddrinfo: %s\n", gai_strerror(status));
return -1;
}
free(dup_address);
return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_in, sizeof(struct sockaddr_in));
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sock = fpm_sockets_get_listening_socket(wp, p->ai_addr, p->ai_addrlen)) != -1) {
break;
}
}
freeaddrinfo(servinfo);
return sock;
}
/* }}} */

6
sapi/fpm/fpm/fpm_sockets.h

@ -45,10 +45,4 @@ static inline int fd_set_blocked(int fd, int blocked) /* {{{ */
}
/* }}} */
#define IPQUAD(sin_addr) \
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[0], \
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[1], \
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[2], \
(unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[3]
#endif

2
sapi/fpm/php-fpm.conf.in

@ -152,6 +152,8 @@ group = @php_fpm_group@
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on
; a specific port;
; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
; a specific port;
; 'port' - to listen on a TCP socket to all addresses on a
; specific port;
; '/path/to/unix/socket' - to listen on a unix socket.

53
sapi/fpm/tests/003.phpt

@ -0,0 +1,53 @@
--TEST--
FPM: Test IPv6 support
--SKIPIF--
<?php include "skipif.inc"; ?>
--FILE--
<?php
include "include.inc";
$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
$cfg = <<<EOT
[global]
error_log = $logfile
[unconfined]
listen = [::1]:9000
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
EOT;
$fpm = run_fpm($cfg, $tail);
if (is_resource($fpm)) {
var_dump(fgets($tail));
var_dump(fgets($tail));
$i = 0;
while (($i++ < 30) && !($fp = fsockopen('[::1]', 9000))) {
usleep(10000);
}
if ($fp) {
echo "Done\n";
fclose($fp);
}
proc_terminate($fpm);
stream_get_contents($tail);
fclose($tail);
proc_close($fpm);
}
?>
--EXPECTF--
string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
"
string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
"
Done
--CLEAN--
<?php
$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
@unlink($logfile);
?>
Loading…
Cancel
Save