diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index 197c5b1c2b26e..73be32b21ffd4 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -125,6 +125,9 @@ static struct ini_value_parser_s ini_fpm_pool_options[] = { { "listen.group", &fpm_conf_set_string, WPO(listen_group) }, { "listen.mode", &fpm_conf_set_string, WPO(listen_mode) }, { "listen.allowed_clients", &fpm_conf_set_string, WPO(listen_allowed_clients) }, +#ifdef SO_SETFIB + { "listen.setfib", &fpm_conf_set_integer, WPO(listen_setfib) }, +#endif { "process.priority", &fpm_conf_set_integer, WPO(process_priority) }, { "process.dumpable", &fpm_conf_set_boolean, WPO(process_dumpable) }, { "pm", &fpm_conf_set_pm, WPO(pm) }, @@ -1715,6 +1718,9 @@ static void fpm_conf_dump(void) /* {{{ */ zlog(ZLOG_NOTICE, "\tlisten.group = %s", STR2STR(wp->config->listen_group)); zlog(ZLOG_NOTICE, "\tlisten.mode = %s", STR2STR(wp->config->listen_mode)); zlog(ZLOG_NOTICE, "\tlisten.allowed_clients = %s", STR2STR(wp->config->listen_allowed_clients)); +#ifdef HAVE_SETFIB + zlog(ZLOG_NOTICE, "\tlisten.setfib = %d", wp->config->listen_setfib); +#endif if (wp->config->process_priority == 64) { zlog(ZLOG_NOTICE, "\tprocess.priority = undefined"); } else { diff --git a/sapi/fpm/fpm/fpm_conf.h b/sapi/fpm/fpm/fpm_conf.h index 4c0addc2a950f..73657cd3a5a22 100644 --- a/sapi/fpm/fpm/fpm_conf.h +++ b/sapi/fpm/fpm/fpm_conf.h @@ -103,6 +103,9 @@ struct fpm_worker_pool_config_s { char *listen_acl_users; char *listen_acl_groups; #endif +#ifdef SO_SETFIB + int listen_setfib; +#endif }; struct ini_value_parser_s { diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c index 5b4bdc7f430a8..84fb25e234359 100644 --- a/sapi/fpm/fpm/fpm_sockets.c +++ b/sapi/fpm/fpm/fpm_sockets.c @@ -39,6 +39,10 @@ static struct fpm_array_s sockets_list; enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 }; +#ifdef SO_SETFIB +static int routemax = -1; +#endif + static inline void fpm_sockets_get_env_name(char *envname, unsigned idx) /* {{{ */ { if (!idx) { @@ -250,6 +254,20 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct return -1; } +#ifdef SO_SETFIB + if (-1 < wp->config->listen_setfib) { + if (routemax < wp->config->listen_setfib) { + zlog(ZLOG_ERROR, "Invalid routing table id %d, max is %d", wp->config->listen_setfib, routemax); + close(sock); + return -1; + } + + if (0 > setsockopt(sock, SOL_SOCKET, SO_SETFIB, &wp->config->listen_setfib, sizeof(wp->config->listen_setfib))) { + zlog(ZLOG_WARNING, "failed to change socket SO_SETFIB attribute"); + } + } +#endif + return sock; } /* }}} */ @@ -386,6 +404,20 @@ static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) /* } /* }}} */ +#ifdef SO_SETFIB +static zend_result fpm_socket_setfib_init(void) +{ + /* potentially up to 65536 but needs to check the actual cap beforehand */ + size_t len = sizeof(routemax); + if (sysctlbyname("net.fibs", &routemax, &len, NULL, 0) < 0) { + zlog(ZLOG_ERROR, "failed to get max routing table"); + return FAILURE; + } + + return SUCCESS; +} +#endif + int fpm_sockets_init_main() /* {{{ */ { unsigned i, lq_len; @@ -399,6 +431,12 @@ int fpm_sockets_init_main() /* {{{ */ return -1; } +#ifdef SO_SETFIB + if (fpm_socket_setfib_init() == FAILURE) { + return -1; + } +#endif + /* import inherited sockets */ for (i = 0; i < FPM_ENV_SOCKET_SET_MAX; i++) { fpm_sockets_get_env_name(envname, i); diff --git a/sapi/fpm/fpm/fpm_sockets.h b/sapi/fpm/fpm/fpm_sockets.h index c4c4fdbfdd07c..94d903ca45564 100644 --- a/sapi/fpm/fpm/fpm_sockets.h +++ b/sapi/fpm/fpm/fpm_sockets.h @@ -5,6 +5,9 @@ #include #include +#if defined(__FreeBSD__) +#include +#endif #include #include #include diff --git a/sapi/fpm/tests/setsofib.phpt b/sapi/fpm/tests/setsofib.phpt new file mode 100644 index 0000000000000..ba6502e14acb6 --- /dev/null +++ b/sapi/fpm/tests/setsofib.phpt @@ -0,0 +1,44 @@ +--TEST-- +FPM: listen.setfib` +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogError('Invalid routing table id 68000, max is 1'); +$tester->terminate(); +$tester->close(); + +?> +Done +--EXPECT-- +Done +--CLEAN-- +