diff src/http/modules/ngx_http_realip_module.c @ 540:c04fa65fe604 NGINX_0_8_22

nginx 0.8.22 *) Feature: the "proxy_bind", "fastcgi_bind", and "memcached_bind" directives. *) Feature: the "access" and the "deny" directives support IPv6. *) Feature: the "set_real_ip_from" directive supports IPv6 addresses in request headers. *) Feature: the "unix:" parameter of the "set_real_ip_from" directive. *) Bugfix: nginx did not delete unix domain socket after configuration testing. *) Bugfix: nginx deleted unix domain socket while online upgrade. *) Bugfix: the "!-x" operator did not work. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process, if limit_rate was used in HTTPS server. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process while $limit_rate logging. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault might occur in a worker process, if there was no "listen" directive in "server" block; the bug had appeared in 0.8.21.
author Igor Sysoev <http://sysoev.ru>
date Tue, 03 Nov 2009 00:00:00 +0300
parents f39b9e29530d
children 2b9e388c61f1
line wrap: on
line diff
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -25,17 +25,23 @@ typedef struct {
     ngx_uint_t         type;
     ngx_uint_t         hash;
     ngx_str_t          header;
+#if (NGX_HAVE_UNIX_DOMAIN)
+    ngx_uint_t         unixsock; /* unsigned  unixsock:1; */
+#endif
 } ngx_http_realip_loc_conf_t;
 
 
 typedef struct {
     ngx_connection_t  *connection;
-    in_addr_t          addr;
+    struct sockaddr   *sockaddr;
+    socklen_t          socklen;
     ngx_str_t          addr_text;
 } ngx_http_realip_ctx_t;
 
 
 static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip,
+    size_t len);
 static void ngx_http_realip_cleanup(void *data);
 static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
