[PATCH] Added so_freebind and so_transparent to the listen directive
Trygve Vea
trygve.vea at redpill-linpro.com
Thu Mar 27 15:34:37 UTC 2014
# HG changeset patch
# User Trygve Vea <trygve.vea at redpill-linpro.com>
# Date 1395933815 -3600
# Thu Mar 27 16:23:35 2014 +0100
# Node ID 13e6a37c2f57443b0d5dd0abce8d9d4ab00e31e3
# Parent 2411d4b5be2ca690a5a00a1d8ad96ff69a00317f
Added so_freebind and so_transparent to the listen directive
This solves a Linux/IPv6-specific problem.
To be able to listen to an IPv6 address that is not yet available on the host,
one need to use the IP_FREEBIND and IP_TRANSPARENT socket options.
The use case in question is for a failover setup with several service-
addresses in a IPv6-only environment.
IPv4 has a sysctl available (ip_nonlocal_bind), which is not available for
IPv6 - thus making these patches necessary.
diff -r 2411d4b5be2c -r 13e6a37c2f57 src/core/ngx_connection.c
--- a/src/core/ngx_connection.c Wed Mar 26 18:01:11 2014 +0400
+++ b/src/core/ngx_connection.c Thu Mar 27 16:23:35 2014 +0100
@@ -305,6 +305,14 @@
ngx_open_listening_sockets(ngx_cycle_t *cycle)
{
int reuseaddr;
+#ifdef NGX_LINUX
+#ifdef IP_FREEBIND
+ int so_freebind;
+#endif
+#ifdef IP_TRANSPARENT
+ int so_transparent;
+#endif
+#endif
ngx_uint_t i, tries, failed;
ngx_err_t err;
ngx_log_t *log;
@@ -370,6 +378,37 @@
return NGX_ERROR;
}
+#ifdef NGX_LINUX
+#ifdef IP_FREEBIND
+ if (ls[i].so_freebind) {
+ so_freebind = (ls[i].so_freebind == 1) ? 1 : 0;
+
+ if (setsockopt(s, SOL_IP, IP_FREEBIND,
+ (const void *) &so_freebind, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(IP_FREEBIND, %d) %V failed",
+ so_freebind, &ls[i].addr_text);
+ }
+ }
+#endif
+#ifdef IP_TRANSPARENT
+ if (ls[i].so_transparent) {
+ so_transparent = (ls[i].so_transparent == 1) ? 1 : 0;
+
+ if (setsockopt(s, SOL_IP, IP_TRANSPARENT,
+ (const void *) &so_transparent, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(IP_TRANSPARENT, %d) %V failed",
+ so_transparent, &ls[i].addr_text);
+ }
+ }
+#endif
+#endif
+
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
if (ls[i].sockaddr->sa_family == AF_INET6) {
diff -r 2411d4b5be2c -r 13e6a37c2f57 src/core/ngx_connection.h
--- a/src/core/ngx_connection.h Wed Mar 26 18:01:11 2014 +0400
+++ b/src/core/ngx_connection.h Thu Mar 27 16:23:35 2014 +0100
@@ -67,6 +67,14 @@
unsigned ipv6only:1;
#endif
unsigned keepalive:2;
+#ifdef NGX_LINUX
+#ifdef IP_FREEBIND
+ unsigned so_freebind:1;
+#endif
+#ifdef IP_TRANSPARENT
+ unsigned so_transparent:1;
+#endif
+#endif
#if (NGX_HAVE_DEFERRED_ACCEPT)
unsigned deferred_accept:1;
diff -r 2411d4b5be2c -r 13e6a37c2f57 src/http/ngx_http.c
--- a/src/http/ngx_http.c Wed Mar 26 18:01:11 2014 +0400
+++ b/src/http/ngx_http.c Thu Mar 27 16:23:35 2014 +0100
@@ -1791,6 +1791,14 @@
ls->sndbuf = addr->opt.sndbuf;
ls->keepalive = addr->opt.so_keepalive;
+#ifdef NGX_LINUX
+#ifdef IP_FREEBIND
+ ls->so_freebind = addr->opt.so_freebind;
+#endif
+#ifdef IP_TRANSPARENT
+ ls->so_transparent = addr->opt.so_transparent;
+#endif
+#endif
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
ls->keepidle = addr->opt.tcp_keepidle;
ls->keepintvl = addr->opt.tcp_keepintvl;
diff -r 2411d4b5be2c -r 13e6a37c2f57 src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c Wed Mar 26 18:01:11 2014 +0400
+++ b/src/http/ngx_http_core_module.c Thu Mar 27 16:23:35 2014 +0100
@@ -4283,6 +4283,30 @@
continue;
}
+ if (ngx_strcmp(value[n].data, "so_freebind") == 0) {
+#ifdef NGX_LINUX
+ lsopt.so_freebind = 1;
+ continue;
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the \"so_freebind\" parameter requires "
+ "nginx to be built for Linux");
+ return NGX_CONF_ERROR;
+#endif
+ }
+
+ if (ngx_strcmp(value[n].data, "so_transparent") == 0) {
+#ifdef NGX_LINUX
+ lsopt.so_transparent = 1;
+ continue;
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the \"so_transparent\" parameter requires "
+ "nginx to be built for linux");
+ return NGX_CONF_ERROR;
+#endif
+ }
+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter \"%V\"", &value[n]);
return NGX_CONF_ERROR;
diff -r 2411d4b5be2c -r 13e6a37c2f57 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h Wed Mar 26 18:01:11 2014 +0400
+++ b/src/http/ngx_http_core_module.h Thu Mar 27 16:23:35 2014 +0100
@@ -82,6 +82,14 @@
unsigned ipv6only:1;
#endif
unsigned so_keepalive:2;
+#ifdef NGX_LINUX
+#ifdef IP_FREEBIND
+ unsigned so_freebind:1;
+#endif
+#ifdef IP_TRANSPARENT
+ unsigned so_transparent:1;
+#endif
+#endif
unsigned proxy_protocol:1;
int backlog;
More information about the nginx-devel
mailing list