changeset 2537:a472d954c534

prepare ngx_ptocidr() for IPv6
author Igor Sysoev <igor@sysoev.ru>
date Tue, 24 Feb 2009 14:01:40 +0000
parents a6d6d762c554
children c5bbb6164630
files src/core/ngx_inet.c src/core/ngx_inet.h src/event/ngx_event.c src/http/modules/ngx_http_access_module.c src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_realip_module.c
diffstat 6 files changed, 115 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -226,26 +226,25 @@ ngx_inet6_ntop(u_char *p, u_char *text, 
 /* AF_INET only */
 
 ngx_int_t
-ngx_ptocidr(ngx_str_t *text, void *cidr)
+ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
 {
-    u_char           *addr, *mask, *last;
-    ngx_int_t         shift;
-    ngx_inet_cidr_t  *in_cidr;
+    u_char     *addr, *mask, *last;
+    ngx_int_t   shift;
 
-    in_cidr = cidr;
     addr = text->data;
     last = addr + text->len;
 
     mask = ngx_strlchr(addr, last, '/');
 
-    in_cidr->addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
+    cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
 
-    if (in_cidr->addr == INADDR_NONE) {
+    if (cidr->u.in.addr == INADDR_NONE) {
         return NGX_ERROR;
     }
 
     if (mask == NULL) {
-        in_cidr->mask = 0xffffffff;
+        cidr->family = AF_INET;
+        cidr->u.in.mask = 0xffffffff;
         return NGX_OK;
     }
 
@@ -256,26 +255,28 @@ ngx_ptocidr(ngx_str_t *text, void *cidr)
         return NGX_ERROR;
     }
 
+    cidr->family = AF_INET;
+
     if (shift == 0) {
 
         /* the x86 compilers use the shl instruction that shifts by modulo 32 */
 
-        in_cidr->mask = 0;
+        cidr->u.in.mask = 0;
 
-        if (in_cidr->addr == 0) {
+        if (cidr->u.in.addr == 0) {
             return NGX_OK;
         }
 
         return NGX_DONE;
     }
 
-    in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
+    cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
 
-    if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) {
+    if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
         return NGX_OK;
     }
 
-    in_cidr->addr &= in_cidr->mask;
+    cidr->u.in.addr &= cidr->u.in.mask;
 
     return NGX_DONE;
 }
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -35,50 +35,71 @@
 
 
 typedef struct {
-    in_addr_t         addr;
-    in_addr_t         mask;
-} ngx_inet_cidr_t;
+    struct in6_addr           addr;
+    struct in6_addr           mask;
+} ngx_in6_cidr_t;
+
+
+#if (NGX_HAVE_INET6)
+
+typedef struct {
+    in_addr_t                 addr;
+    in_addr_t                 mask;
+} ngx_in_cidr_t;
+
+#endif
+
+
+typedef struct {
+    ngx_uint_t                family;
+    union {
+        ngx_in_cidr_t         in;
+#if (NGX_HAVE_INET6)
+        ngx_in6_cidr_t        in6;
+#endif
+    } u;
+} ngx_cidr_t;
 
 
 typedef union {
-    in_addr_t         in_addr;
+    in_addr_t                 in_addr;
 } ngx_url_addr_t;
 
 
 typedef struct {
-    struct sockaddr  *sockaddr;
-    socklen_t         socklen;
-    ngx_str_t         name;
+    struct sockaddr          *sockaddr;
+    socklen_t                 socklen;
+    ngx_str_t                 name;
 } ngx_peer_addr_t;
 
 
 typedef struct {
-    ngx_str_t         url;
-    ngx_str_t         host;
-    ngx_str_t         port_text;
-    ngx_str_t         uri;
+    ngx_str_t                 url;
+    ngx_str_t                 host;
+    ngx_str_t                 port_text;
+    ngx_str_t                 uri;
 
-    in_port_t         port;
-    in_port_t         default_port;
-    int               family;
+    in_port_t                 port;
+    in_port_t                 default_port;
+    int                       family;
 
-    unsigned          listen:1;
-    unsigned          uri_part:1;
-    unsigned          no_resolve:1;
-    unsigned          one_addr:1;
+    unsigned                  listen:1;
+    unsigned                  uri_part:1;
+    unsigned                  no_resolve:1;
+    unsigned                  one_addr:1;
 
-    unsigned          no_port:1;
-    unsigned          wildcard:1;
+    unsigned                  no_port:1;
+    unsigned                  wildcard:1;
 
-    ngx_url_addr_t    addr;
+    ngx_url_addr_t            addr;
 
-    socklen_t         socklen;
-    u_char            sockaddr[NGX_SOCKADDRLEN];
+    socklen_t                 socklen;
+    u_char                    sockaddr[NGX_SOCKADDRLEN];
 
-    ngx_peer_addr_t  *addrs;
-    ngx_uint_t        naddrs;
+    ngx_peer_addr_t          *addrs;
+    ngx_uint_t                naddrs;
 
-    char             *err;
+    char                     *err;
 } ngx_url_t;
 
 
@@ -86,7 +107,7 @@ in_addr_t ngx_inet_addr(u_char *text, si
 size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
     ngx_uint_t port);
 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
-ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr);
+ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
 ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
 ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
 
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -1040,18 +1040,16 @@ ngx_event_debug_connection(ngx_conf_t *c
     ngx_str_t          *value;
     ngx_event_debug_t  *dc;
     struct hostent     *h;
-    ngx_inet_cidr_t     in_cidr;
+    ngx_cidr_t          cidr;
 
     value = cf->args->elts;
 
-    /* AF_INET only */
-
     dc = ngx_array_push(&ecf->debug_connection);
     if (dc == NULL) {
         return NGX_CONF_ERROR;
     }
 
-    rc = ngx_ptocidr(&value[1], &in_cidr);
+    rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_DONE) {
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
@@ -1060,8 +1058,18 @@ ngx_event_debug_connection(ngx_conf_t *c
     }
 
     if (rc == NGX_OK) {
-        dc->mask = in_cidr.mask;
-        dc->addr = in_cidr.addr;
+
+        /* AF_INET only */
+
+        if (cidr.family != AF_INET) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "\"debug_connection\" supports IPv4 only");
+            return NGX_CONF_ERROR;
+        }
+
+        dc->mask = cidr.u.in.mask;
+        dc->addr = cidr.u.in.addr;
+
         return NGX_CONF_OK;
     }
 
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -141,7 +141,7 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx
 
     ngx_int_t                rc;
     ngx_str_t               *value;
-    ngx_inet_cidr_t          in_cidr;
+    ngx_cidr_t               cidr;
     ngx_http_access_rule_t  *rule;
 
     if (alcf->rules == NULL) {
@@ -168,7 +168,7 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx
         return NGX_CONF_OK;
     }
 
-    rc = ngx_ptocidr(&value[1], &in_cidr);
+    rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_ERROR) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@@ -176,13 +176,19 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
+    if (cidr.family != AF_INET) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"allow\" supports IPv4 only");
+        return NGX_CONF_ERROR;
+    }
+
     if (rc == NGX_DONE) {
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                            "low address bits of %V are meaningless", &value[1]);
     }
 
-    rule->mask = in_cidr.mask;
-    rule->addr = in_cidr.addr;
+    rule->mask = cidr.u.in.mask;
+    rule->addr = cidr.u.in.addr;
 
     return NGX_CONF_OK;
 }
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -778,7 +778,7 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
     ngx_int_t                        rc, del;
     ngx_str_t                       *net;
     ngx_uint_t                       i;
-    ngx_inet_cidr_t                  cidrin;
+    ngx_cidr_t                       cidr;
     ngx_http_variable_value_t       *val, *old;
 
     if (ctx->tree == NULL) {
@@ -789,8 +789,8 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
     }
 
     if (ngx_strcmp(value[0].data, "default") == 0) {
-        cidrin.addr = 0;
-        cidrin.mask = 0;
+        cidr.u.in.addr = 0;
+        cidr.u.in.mask = 0;
         net = &value[0];
 
     } else {
@@ -804,11 +804,11 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
         }
 
         if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
-            cidrin.addr = 0xffffffff;
-            cidrin.mask = 0xffffffff;
+            cidr.u.in.addr = 0xffffffff;
+            cidr.u.in.mask = 0xffffffff;
 
         } else {
-            rc = ngx_ptocidr(net, &cidrin);
+            rc = ngx_ptocidr(net, &cidr);
 
             if (rc == NGX_ERROR) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -816,18 +816,25 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
                 return NGX_CONF_ERROR;
             }
 
+            if (cidr.family != AF_INET) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "\"geo\" supports IPv4 only");
+                return NGX_CONF_ERROR;
+            }
+
             if (rc == NGX_DONE) {
                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                                    "low address bits of %V are meaningless",
                                    net);
             }
 
-            cidrin.addr = ntohl(cidrin.addr);
-            cidrin.mask = ntohl(cidrin.mask);
+            cidr.u.in.addr = ntohl(cidr.u.in.addr);
+            cidr.u.in.mask = ntohl(cidr.u.in.mask);
         }
 
         if (del) {
-            if (ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask)
+            if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
+                                       cidr.u.in.mask)
                 != NGX_OK)
             {
                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
@@ -845,7 +852,7 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
     }
 
     for (i = 2; i; i--) {
-        rc = ngx_radix32tree_insert(ctx->tree, cidrin.addr, cidrin.mask,
+        rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask,
                                     (uintptr_t) val);
         if (rc == NGX_OK) {
             return NGX_CONF_OK;
@@ -858,13 +865,13 @@ ngx_http_geo_cidr(ngx_conf_t *cf, ngx_ht
         /* rc == NGX_BUSY */
 
         old  = (ngx_http_variable_value_t *)
-                   ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask);
+              ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask);
 
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
                 net, val, old);
 
-        rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask);
+        rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask);
 
         if (rc == NGX_ERROR) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -282,7 +282,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
 
     ngx_int_t                rc;
     ngx_str_t               *value;
-    ngx_inet_cidr_t          in_cidr;
+    ngx_cidr_t               cidr;
     ngx_http_realip_from_t  *from;
 
     if (rlcf->from == NULL) {
@@ -300,7 +300,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
 
     value = cf->args->elts;
 
-    rc = ngx_ptocidr(&value[1], &in_cidr);
+    rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_ERROR) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
@@ -308,13 +308,19 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
+    if (cidr.family != AF_INET) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"realip_from\" supports IPv4 only");
+        return NGX_CONF_ERROR;
+    }
+
     if (rc == NGX_DONE) {
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                            "low address bits of %V are meaningless", &value[1]);
     }
 
-    from->mask = in_cidr.mask;
-    from->addr = in_cidr.addr;
+    from->mask = cidr.u.in.mask;
+    from->addr = cidr.u.in.addr;
 
     return NGX_CONF_OK;
 }