@@ -103,13 +109,11 @@ ngx_http_realip_handler(ngx_http_request
 {
     u_char                      *ip, *p;
     size_t                       len;
-    in_addr_t                    addr;
     ngx_uint_t                   i, hash;
     ngx_list_part_t             *part;
     ngx_table_elt_t             *header;
     struct sockaddr_in          *sin;
     ngx_connection_t            *c;
-    ngx_pool_cleanup_t          *cln;
     ngx_http_realip_ctx_t       *ctx;
     ngx_http_realip_from_t      *from;
     ngx_http_realip_loc_conf_t  *rlcf;
@@ -120,11 +124,6 @@ ngx_http_realip_handler(ngx_http_request
         return NGX_DECLINED;
     }
 
-    cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
-    if (cln == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
     rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
 
     if (rlcf->from == NULL) {
@@ -207,52 +206,83 @@ found:
 
     /* AF_INET only */
 
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        return NGX_DECLINED;
+    if (c->sockaddr->sa_family == AF_INET) {
+        sin = (struct sockaddr_in *) c->sockaddr;
+
+        from = rlcf->from->elts;
+        for (i = 0; i < rlcf->from->nelts; i++) {
+
+            ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                           "realip: %08XD %08XD %08XD",
+                           sin->sin_addr.s_addr, from[i].mask, from[i].addr);
+
+            if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) {
+                return ngx_http_realip_set_addr(r, ip, len);
+            }
+        }
+    }
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+    if (c->sockaddr->sa_family == AF_UNIX && rlcf->unixsock) {
+        return ngx_http_realip_set_addr(r, ip, len);
     }
 
-    sin = (struct sockaddr_in *) c->sockaddr;
+#endif
 
-    from = rlcf->from->elts;
-    for (i = 0; i < rlcf->from->nelts; i++) {
+    return NGX_DECLINED;
+}
 
-        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                       "realip: %08XD %08XD %08XD",
-                       sin->sin_addr.s_addr, from[i].mask, from[i].addr);
 
-        if ((sin->sin_addr.s_addr & from[i].mask) == from[i].addr) {
-
-            ctx = cln->data;
-
-            ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
+static ngx_int_t
+ngx_http_realip_set_addr(ngx_http_request_t *r, u_char *ip, size_t len)
+{
+    u_char                 *p;
+    ngx_int_t               rc;
+    ngx_addr_t              addr;
+    ngx_connection_t       *c;
+    ngx_pool_cleanup_t     *cln;
+    ngx_http_realip_ctx_t  *ctx;
 
-            addr = inet_addr((char *) ip);
+    cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
+    if (cln == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
 
-            if (addr == INADDR_NONE) {
-                return NGX_DECLINED;
-            }
+    ctx = cln->data;
+    ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
+
+    c = r->connection;
+
+    rc = ngx_parse_addr(c->pool, &addr, ip, len);
 
-            p = ngx_pnalloc(c->pool, len);
-            if (p == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
+    switch (rc) {
+    case NGX_DECLINED:
+        return NGX_DECLINED;
+    case NGX_ERROR:
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    default: /* NGX_OK */
+        break;
+    }
 
-            ngx_memcpy(p, ip, len);
-
-            cln->handler = ngx_http_realip_cleanup;
+    p = ngx_pnalloc(c->pool, len);
+    if (p == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
 
-            ctx->connection = c;
-            ctx->addr = sin->sin_addr.s_addr;
-            ctx->addr_text = c->addr_text;
+    ngx_memcpy(p, ip, len);
 
-            sin->sin_addr.s_addr = addr;
+    cln->handler = ngx_http_realip_cleanup;
 
-            c->addr_text.len = len;
-            c->addr_text.data = p;
+    ctx->connection = c;
+    ctx->sockaddr = c->sockaddr;
+    ctx->socklen = c->socklen;
+    ctx->addr_text = c->addr_text;
 
-            return NGX_DECLINED;
-        }
-    }
+    c->sockaddr = addr.sockaddr;
+    c->socklen = addr.socklen;
+    c->addr_text.len = len;
+    c->addr_text.data = p;
 
     return NGX_DECLINED;
 }
@@ -263,14 +293,12 @@ ngx_http_realip_cleanup(void *data)
 {
     ngx_http_realip_ctx_t *ctx = data;
 
-    ngx_connection_t    *c;
-    struct sockaddr_in  *sin;
+    ngx_connection_t  *c;
 
     c = ctx->connection;
 
-    sin = (struct sockaddr_in *) c->sockaddr;
-    sin->sin_addr.s_addr = ctx->addr;
-
+    c->sockaddr = ctx->sockaddr;
+    c->socklen = ctx->socklen;
     c->addr_text = ctx->addr_text;
 }
 
@@ -285,6 +313,17 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
     ngx_cidr_t               cidr;
     ngx_http_realip_from_t  *from;
 
+    value = cf->args->elts;
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+    if (ngx_strcmp(value[1].data, "unix:") == 0) {
+         rlcf->unixsock = 1;
+         return NGX_CONF_OK;
+    }
+
+#endif
+
     if (rlcf->from == NULL) {
         rlcf->from = ngx_array_create(cf->pool, 2,
                                       sizeof(ngx_http_realip_from_t));
@@ -298,8 +337,6 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
-    value = cf->args->elts;
-
     rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_ERROR) {
@@ -310,7 +347,7 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx
 
     if (cidr.family != AF_INET) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "\"realip_from\" supports IPv4 only");
+                           "\"set_real_ip_from\" supports IPv4 only");
         return NGX_CONF_ERROR;
     }
 
@@ -369,6 +406,7 @@ ngx_http_realip_create_loc_conf(ngx_conf
      *     conf->from = NULL;
      *     conf->hash = 0;
      *     conf->header = { 0, NULL };
+     *     conf->unixsock = 0;
      */
 
     conf->type = NGX_CONF_UNSET_UINT;
@@ -385,6 +423,9 @@ ngx_http_realip_merge_loc_conf(ngx_conf_
 
     if (conf->from == NULL) {
         conf->from = prev->from;
+#if (NGX_HAVE_UNIX_DOMAIN)
+        conf->unixsock = prev->unixsock;
+#endif
     }
 
     ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);