summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2011-05-25 14:55:59 +0000
committerJonathan Kolb <jon@b0g.us>2011-05-25 14:55:59 +0000
commit05db4154017269f45cc8742ca187855e1331b08d (patch)
treeb39f6526ef879ba55c0d334385cdded679fab736
parent1b122b0876a0f0e1efcb4be6d730f353b04759ea (diff)
downloadnginx-05db4154017269f45cc8742ca187855e1331b08d.tar.gz
Changes with nginx 1.0.3 25 May 2011v1.0.3
*) Feature: the "auth_basic_user_file" directive supports "$apr1", "{PLAIN}", and "{SSHA}" password encryption methods. Thanks to Maxim Dounin. *) Feature: the "geoip_org" directive and $geoip_org variable. Thanks to Alexander Uskov, Arnaud Granal, and Denis F. Latypoff. *) Feature: ngx_http_geo_module and ngx_http_geoip_module support IPv4 addresses mapped to IPv6 addresses. *) Bugfix: a segmentation fault occurred in a worker process during testing IPv4 address mapped to IPv6 address, if access or deny rules were defined only for IPv6; the bug had appeared in 0.8.22. *) Bugfix: a cached reponse may be broken if proxy/fastcgi/scgi/ uwsgi_cache_bypass and proxy/fastcgi/scgi/uwsgi_no_cache directive values were different; the bug had appeared in 0.8.46.
-rw-r--r--CHANGES21
-rw-r--r--CHANGES.ru22
-rw-r--r--auto/feature6
-rw-r--r--auto/lib/conf1
-rw-r--r--auto/lib/sha1/conf3
-rw-r--r--auto/modules2
-rw-r--r--auto/sources6
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_crypt.c234
-rw-r--r--src/core/ngx_crypt.h19
-rw-r--r--src/http/modules/ngx_http_access_module.c31
-rw-r--r--src/http/modules/ngx_http_auth_basic_module.c1
-rw-r--r--src/http/modules/ngx_http_geo_module.c32
-rw-r--r--src/http/modules/ngx_http_geoip_module.c164
-rw-r--r--src/http/modules/ngx_http_split_clients_module.c2
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http_file_cache.c4
-rw-r--r--src/http/ngx_http_upstream.c38
-rw-r--r--src/os/unix/ngx_user.c4
-rw-r--r--src/os/unix/ngx_user.h2
20 files changed, 525 insertions, 73 deletions
diff --git a/CHANGES b/CHANGES
index fc2bb213d..d150d0c2b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,25 @@
+Changes with nginx 1.0.3 25 May 2011
+
+ *) Feature: the "auth_basic_user_file" directive supports "$apr1",
+ "{PLAIN}", and "{SSHA}" password encryption methods.
+ Thanks to Maxim Dounin.
+
+ *) Feature: the "geoip_org" directive and $geoip_org variable.
+ Thanks to Alexander Uskov, Arnaud Granal, and Denis F. Latypoff.
+
+ *) Feature: ngx_http_geo_module and ngx_http_geoip_module support IPv4
+ addresses mapped to IPv6 addresses.
+
+ *) Bugfix: a segmentation fault occurred in a worker process during
+ testing IPv4 address mapped to IPv6 address, if access or deny rules
+ were defined only for IPv6; the bug had appeared in 0.8.22.
+
+ *) Bugfix: a cached reponse may be broken if proxy/fastcgi/scgi/
+ uwsgi_cache_bypass and proxy/fastcgi/scgi/uwsgi_no_cache directive
+ values were different; the bug had appeared in 0.8.46.
+
+
Changes with nginx 1.0.2 10 May 2011
*) Feature: now shared zones and caches use POSIX semaphores.
diff --git a/CHANGES.ru b/CHANGES.ru
index 78bbb9b17..6317e2b65 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,26 @@
+Изменения в nginx 1.0.3 25.05.2011
+
+ *) Добавление: директива auth_basic_user_file поддерживает шифрование
+ пароля методами "$apr1", "{PLAIN}" и "{SSHA}".
+ Спасибо Максиму Дунину.
+
+ *) Добавление: директива geoip_org и переменная $geoip_org.
+ Спасибо Александру Ускову, Arnaud Granal и Денису Латыпову.
+
+ *) Добавление: модули ngx_http_geo_module и ngx_http_geoip_module
+ поддерживают адреса IPv4, отображённые на IPv6 адреса.
+
+ *) Исправление: при проверке адреса IPv4, отображённого на адрес IPv6,
+ в рабочем процессе происходил segmentation fault, если директивы
+ access или deny были определены только для адресов IPv6; ошибка
+ появилась в 0.8.22.
+
+ *) Исправление: закэшированный ответ мог быть испорчен, если значения
+ директив proxy/fastcgi/scgi/uwsgi_cache_bypass и proxy/fastcgi/scgi/
+ uwsgi_no_cache были разными; ошибка появилась в 0.8.46.
+
+
Изменения в nginx 1.0.2 10.05.2011
*) Добавление: теперь разделяемые зоны и кэши используют семафоры POSIX.
diff --git a/auto/feature b/auto/feature
index 0f9becc3b..98e757caf 100644
--- a/auto/feature
+++ b/auto/feature
@@ -52,7 +52,7 @@ if [ -x $NGX_AUTOTEST ]; then
yes)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
- if /bin/sh -c $NGX_AUTOTEST >/dev/null 2>&1; then
+ if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
@@ -67,7 +67,7 @@ if [ -x $NGX_AUTOTEST ]; then
value)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
- if /bin/sh -c $NGX_AUTOTEST >/dev/null 2>&1; then
+ if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " found"
ngx_found=yes
@@ -85,7 +85,7 @@ END
bug)
# /bin/sh is used to intercept "Killed" or "Abort trap" messages
- if /bin/sh -c $NGX_AUTOTEST >/dev/null 2>&1; then
+ if /bin/sh -c $NGX_AUTOTEST >> $NGX_AUTOCONF_ERR 2>&1; then
echo " not found"
else
diff --git a/auto/lib/conf b/auto/lib/conf
index f89d922f8..357e7810d 100644
--- a/auto/lib/conf
+++ b/auto/lib/conf
@@ -43,6 +43,7 @@ if [ $USE_SHA1 = YES ]; then
if [ $USE_OPENSSL = YES ]; then
have=NGX_HAVE_OPENSSL_SHA1_H . auto/have
+ have=NGX_HAVE_SHA1 . auto/have
SHA1=YES
SHA1_LIB=OpenSSL
diff --git a/auto/lib/sha1/conf b/auto/lib/sha1/conf
index 888537779..af3d3fba2 100644
--- a/auto/lib/sha1/conf
+++ b/auto/lib/sha1/conf
@@ -4,6 +4,7 @@
if [ $SHA1 != NONE ]; then
+ have=NGX_HAVE_SHA1 . auto/have
CORE_INCS="$CORE_INCS $SHA1"
case "$NGX_CC_NAME" in
@@ -41,7 +42,7 @@ else
# FreeBSD
ngx_feature="sha1 in system md library"
- ngx_feature_name=
+ ngx_feature_name=NGX_HAVE_SHA1
ngx_feature_run=no
ngx_feature_incs="#include <sha.h>"
ngx_feature_path=
diff --git a/auto/modules b/auto/modules
index 9ac1ddd07..80c557c2b 100644
--- a/auto/modules
+++ b/auto/modules
@@ -197,6 +197,8 @@ if [ $HTTP_RANDOM_INDEX = YES ]; then
fi
if [ $HTTP_AUTH_BASIC = YES ]; then
+ USE_MD5=YES
+ USE_SHA1=YES
have=NGX_CRYPT . auto/have
HTTP_MODULES="$HTTP_MODULES $HTTP_AUTH_BASIC_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_AUTH_BASIC_SRCS"
diff --git a/auto/sources b/auto/sources
index 07809baae..0ab99440c 100644
--- a/auto/sources
+++ b/auto/sources
@@ -34,7 +34,8 @@ CORE_DEPS="src/core/nginx.h \
src/core/ngx_cycle.h \
src/core/ngx_conf_file.h \
src/core/ngx_resolver.h \
- src/core/ngx_open_file_cache.h"
+ src/core/ngx_open_file_cache.h \
+ src/core/ngx_crypt.h"
CORE_SRCS="src/core/nginx.c \
@@ -64,7 +65,8 @@ CORE_SRCS="src/core/nginx.c \
src/core/ngx_cpuinfo.c \
src/core/ngx_conf_file.c \
src/core/ngx_resolver.c \
- src/core/ngx_open_file_cache.c"
+ src/core/ngx_open_file_cache.c \
+ src/core/ngx_crypt.c"
REGEX_DEPS=src/core/ngx_regex.h
diff --git a/src/core/nginx.h b/src/core/nginx.h
index c2e56221f..2874fe233 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1000002
-#define NGINX_VERSION "1.0.2"
+#define nginx_version 1000003
+#define NGINX_VERSION "1.0.3"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_crypt.c b/src/core/ngx_crypt.c
new file mode 100644
index 000000000..2538cfcf4
--- /dev/null
+++ b/src/core/ngx_crypt.c
@@ -0,0 +1,234 @@
+
+/*
+ * Copyright (C) Maxim Dounin
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_md5.h>
+#if (NGX_HAVE_SHA1)
+#include <ngx_sha1.h>
+#endif
+
+
+static ngx_int_t ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt,
+ u_char **encrypted);
+static ngx_int_t ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt,
+ u_char **encrypted);
+
+#if (NGX_HAVE_SHA1)
+
+static ngx_int_t ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt,
+ u_char **encrypted);
+
+#endif
+
+
+static u_char *ngx_crypt_to64(u_char *p, uint32_t v, size_t n);
+
+
+ngx_int_t
+ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
+{
+ if (ngx_strncmp(salt, "$apr1$", sizeof("$apr1$") - 1) == 0) {
+ return ngx_crypt_apr1(pool, key, salt, encrypted);
+
+ } else if (ngx_strncmp(salt, "{PLAIN}", sizeof("{PLAIN}") - 1) == 0) {
+ return ngx_crypt_plain(pool, key, salt, encrypted);
+
+#if (NGX_HAVE_SHA1)
+ } else if (ngx_strncmp(salt, "{SSHA}", sizeof("{SSHA}") - 1) == 0) {
+ return ngx_crypt_ssha(pool, key, salt, encrypted);
+#endif
+ }
+
+ /* fallback to libc crypt() */
+
+ return ngx_libc_crypt(pool, key, salt, encrypted);
+}
+
+
+static ngx_int_t
+ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
+{
+ ngx_int_t n;
+ ngx_uint_t i;
+ u_char *p, *last, final[16];
+ size_t saltlen, keylen;
+ ngx_md5_t md5, ctx1;
+
+ /* Apache's apr1 crypt is Paul-Henning Kamp's md5 crypt with $apr1$ magic */
+
+ keylen = ngx_strlen(key);
+
+ /* true salt: no magic, max 8 chars, stop at first $ */
+
+ salt += sizeof("$apr1$") - 1;
+ last = salt + 8;
+ for (p = salt; *p && *p != '$' && p < last; p++) { /* void */ }
+ saltlen = p - salt;
+
+ /* hash key and salt */
+
+ ngx_md5_init(&md5);
+ ngx_md5_update(&md5, key, keylen);
+ ngx_md5_update(&md5, "$apr1$", sizeof("$apr1$") - 1);
+ ngx_md5_update(&md5, salt, saltlen);
+
+ ngx_md5_init(&ctx1);
+ ngx_md5_update(&ctx1, key, keylen);
+ ngx_md5_update(&ctx1, salt, saltlen);
+ ngx_md5_update(&ctx1, key, keylen);
+ ngx_md5_final(final, &ctx1);
+
+ for (n = keylen; n > 0; n -= 16) {
+ ngx_md5_update(&md5, final, n > 16 ? 16 : n);
+ }
+
+ ngx_memzero(final, sizeof(final));
+
+ for (i = keylen; i; i >>= 1) {
+ if (i & 1) {
+ ngx_md5_update(&md5, final, 1);
+
+ } else {
+ ngx_md5_update(&md5, key, 1);
+ }
+ }
+
+ ngx_md5_final(final, &md5);
+
+ for (i = 0; i < 1000; i++) {
+ ngx_md5_init(&ctx1);
+
+ if (i & 1) {
+ ngx_md5_update(&ctx1, key, keylen);
+
+ } else {
+ ngx_md5_update(&ctx1, final, 16);
+ }
+
+ if (i % 3) {
+ ngx_md5_update(&ctx1, salt, saltlen);
+ }
+
+ if (i % 7) {
+ ngx_md5_update(&ctx1, key, keylen);
+ }
+
+ if (i & 1) {
+ ngx_md5_update(&ctx1, final, 16);
+
+ } else {
+ ngx_md5_update(&ctx1, key, keylen);
+ }
+
+ ngx_md5_final(final, &ctx1);
+ }
+
+ /* output */
+
+ *encrypted = ngx_pnalloc(pool, sizeof("$apr1$") - 1 + saltlen + 16 + 1);
+ if (*encrypted == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = ngx_cpymem(*encrypted, "$apr1$", sizeof("$apr1$") - 1);
+ p = ngx_copy(p, salt, saltlen);
+ *p++ = '$';
+
+ p = ngx_crypt_to64(p, (final[ 0]<<16) | (final[ 6]<<8) | final[12], 4);
+ p = ngx_crypt_to64(p, (final[ 1]<<16) | (final[ 7]<<8) | final[13], 4);
+ p = ngx_crypt_to64(p, (final[ 2]<<16) | (final[ 8]<<8) | final[14], 4);
+ p = ngx_crypt_to64(p, (final[ 3]<<16) | (final[ 9]<<8) | final[15], 4);
+ p = ngx_crypt_to64(p, (final[ 4]<<16) | (final[10]<<8) | final[ 5], 4);
+ p = ngx_crypt_to64(p, final[11], 2);
+ *p = '\0';
+
+ return NGX_OK;
+}
+
+
+static u_char *
+ngx_crypt_to64(u_char *p, uint32_t v, size_t n)
+{
+ static u_char itoa64[] =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ while (n--) {
+ *p++ = itoa64[v & 0x3f];
+ v >>= 6;
+ }
+
+ return p;
+}
+
+
+static ngx_int_t
+ngx_crypt_plain(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
+{
+ size_t len;
+ u_char *p;
+
+ len = ngx_strlen(key);
+
+ *encrypted = ngx_pnalloc(pool, sizeof("{PLAIN}") - 1 + len + 1);
+ if (*encrypted == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = ngx_cpymem(*encrypted, "{PLAIN}", sizeof("{PLAIN}") - 1);
+ ngx_memcpy(p, key, len + 1);
+
+ return NGX_OK;
+}
+
+
+#if (NGX_HAVE_SHA1)
+
+static ngx_int_t
+ngx_crypt_ssha(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
+{
+ size_t len;
+ ngx_str_t encoded, decoded;
+ ngx_sha1_t sha1;
+
+ /* "{SSHA}" base64(SHA1(key salt) salt) */
+
+ /* decode base64 salt to find out true salt */
+
+ encoded.data = salt + sizeof("{SSHA}") - 1;
+ encoded.len = ngx_strlen(encoded.data);
+
+ decoded.data = ngx_pnalloc(pool, ngx_base64_decoded_length(encoded.len));
+ if (decoded.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_decode_base64(&decoded, &encoded);
+
+ /* update SHA1 from key and salt */
+
+ ngx_sha1_init(&sha1);
+ ngx_sha1_update(&sha1, key, ngx_strlen(key));
+ ngx_sha1_update(&sha1, decoded.data + 20, decoded.len - 20);
+ ngx_sha1_final(decoded.data, &sha1);
+
+ /* encode it back to base64 */
+
+ len = sizeof("{SSHA}") - 1 + ngx_base64_encoded_length(decoded.len) + 1;
+
+ *encrypted = ngx_pnalloc(pool, len);
+ if (*encrypted == NULL) {
+ return NGX_ERROR;
+ }
+
+ encoded.data = ngx_cpymem(*encrypted, "{SSHA}", sizeof("{SSHA}") - 1);
+ ngx_encode_base64(&encoded, &decoded);
+ encoded.data[encoded.len] = '\0';
+
+ return NGX_OK;
+}
+
+#endif /* NGX_HAVE_SHA1 */
diff --git a/src/core/ngx_crypt.h b/src/core/ngx_crypt.h
new file mode 100644
index 000000000..45ef81d4b
--- /dev/null
+++ b/src/core/ngx_crypt.h
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_CRYPT_H_INCLUDED_
+#define _NGX_CRYPT_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+ngx_int_t ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
+ u_char **encrypted);
+
+
+#endif /* _NGX_CRYPT_H_INCLUDED_ */
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index bfc36e9bf..a28ebf7b7 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -108,20 +108,30 @@ ngx_http_access_handler(ngx_http_request_t *r)
{
struct sockaddr_in *sin;
ngx_http_access_loc_conf_t *alcf;
+#if (NGX_HAVE_INET6)
+ u_char *p;
+ in_addr_t addr;
+ struct sockaddr_in6 *sin6;
+#endif
alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module);
-#if (NGX_HAVE_INET6)
+ switch (r->connection->sockaddr->sa_family) {
+
+ case AF_INET:
+ if (alcf->rules) {
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
+ return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr);
+ }
+ break;
- if (alcf->rules6 && r->connection->sockaddr->sa_family == AF_INET6) {
- u_char *p;
- in_addr_t addr;
- struct sockaddr_in6 *sin6;
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
p = sin6->sin6_addr.s6_addr;
- if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ if (alcf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
addr = p[12] << 24;
addr += p[13] << 16;
addr += p[14] << 8;
@@ -129,14 +139,11 @@ ngx_http_access_handler(ngx_http_request_t *r)
return ngx_http_access_inet(r, alcf, htonl(addr));
}
- return ngx_http_access_inet6(r, alcf, p);
- }
+ if (alcf->rules6) {
+ return ngx_http_access_inet6(r, alcf, p);
+ }
#endif
-
- if (alcf->rules && r->connection->sockaddr->sa_family == AF_INET) {
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr);
}
return NGX_DECLINED;
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c
index c6b7f92f1..45168de84 100644
--- a/src/http/modules/ngx_http_auth_basic_module.c
+++ b/src/http/modules/ngx_http_auth_basic_module.c
@@ -7,6 +7,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
+#include <ngx_crypt.h>
#define NGX_HTTP_AUTH_BUF_SIZE 2048
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index e60f1f4fb..7c5019605 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -257,17 +257,41 @@ ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
{
struct sockaddr_in *sin;
ngx_http_variable_value_t *v;
+#if (NGX_HAVE_INET6)
+ u_char *p;
+ in_addr_t addr;
+ struct sockaddr_in6 *sin6;
+#endif
if (ctx->index == -1) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http geo started: %V", &r->connection->addr_text);
- if (r->connection->sockaddr->sa_family != AF_INET) {
- return 0;
+ switch (r->connection->sockaddr->sa_family) {
+
+ case AF_INET:
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
+ return ntohl(sin->sin_addr.s_addr);
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ p = sin6->sin6_addr.s6_addr;
+ addr = p[12] << 24;
+ addr += p[13] << 16;
+ addr += p[14] << 8;
+ addr += p[15];
+
+ return addr;
+ }
+
+#endif
}
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- return ntohl(sin->sin_addr.s_addr);
+ return INADDR_NONE;
}
v = ngx_http_get_flushed_variable(r, ctx->index);
diff --git a/src/http/modules/ngx_http_geoip_module.c b/src/http/modules/ngx_http_geoip_module.c
index 34140a198..311a30ce3 100644
--- a/src/http/modules/ngx_http_geoip_module.c
+++ b/src/http/modules/ngx_http_geoip_module.c
@@ -14,6 +14,7 @@
typedef struct {
GeoIP *country;
+ GeoIP *org;
GeoIP *city;
} ngx_http_geoip_conf_t;
@@ -28,6 +29,8 @@ typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
@@ -42,6 +45,8 @@ static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static void ngx_http_geoip_cleanup(void *data);
@@ -56,6 +61,13 @@ static ngx_command_t ngx_http_geoip_commands[] = {
0,
NULL },
+ { ngx_string("geoip_org"),
+ NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
+ ngx_http_geoip_org,
+ NGX_HTTP_MAIN_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("geoip_city"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
ngx_http_geoip_city,
@@ -112,6 +124,10 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = {
ngx_http_geoip_country_variable,
(uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
+ { ngx_string("geoip_org"), NULL,
+ ngx_http_geoip_org_variable,
+ (uintptr_t) GeoIP_name_by_ipnum, 0, 0 },
+
{ ngx_string("geoip_city_continent_code"), NULL,
ngx_http_geoip_city_variable,
offsetof(GeoIPRecord, continent_code), 0, 0 },
@@ -164,6 +180,44 @@ static ngx_http_variable_t ngx_http_geoip_vars[] = {
};
+static u_long
+ngx_http_geoip_addr(ngx_http_request_t *r)
+{
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ u_char *p;
+ u_long addr;
+ struct sockaddr_in6 *sin6;
+#endif
+
+ switch (r->connection->sockaddr->sa_family) {
+
+ case AF_INET:
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
+ return ntohl(sin->sin_addr.s_addr);
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ p = sin6->sin6_addr.s6_addr;
+ addr = p[12] << 24;
+ addr += p[13] << 16;
+ addr += p[14] << 8;
+ addr += p[15];
+
+ return addr;
+ }
+
+#endif
+ }
+
+ return INADDR_NONE;
+}
+
+
static ngx_int_t
ngx_http_geoip_country_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
@@ -171,9 +225,7 @@ ngx_http_geoip_country_variable(ngx_http_request_t *r,
ngx_http_geoip_variable_handler_pt handler =
(ngx_http_geoip_variable_handler_pt) data;
- u_long addr;
const char *val;
- struct sockaddr_in *sin;
ngx_http_geoip_conf_t *gcf;
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
@@ -182,14 +234,45 @@ ngx_http_geoip_country_variable(ngx_http_request_t *r,
goto not_found;
}
- if (r->connection->sockaddr->sa_family != AF_INET) {
+ val = handler(gcf->country, ngx_http_geoip_addr(r));
+
+ if (val == NULL) {
goto not_found;
}
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- addr = ntohl(sin->sin_addr.s_addr);
+ v->len = ngx_strlen(val);
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) val;
+
+ return NGX_OK;
- val = handler(gcf->country, addr);
+not_found:
+
+ v->not_found = 1;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_geoip_org_variable(ngx_http_request_t *r,
+ ngx_http_variable_value_t *v, uintptr_t data)
+{
+ ngx_http_geoip_variable_handler_pt handler =
+ (ngx_http_geoip_variable_handler_pt) data;
+
+ const char *val;
+ ngx_http_geoip_conf_t *gcf;
+
+ gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+
+ if (gcf->org == NULL) {
+ goto not_found;
+ }
+
+ val = handler(gcf->org, ngx_http_geoip_addr(r));
if (val == NULL) {
goto not_found;
@@ -364,18 +447,12 @@ ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
static GeoIPRecord *
ngx_http_geoip_get_city_record(ngx_http_request_t *r)
{
- u_long addr;
- struct sockaddr_in *sin;
ngx_http_geoip_conf_t *gcf;
gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
- if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) {
-
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- addr = ntohl(sin->sin_addr.s_addr);
-
- return GeoIP_record_by_ipnum(gcf->city, addr);
+ if (gcf->city) {
+ return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r));
}
return NULL;
@@ -441,7 +518,7 @@ ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (gcf->country == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "GeoIO_open(\"%V\") failed", &value[1]);
+ "GeoIP_open(\"%V\") failed", &value[1]);
return NGX_CONF_ERROR;
}
@@ -475,6 +552,57 @@ ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
+ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_geoip_conf_t *gcf = conf;
+
+ ngx_str_t *value;
+
+ if (gcf->org) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+
+ gcf->org = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
+
+ if (gcf->org == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "GeoIP_open(\"%V\") failed", &value[1]);
+
+ return NGX_CONF_ERROR;
+ }
+
+ if (cf->args->nelts == 3) {
+ if (ngx_strcmp(value[2].data, "utf8") == 0) {
+ GeoIP_set_charset (gcf->org, GEOIP_CHARSET_UTF8);
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter \"%V\"", &value[2]);
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ switch (gcf->org->databaseType) {
+
+ case GEOIP_ISP_EDITION:
+ case GEOIP_ORG_EDITION:
+ case GEOIP_DOMAIN_EDITION:
+ case GEOIP_ASNUM_EDITION:
+
+ return NGX_CONF_OK;
+
+ default:
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid GeoIP database \"%V\" type:%d",
+ &value[1], gcf->org->databaseType);
+ return NGX_CONF_ERROR;
+ }
+}
+
+
+static char *
ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_geoip_conf_t *gcf = conf;
@@ -491,7 +619,7 @@ ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (gcf->city == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "GeoIO_open(\"%V\") failed", &value[1]);
+ "GeoIP_open(\"%V\") failed", &value[1]);
return NGX_CONF_ERROR;
}
@@ -532,6 +660,10 @@ ngx_http_geoip_cleanup(void *data)
GeoIP_delete(gcf->country);
}
+ if (gcf->org) {
+ GeoIP_delete(gcf->org);
+ }
+
if (gcf->city) {
GeoIP_delete(gcf->city);
}
diff --git a/src/http/modules/ngx_http_split_clients_module.c b/src/http/modules/ngx_http_split_clients_module.c
index a43fac519..0b726f777 100644
--- a/src/http/modules/ngx_http_split_clients_module.c
+++ b/src/http/modules/ngx_http_split_clients_module.c
@@ -94,7 +94,7 @@ ngx_http_split_clients_variable(ngx_http_request_t *r,
for (i = 0; i < ctx->parts.nelts; i++) {
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "%D %D", hash, part[i].percent);
+ "http split: %uD %uD", hash, part[i].percent);
if (hash < part[i].percent) {
*v = part[i].value;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index bc9790193..fa2fed8c6 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.0.2';
+our $VERSION = '1.0.3';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index fb1ab9854..03cd268b2 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -174,8 +174,6 @@ ngx_http_file_cache_create(ngx_http_request_t *r)
ngx_pool_cleanup_t *cln;
ngx_http_file_cache_t *cache;
- ngx_http_file_cache_create_key(r);
-
c = r->cache;
cache = c->file_cache;
@@ -906,7 +904,7 @@ ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf)
ngx_http_file_cache_t *cache;
ngx_http_file_cache_node_t *fcn;
- if (c->updated) {
+ if (c->updated || c->node == NULL) {
return;
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 914d72c84..8f1ee42c3 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -641,19 +641,6 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (c == NULL) {
- switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
-
- case NGX_ERROR:
- return NGX_ERROR;
-
- case NGX_DECLINED:
- u->cache_status = NGX_HTTP_CACHE_BYPASS;
- return NGX_DECLINED;
-
- default: /* NGX_OK */
- break;
- }
-
if (!(r->method & u->conf->cache_methods)) {
return NGX_DECLINED;
}
@@ -674,6 +661,19 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
ngx_http_file_cache_create_key(r);
+ switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
+
+ case NGX_ERROR:
+ return NGX_ERROR;
+
+ case NGX_DECLINED:
+ u->cache_status = NGX_HTTP_CACHE_BYPASS;
+ return NGX_DECLINED;
+
+ default: /* NGX_OK */
+ break;
+ }
+
u->cacheable = 1;
c = r->cache;
@@ -2135,18 +2135,6 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
- if (ngx_http_file_cache_new(r) != NGX_OK) {
- ngx_http_upstream_finalize_request(r, u, 0);
- return;
- }
-
- if (u->create_key(r) != NGX_OK) {
- ngx_http_upstream_finalize_request(r, u, 0);
- return;
- }
-
- /* TODO: add keys */
-
r->cache->min_uses = u->conf->cache_min_uses;
r->cache->body_start = u->conf->buffer_size;
r->cache->file_cache = u->conf->cache->data;
diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c
index 165c6a46b..c46fb2bfd 100644
--- a/src/os/unix/ngx_user.c
+++ b/src/os/unix/ngx_user.c
@@ -23,7 +23,7 @@
#if (NGX_HAVE_GNU_CRYPT_R)
ngx_int_t
-ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
+ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
{
char *value;
size_t len;
@@ -58,7 +58,7 @@ ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
#else
ngx_int_t
-ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
+ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
{
char *value;
size_t len;
diff --git a/src/os/unix/ngx_user.h b/src/os/unix/ngx_user.h
index 7cd944d01..68d1c6e5f 100644
--- a/src/os/unix/ngx_user.h
+++ b/src/os/unix/ngx_user.h
@@ -16,7 +16,7 @@ typedef uid_t ngx_uid_t;
typedef gid_t ngx_gid_t;
-ngx_int_t ngx_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
+ngx_int_t ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt,
u_char **encrypted);