Stream: set SO_REUSEADDR for UDP upstream sockets. The option is only set if the socket is bound to a specific port to allow several such sockets coexist at the same time. This is required, for example, when nginx acts as a transparent proxy and receives two datagrams from the same client in a short time. The feature is only implemented for Linux.
diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c index 9a8f4d9..30cb59a 100644 --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c
@@ -21,6 +21,9 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) { int rc, type; +#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX) + in_port_t port; +#endif ngx_int_t event; ngx_err_t err; ngx_uint_t level; @@ -87,9 +90,13 @@ } #endif +#if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT || NGX_LINUX) + port = ngx_inet_get_port(pc->sockaddr); +#endif + #if (NGX_HAVE_IP_BIND_ADDRESS_NO_PORT) - if (pc->sockaddr->sa_family != AF_UNIX) { + if (pc->sockaddr->sa_family != AF_UNIX && port == 0) { static int bind_address_no_port = 1; if (bind_address_no_port) { @@ -113,6 +120,23 @@ #endif +#if (NGX_LINUX) + + if (pc->type == SOCK_DGRAM && port != 0) { + int reuse_addr = 1; + + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (const void *) &reuse_addr, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno, + "setsockopt(SO_REUSEADDR) failed"); + goto failed; + } + } + +#endif + if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) { ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno, "bind(%V) failed", &pc->local->name);