Index: src/http/modules/ngx_http_realip_module.c
===================================================================
--- src/http/modules/ngx_http_realip_module.c	(revision 4232)
+++ src/http/modules/ngx_http_realip_module.c	(working copy)
@@ -19,9 +19,18 @@
     in_addr_t          addr;
 } ngx_http_realip_from_t;
 
+#if (NGX_HAVE_INET6)
+typedef struct {
+    struct in6_addr    mask;
+    struct in6_addr    addr;
+} ngx_http_realip_from6_t;
+#endif
 
 typedef struct {
     ngx_array_t       *from;     /* array of ngx_http_realip_from_t */
+#if (NGX_HAVE_INET6)
+    ngx_array_t       *from6;    /* array of ngx_http_realip_from6_t */
+#endif
     ngx_uint_t         type;
     ngx_uint_t         hash;
     ngx_str_t          header;
@@ -117,6 +126,11 @@
     ngx_http_realip_ctx_t       *ctx;
     ngx_http_realip_from_t      *from;
     ngx_http_realip_loc_conf_t  *rlcf;
+#if (NGX_HAVE_INET6)
+    ngx_uint_t                   n;
+    struct sockaddr_in6         *sin6;
+    ngx_http_realip_from6_t     *from6;
+#endif
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
 
@@ -209,8 +223,6 @@
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "realip: \"%s\"", ip);
 
-    /* AF_INET only */
-
     if (c->sockaddr->sa_family == AF_INET) {
         sin = (struct sockaddr_in *) c->sockaddr;
 
@@ -227,6 +239,26 @@
         }
     }
 
+#if (NGX_HAVE_INET6)
+    if (c->sockaddr->sa_family == AF_INET6) {
+        sin6 = (struct sockaddr_in6 *) c->sockaddr;
+
+        from6 = rlcf->from6->elts;
+        for (i = 0; i < rlcf->from6->nelts; i++) {
+            for (n = 0; n < 16; n++) {
+                if ((sin6->sin6_addr.s6_addr[n] & from6[i].mask.s6_addr[n]) != from6[i].addr.s6_addr[n]) {
+                    goto next;
+                }
+            }
+
+            return ngx_http_realip_set_addr(r, ip, len);
+
+    next:
+        continue;
+        }
+    }
+#endif
+
 #if (NGX_HAVE_UNIX_DOMAIN)
 
     if (c->sockaddr->sa_family == AF_UNIX && rlcf->unixsock) {
@@ -317,6 +349,9 @@
     ngx_str_t               *value;
     ngx_cidr_t               cidr;
     ngx_http_realip_from_t  *from;
+#if (NGX_HAVE_INET6)
+    ngx_http_realip_from6_t *from6;
+#endif
 
     value = cf->args->elts;
 
@@ -328,20 +363,7 @@
     }
 
 #endif
-
-    if (rlcf->from == NULL) {
-        rlcf->from = ngx_array_create(cf->pool, 2,
-                                      sizeof(ngx_http_realip_from_t));
-        if (rlcf->from == NULL) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    from = ngx_array_push(rlcf->from);
-    if (from == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
+    
     rc = ngx_ptocidr(&value[1], &cidr);
 
     if (rc == NGX_ERROR) {
@@ -350,20 +372,58 @@
         return NGX_CONF_ERROR;
     }
 
+#if !(NGX_HAVE_INET6)
     if (cidr.family != AF_INET) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "\"set_real_ip_from\" supports IPv4 only");
         return NGX_CONF_ERROR;
     }
+#endif
 
     if (rc == NGX_DONE) {
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                            "low address bits of %V are meaningless", &value[1]);
     }
 
-    from->mask = cidr.u.in.mask;
-    from->addr = cidr.u.in.addr;
+    switch (cidr.family) {
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        if (rlcf->from6 == NULL) {
+            rlcf->from6 = ngx_array_create(cf->pool, 2,
+                                           sizeof(ngx_http_realip_from6_t));
+            if (rlcf->from6 == NULL) {
+                return NGX_CONF_ERROR;
+            }
+        }
 
+        from6 = ngx_array_push(rlcf->from6);
+        if (from6 == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        from6->addr = cidr.u.in6.addr;
+        from6->mask = cidr.u.in6.mask;
+        break;
+#endif
+
+    default: /* AF_INET */
+        if (rlcf->from == NULL) {
+            rlcf->from = ngx_array_create(cf->pool, 2,
+                                          sizeof(ngx_http_realip_from_t));
+            if (rlcf->from == NULL) {
+                return NGX_CONF_ERROR;
+            }
+        }
+
+        from = ngx_array_push(rlcf->from);
+        if (from == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        from->addr = cidr.u.in.addr;
+        from->mask = cidr.u.in.mask;
+    }
+
     return NGX_CONF_OK;
 }
 
@@ -432,6 +492,12 @@
         conf->from = prev->from;
     }
 
+#if (NGX_HAVE_INET6)
+    if (conf->from6 == NULL) {
+        conf->from6 = prev->from6;
+    }
+#endif
+
 #if (NGX_HAVE_UNIX_DOMAIN)
     if (conf->unixsock == 2) {
         conf->unixsock = (prev->unixsock == 2) ? 0 : prev->unixsock;
