[nginx] Listen port ranges.

Roman Arutyunyan arut at nginx.com
Thu Mar 21 11:09:58 UTC 2019


details:   https://hg.nginx.org/nginx/rev/d9c3917c7f90
branches:  
changeset: 7480:d9c3917c7f90
user:      Roman Arutyunyan <arut at nginx.com>
date:      Wed Mar 06 20:46:09 2019 +0300
description:
Listen port ranges.

A range is specified with a dash.  For each port in a range a separate listen
socket is created.

Examples:

    listen 8080-9000;
    listen example.com:80-88;

diffstat:

 src/core/ngx_inet.c |  147 +++++++++++++++++++++++++++++++++++++++++----------
 src/core/ngx_inet.h |    1 +
 2 files changed, 119 insertions(+), 29 deletions(-)

diffs (262 lines):

diff -r 8be88b22fe81 -r d9c3917c7f90 src/core/ngx_inet.c
--- a/src/core/ngx_inet.c	Wed Mar 20 20:31:59 2019 +0300
+++ b/src/core/ngx_inet.c	Wed Mar 06 20:46:09 2019 +0300
@@ -782,7 +782,7 @@ ngx_parse_unix_domain_url(ngx_pool_t *po
 static ngx_int_t
 ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
 {
-    u_char              *host, *port, *last, *uri, *args;
+    u_char              *host, *port, *last, *uri, *args, *dash;
     size_t               len;
     ngx_int_t            n;
     struct sockaddr_in  *sin;
@@ -830,6 +830,25 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
 
         len = last - port;
 
+        if (u->listen) {
+            dash = ngx_strlchr(port, last, '-');
+
+            if (dash) {
+                dash++;
+
+                n = ngx_atoi(dash, last - dash);
+
+                if (n < 1 || n > 65535) {
+                    u->err = "invalid port";
+                    return NGX_ERROR;
+                }
+
+                u->last_port = (in_port_t) n;
+
+                len = dash - port - 1;
+            }
+        }
+
         n = ngx_atoi(port, len);
 
         if (n < 1 || n > 65535) {
@@ -837,10 +856,15 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
             return NGX_ERROR;
         }
 
+        if (u->last_port && n > u->last_port) {
+            u->err = "invalid port range";
+            return NGX_ERROR;
+        }
+
         u->port = (in_port_t) n;
         sin->sin_port = htons((in_port_t) n);
 
-        u->port_text.len = len;
+        u->port_text.len = last - port;
         u->port_text.data = port;
 
         last = port - 1;
@@ -852,15 +876,47 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
 
                 /* test value as port only */
 
-                n = ngx_atoi(host, last - host);
+                len = last - host;
+
+                dash = ngx_strlchr(host, last, '-');
+
+                if (dash) {
+                    dash++;
+
+                    n = ngx_atoi(dash, last - dash);
+
+                    if (n == NGX_ERROR) {
+                        goto no_port;
+                    }
+
+                    if (n < 1 || n > 65535) {
+                        u->err = "invalid port";
+
+                    } else {
+                        u->last_port = (in_port_t) n;
+                    }
+
+                    len = dash - host - 1;
+                }
+
+                n = ngx_atoi(host, len);
 
                 if (n != NGX_ERROR) {
 
+                    if (u->err) {
+                        return NGX_ERROR;
+                    }
+
                     if (n < 1 || n > 65535) {
                         u->err = "invalid port";
                         return NGX_ERROR;
                     }
 
+                    if (u->last_port && n > u->last_port) {
+                        u->err = "invalid port range";
+                        return NGX_ERROR;
+                    }
+
                     u->port = (in_port_t) n;
                     sin->sin_port = htons((in_port_t) n);
                     sin->sin_addr.s_addr = INADDR_ANY;
@@ -876,9 +932,13 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
             }
         }
 
+no_port:
+
+        u->err = NULL;
         u->no_port = 1;
         u->port = u->default_port;
         sin->sin_port = htons(u->default_port);
+        u->last_port = 0;
     }
 
     len = last - host;
