diff src/stream/ngx_stream_core_module.c @ 7478:4f9b72a229c1

Multiple addresses in "listen". Previously only one address was used by the listen directive handler even if host name resolved to multiple addresses. Now a separate listening socket is created for each address.
author Roman Arutyunyan <arut@nginx.com>
date Fri, 15 Mar 2019 15:45:56 +0300
parents fe767c99c2ad
children 2ab7b55ae4a0 893b3313f53c
line wrap: on
line diff
--- a/src/stream/ngx_stream_core_module.c
+++ b/src/stream/ngx_stream_core_module.c
@@ -577,7 +577,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, n
 
     ngx_str_t                    *value, size;
     ngx_url_t                     u;
-    ngx_uint_t                    i, backlog;
+    ngx_uint_t                    i, n, backlog;
     ngx_stream_listen_t          *ls, *als;
     ngx_stream_core_main_conf_t  *cmcf;
 
@@ -602,21 +602,17 @@ ngx_stream_core_listen(ngx_conf_t *cf, n
 
     cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
 
-    ls = ngx_array_push(&cmcf->listen);
+    ls = ngx_array_push_n(&cmcf->listen, u.naddrs);
     if (ls == NULL) {
         return NGX_CONF_ERROR;
     }
 
     ngx_memzero(ls, sizeof(ngx_stream_listen_t));
 
-    ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen);
-
-    ls->socklen = u.socklen;
     ls->backlog = NGX_LISTEN_BACKLOG;
     ls->rcvbuf = -1;
     ls->sndbuf = -1;
     ls->type = SOCK_STREAM;
-    ls->wildcard = u.wildcard;
     ls->ctx = cf->ctx;
 
 #if (NGX_HAVE_INET6)
@@ -688,35 +684,20 @@ ngx_stream_core_listen(ngx_conf_t *cf, n
 
         if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
-            size_t  len;
-            u_char  buf[NGX_SOCKADDR_STRLEN];
-
-            if (ls->sockaddr.sockaddr.sa_family == AF_INET6) {
-
-                if (ngx_strcmp(&value[i].data[10], "n") == 0) {
-                    ls->ipv6only = 1;
+            if (ngx_strcmp(&value[i].data[10], "n") == 0) {
+                ls->ipv6only = 1;
 
-                } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
-                    ls->ipv6only = 0;
-
-                } else {
-                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                                       "invalid ipv6only flags \"%s\"",
-                                       &value[i].data[9]);
-                    return NGX_CONF_ERROR;
-                }
-
-                ls->bind = 1;
+            } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
+                ls->ipv6only = 0;
 
             } else {
-                len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf,
-                                    NGX_SOCKADDR_STRLEN, 1);
-
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                                   "ipv6only is not supported "
-                                   "on addr \"%*s\", ignored", len, buf);
+                                   "invalid ipv6only flags \"%s\"",
+                                   &value[i].data[9]);
+                return NGX_CONF_ERROR;
             }
 
+            ls->bind = 1;
             continue;
 #else
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -882,21 +863,31 @@ ngx_stream_core_listen(ngx_conf_t *cf, n
 
     als = cmcf->listen.elts;
 
-    for (i = 0; i < cmcf->listen.nelts - 1; i++) {
-        if (ls->type != als[i].type) {
-            continue;
-        }
+    for (n = 0; n < u.naddrs; n++) {
+        ls[n] = ls[0];
+
+        ls[n].sockaddr = u.addrs[n].sockaddr;
+        ls[n].socklen = u.addrs[n].socklen;
+        ls[n].addr_text = u.addrs[n].name;
+        ls[n].wildcard = ngx_inet_wildcard(ls[n].sockaddr);
+
+        for (i = 0; i < cmcf->listen.nelts - u.naddrs + n; i++) {
+            if (ls[n].type != als[i].type) {
+                continue;
+            }
 
-        if (ngx_cmp_sockaddr(&als[i].sockaddr.sockaddr, als[i].socklen,
-                             &ls->sockaddr.sockaddr, ls->socklen, 1)
-            != NGX_OK)
-        {
-            continue;
+            if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
+                                 ls[n].sockaddr, ls[n].socklen, 1)
+                != NGX_OK)
+            {
+                continue;
+            }
+
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "duplicate \"%V\" address and port pair",
+                               &ls[n].addr_text);
+            return NGX_CONF_ERROR;
         }
-
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "duplicate \"%V\" address and port pair", &u.url);
-        return NGX_CONF_ERROR;
     }
 
     return NGX_CONF_OK;