@@ -929,7 +989,7 @@ static ngx_int_t
 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
 {
 #if (NGX_HAVE_INET6)
-    u_char               *p, *host, *port, *last, *uri;
+    u_char               *p, *host, *port, *last, *uri, *dash;
     size_t                len;
     ngx_int_t             n;
     struct sockaddr_in6  *sin6;
@@ -975,6 +1035,25 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng
 
         len = last - port;
 
+        if (u->listen) {
+            dash = ngx_strlchr(port, last, '-');
+
+            if (dash) {
+                dash++;
+
+                n = ngx_atoi(dash, last - dash);
+
+                if (n < 1 || n > 65535) {
+                    u->err = "invalid port";
+                    return NGX_ERROR;
+                }
+
+                u->last_port = (in_port_t) n;
+
+                len = dash - port - 1;
+            }
+        }
+
         n = ngx_atoi(port, len);
 
         if (n < 1 || n > 65535) {
@@ -982,10 +1061,15 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng
             return NGX_ERROR;
         }
 
+        if (u->last_port && n > u->last_port) {
+            u->err = "invalid port range";
+            return NGX_ERROR;
+        }
+
         u->port = (in_port_t) n;
         sin6->sin6_port = htons((in_port_t) n);
 
-        u->port_text.len = len;
+        u->port_text.len = last - port;
         u->port_text.data = port;
 
     } else {
@@ -1181,51 +1265,56 @@ ngx_inet_add_addr(ngx_pool_t *pool, ngx_
 {
     u_char           *p;
     size_t            len;
+    ngx_uint_t        i, nports;
     ngx_addr_t       *addr;
     struct sockaddr  *sa;
 
+    nports = u->last_port ? u->last_port - u->port + 1 : 1;
+
     if (u->addrs == NULL) {
-        u->addrs = ngx_palloc(pool, total * sizeof(ngx_addr_t));
+        u->addrs = ngx_palloc(pool, total * nports * sizeof(ngx_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
     }
 
-    sa = ngx_pcalloc(pool, socklen);
-    if (sa == NULL) {
-        return NGX_ERROR;
-    }
+    for (i = 0; i < nports; i++) {
+        sa = ngx_pcalloc(pool, socklen);
+        if (sa == NULL) {
+            return NGX_ERROR;
+        }
 
-    ngx_memcpy(sa, sockaddr, socklen);
+        ngx_memcpy(sa, sockaddr, socklen);
 
-    ngx_inet_set_port(sa, u->port);
+        ngx_inet_set_port(sa, u->port + i);
 
-    switch (sa->sa_family) {
+        switch (sa->sa_family) {
 
 #if (NGX_HAVE_INET6)
-    case AF_INET6:
-        len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1;
-        break;
+        case AF_INET6:
+            len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65536") - 1;
+            break;
 #endif
 
-    default: /* AF_INET */
-        len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
-    }
+        default: /* AF_INET */
+            len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
+        }
 
-    p = ngx_pnalloc(pool, len);
-    if (p == NULL) {
-        return NGX_ERROR;
-    }
+        p = ngx_pnalloc(pool, len);
+        if (p == NULL) {
+            return NGX_ERROR;
+        }
 
-    len = ngx_sock_ntop(sa, socklen, p, len, 1);
+        len = ngx_sock_ntop(sa, socklen, p, len, 1);
 
-    addr = &u->addrs[u->naddrs++];
+        addr = &u->addrs[u->naddrs++];
 
-    addr->sockaddr = sa;
-    addr->socklen = socklen;
+        addr->sockaddr = sa;
+        addr->socklen = socklen;
 
-    addr->name.len = len;
-    addr->name.data = p;
+        addr->name.len = len;
+        addr->name.data = p;
+    }
 
     return NGX_OK;
 }
diff -r 8be88b22fe81 -r d9c3917c7f90 src/core/ngx_inet.h
--- a/src/core/ngx_inet.h	Wed Mar 20 20:31:59 2019 +0300
+++ b/src/core/ngx_inet.h	Wed Mar 06 20:46:09 2019 +0300
@@ -86,6 +86,7 @@ typedef struct {
 
     in_port_t                 port;
     in_port_t                 default_port;
+    in_port_t                 last_port;
     int                       family;
 
     unsigned                  listen:1;


More information about the nginx-devel mailing list