summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2009-02-21 07:26:48 +0000
committerJonathan Kolb <jon@b0g.us>2009-02-21 07:26:48 +0000
commit3dd7190a4e759d131d4b7260a484838b5a48eacc (patch)
treee6052cb5f94d4f1c63671bca141dc714fdaeedd6
parent2f3de21383909e4405a8541e20af8381945c75d0 (diff)
downloadnginx-3dd7190a4e759d131d4b7260a484838b5a48eacc.tar.gz
Changes with nginx 0.7.36 21 Feb 2009v0.7.36
*) Feature: a preliminary IPv6 support; the "listen" directive of the HTTP module supports IPv6. *) Bugfix: the $ancient_browser variable did not work for browsers preset by a "modern_browser" directives.
-rw-r--r--CHANGES9
-rw-r--r--CHANGES.ru9
-rw-r--r--auto/options6
-rwxr-xr-xauto/unix15
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_connection.c30
-rw-r--r--src/core/ngx_connection.h3
-rw-r--r--src/core/ngx_cycle.c46
-rw-r--r--src/core/ngx_inet.c338
-rw-r--r--src/core/ngx_inet.h27
-rw-r--r--src/event/ngx_event_accept.c14
-rw-r--r--src/http/modules/ngx_http_access_module.c6
-rw-r--r--src/http/modules/ngx_http_browser_module.c6
-rw-r--r--src/http/modules/ngx_http_empty_gif_module.c1
-rw-r--r--src/http/modules/ngx_http_geo_module.c4
-rw-r--r--src/http/modules/ngx_http_realip_module.c6
-rw-r--r--src/http/modules/ngx_http_upstream_ip_hash_module.c20
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/ngx_http.c860
-rw-r--r--src/http/ngx_http_core_module.c57
-rw-r--r--src/http/ngx_http_core_module.h44
-rw-r--r--src/http/ngx_http_header_filter_module.c4
-rw-r--r--src/http/ngx_http_request.c110
-rw-r--r--src/http/ngx_http_variables.c74
-rw-r--r--src/mail/ngx_mail_core_module.c5
25 files changed, 1191 insertions, 507 deletions
diff --git a/CHANGES b/CHANGES
index d8972e211..ff9194860 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,13 @@
+Changes with nginx 0.7.36 21 Feb 2009
+
+ *) Feature: a preliminary IPv6 support; the "listen" directive of the
+ HTTP module supports IPv6.
+
+ *) Bugfix: the $ancient_browser variable did not work for browsers
+ preset by a "modern_browser" directives.
+
+
Changes with nginx 0.7.35 16 Feb 2009
*) Bugfix: a "ssl_engine" directive did not use a SSL-accelerator for
diff --git a/CHANGES.ru b/CHANGES.ru
index ad56b05d6..76f95f39b 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,13 @@
+Изменения в nginx 0.7.36 21.02.2009
+
+ *) Добавление: предварительная поддержка IPv6; директива listen модуля
+ HTTP поддерживает IPv6.
+
+ *) Исправление: переменная $ancient_browser не работала для браузеров,
+ заданных директивами modern_browser.
+
+
Изменения в nginx 0.7.35 16.02.2009
*) Исправление: директива ssl_engine не использовала SSL-акселератор
diff --git a/auto/options b/auto/options
index 9e6e1a215..fabd5d0d1 100644
--- a/auto/options
+++ b/auto/options
@@ -43,6 +43,8 @@ EVENT_AIO=NO
USE_THREADS=NO
+NGX_IPV6=NO
+
HTTP=YES
NGX_HTTP_LOG_PATH=
@@ -160,6 +162,8 @@ do
#--with-threads=*) USE_THREADS="$value" ;;
#--with-threads) USE_THREADS="pthreads" ;;
+ --with-ipv6) NGX_IPV6=YES ;;
+
--without-http) HTTP=NO ;;
--http-log-path=*) NGX_HTTP_LOG_PATH="$value" ;;
--http-client-body-temp-path=*) NGX_HTTP_CLIENT_TEMP_PATH="$value" ;;
@@ -285,6 +289,8 @@ cat << END
--with-poll_module enable poll module
--without-poll_module disable poll module
+ --with-ipv6 enable ipv6 support
+
--with-http_ssl_module enable ngx_http_ssl_module
--with-http_realip_module enable ngx_http_realip_module
--with-http_addition_module enable ngx_http_addition_module
diff --git a/auto/unix b/auto/unix
index 245d4f7f1..7d6e4805e 100755
--- a/auto/unix
+++ b/auto/unix
@@ -64,6 +64,21 @@ ngx_param=NGX_TIME_T_LEN; ngx_value=$ngx_max_len; . auto/types/value
# syscalls, libc calls and some features
+if [ $NGX_IPV6 = YES ]; then
+ ngx_feature="AF_INET6"
+ ngx_feature_name="NGX_HAVE_INET6"
+ ngx_feature_run=no
+ ngx_feature_incs="#include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>"
+ ngx_feature_path=
+ ngx_feature_libs=
+ ngx_feature_test="struct sockaddr_in6 sin6;
+ sin6.sin6_family = AF_INET6;"
+ . auto/feature
+fi
+
+
ngx_feature="setproctitle()"
ngx_feature_name="NGX_HAVE_SETPROCTITLE"
ngx_feature_run=no
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 5a597924d..a7576049b 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.7.35"
+#define NGINX_VERSION "0.7.36"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 28c904b5e..f48eefbb0 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -52,7 +52,6 @@ ngx_listening_inet_stream_socket(ngx_conf_t *cf, in_addr_t addr, in_port_t port)
ls->type = SOCK_STREAM;
ls->sockaddr = (struct sockaddr *) sin;
ls->socklen = sizeof(struct sockaddr_in);
- ls->addr = offsetof(struct sockaddr_in, sin_addr);
ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
return ls;
@@ -65,7 +64,6 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
size_t len;
ngx_uint_t i;
ngx_listening_t *ls;
- struct sockaddr_in *sin;
socklen_t olen;
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
ngx_err_t err;
@@ -94,33 +92,39 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
continue;
}
- sin = (struct sockaddr_in *) ls[i].sockaddr;
+ switch (ls[i].sockaddr->sa_family) {
- if (sin->sin_family != AF_INET) {
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
+ break;
+#endif
+
+ case AF_INET:
+ ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
+ break;
+
+ default:
ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
"the inherited socket #%d has "
- "unsupported family", ls[i].fd);
+ "an unsupported protocol family", ls[i].fd);
ls[i].ignore = 1;
continue;
}
- ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
+ len = ls[i].addr_text_max_len + sizeof(":65535") - 1;
- ls[i].addr_text.data = ngx_pnalloc(cycle->pool,
- NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1);
+ ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
if (ls[i].addr_text.data == NULL) {
return NGX_ERROR;
}
- len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data,
- NGX_INET_ADDRSTRLEN);
+ len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data, len, 1);
if (len == 0) {
return NGX_ERROR;
}
- ls[i].addr_text.len = ngx_sprintf(ls[i].addr_text.data + len, ":%d",
- ntohs(sin->sin_port))
- - ls[i].addr_text.data;
+ ls[i].addr_text.len = len;
ls[i].backlog = NGX_LISTEN_BACKLOG;
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 573fb3cc1..d9b80f941 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -19,7 +19,6 @@ struct ngx_listening_s {
struct sockaddr *sockaddr;
socklen_t socklen; /* size of sockaddr */
- size_t addr; /* offset to address in sockaddr */
size_t addr_text_max_len;
ngx_str_t addr_text;
@@ -123,10 +122,8 @@ struct ngx_connection_s {
ngx_ssl_connection_t *ssl;
#endif
-#if (NGX_HAVE_IOCP)
struct sockaddr *local_sockaddr;
socklen_t local_socklen;
-#endif
ngx_buf_t *buffer;
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index aa0d9ce7e..9ee7e65a0 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -876,23 +876,47 @@ ngx_destroy_cycle_pools(ngx_conf_t *conf)
static ngx_int_t
ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2)
{
- struct sockaddr_in *sin1, *sin2;
-
- /* AF_INET only */
+ struct sockaddr_in *sin1, *sin2;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin61, *sin62;
+#endif
- if (sa1->sa_family != AF_INET || sa2->sa_family != AF_INET) {
+ if (sa1->sa_family != sa2->sa_family) {
return NGX_DECLINED;
}
- sin1 = (struct sockaddr_in *) sa1;
- sin2 = (struct sockaddr_in *) sa2;
+ switch (sa1->sa_family) {
- if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
- return NGX_DECLINED;
- }
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin61 = (struct sockaddr_in6 *) sa1;
+ sin62 = (struct sockaddr_in6 *) sa2;
- if (sin1->sin_port != sin2->sin_port) {
- return NGX_DECLINED;
+ if (sin61->sin6_port != sin61->sin6_port) {
+ return NGX_DECLINED;
+ }
+
+ if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
+ return NGX_DECLINED;
+ }
+
+ break;
+#endif
+
+ default: /* AF_INET */
+
+ sin1 = (struct sockaddr_in *) sa1;
+ sin2 = (struct sockaddr_in *) sa2;
+
+ if (sin1->sin_port != sin2->sin_port) {
+ return NGX_DECLINED;
+ }
+
+ if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
+ return NGX_DECLINED;
+ }
+
+ break;
}
return NGX_OK;
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index 5c88a9d9d..7ccf6644d 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -8,12 +8,14 @@
#include <ngx_core.h>
+#if (NGX_HAVE_INET6)
+static size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
+#endif
static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
+static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
-/* AF_INET only */
-
in_addr_t
ngx_inet_addr(u_char *text, size_t len)
{
@@ -57,25 +59,58 @@ ngx_inet_addr(u_char *text, size_t len)
}
-/* AF_INET only */
-
size_t
-ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len)
+ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
{
- u_char *p;
- struct sockaddr_in *sin;
+ u_char *p;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ size_t n;
+ struct sockaddr_in6 *sin6;
+#endif
+
+ switch (sa->sa_family) {
- if (sa->sa_family == AF_INET) {
+ case AF_INET:
sin = (struct sockaddr_in *) sa;
p = (u_char *) &sin->sin_addr;
- return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
- p[0], p[1], p[2], p[3])
- - text;
- }
+ if (port) {
+ p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud:%d",
+ p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
+ } else {
+ p = ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
+ p[0], p[1], p[2], p[3]);
+ }
+
+ return (p - text);
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+
+ sin6 = (struct sockaddr_in6 *) sa;
+
+ n = 0;
+
+ if (port) {
+ text[n++] = '[';
+ }
- return 0;
+ n = ngx_inet6_ntop((u_char *) &sin6->sin6_addr, &text[n], len);
+
+ if (port) {
+ n = ngx_sprintf(&text[1 + n], "]:%d",
+ ntohs(sin6->sin6_port)) - text;
+ }
+
+ return n;
+#endif
+
+ default:
+ return 0;
+ }
}
@@ -84,18 +119,109 @@ ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
{
u_char *p;
- if (family == AF_INET) {
+ switch (family) {
+
+ case AF_INET:
- p = (u_char *) addr;
+ p = addr;
return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud",
p[0], p[1], p[2], p[3])
- text;
+
+#if (NGX_HAVE_INET6)
+
+ case AF_INET6:
+ return ngx_inet6_ntop(addr, text, len);
+
+#endif
+
+ default:
+ return 0;
+ }
+}
+
+
+#if (NGX_HAVE_INET6)
+
+static size_t
+ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
+{
+ u_char *dst;
+ size_t max, n;
+ ngx_uint_t i, zero, last;
+
+ if (len < NGX_INET6_ADDRSTRLEN) {
+ return 0;
+ }
+
+ zero = (ngx_uint_t) -1;
+ last = (ngx_uint_t) -1;
+ max = 1;
+ n = 0;
+
+ for (i = 0; i < 16; i += 2) {
+
+ if (p[i] || p[i + 1]) {
+
+ if (max < n) {
+ zero = last;
+ max = n;
+ }
+
+ n = 0;
+ continue;
+ }
+
+ if (n++ == 0) {
+ last = i;
+ }
}
- return 0;
+ if (max < n) {
+ zero = last;
+ max = n;
+ }
+
+ dst = text;
+ n = 16;
+
+ if (zero == 0) {
+
+ if ((max == 5 && p[10] == 0xff && p[11] == 0xff)
+ || (max == 6)
+ || (max == 7 && p[14] != 0 && p[15] != 1))
+ {
+ n = 12;
+ }
+
+ *dst++ = ':';
+ }
+
+ for (i = 0; i < n; i += 2) {
+
+ if (i == zero) {
+ *dst++ = ':';
+ i += (max - 1) * 2;
+ continue;
+ }
+
+ dst = ngx_sprintf(dst, "%uxi", p[i] * 256 + p[i + 1]);
+
+ if (i < 14) {
+ *dst++ = ':';
+ }
+ }
+
+ if (n == 12) {
+ dst = ngx_sprintf(dst, "%ud.%ud.%ud.%ud", p[12], p[13], p[14], p[15]);
+ }
+
+ return dst - text;
}
+#endif
+
/* AF_INET only */
@@ -171,6 +297,10 @@ ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR;
}
+ if (p[0] == '[') {
+ return ngx_parse_inet6_url(pool, u);
+ }
+
return ngx_parse_inet_url(pool, u);
}
@@ -209,13 +339,17 @@ ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
u->host.len = len++;
u->host.data = path;
- u->family = AF_UNIX;
if (len > sizeof(saun->sun_path)) {
u->err = "too long path in the unix domain socket";
return NGX_ERROR;
}
+ u->socklen = sizeof(struct sockaddr_un);
+ saun = (struct sockaddr_un *) &u->sockaddr;
+ saun->sun_family = AF_UNIX;
+ (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
+
u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
if (u->addrs == NULL) {
return NGX_ERROR;
@@ -226,6 +360,7 @@ ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR;
}
+ u->family = AF_UNIX;
u->naddrs = 1;
saun->sun_family = AF_UNIX;
@@ -251,10 +386,15 @@ ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u)
static ngx_int_t
ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
{
- u_char *p, *host, *port, *last, *uri, *args;
- size_t len;
- ngx_int_t n;
- struct hostent *h;
+ u_char *p, *host, *port, *last, *uri, *args;
+ size_t len;
+ ngx_int_t n;
+ struct hostent *h;
+ struct sockaddr_in *sin;
+
+ u->socklen = sizeof(struct sockaddr_in);
+ sin = (struct sockaddr_in *) &u->sockaddr;
+ sin->sin_family = AF_INET;
u->family = AF_INET;
@@ -311,6 +451,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
}
u->port = (in_port_t) n;
+ sin->sin_port = htons((in_port_t) n);
u->port_text.len = len;
u->port_text.data = port;
@@ -334,10 +475,13 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
}
u->port = (in_port_t) n;
+ sin->sin_port = htons((in_port_t) n);
u->port_text.len = last - host;
u->port_text.data = host;
+ u->wildcard = 1;
+
return NGX_OK;
}
}
@@ -374,8 +518,9 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
(void) ngx_cpystrn(p, host, len);
u->addr.in_addr = inet_addr((const char *) p);
+ sin->sin_addr.s_addr = inet_addr((const char *) p);
- if (u->addr.in_addr == INADDR_NONE) {
+ if (sin->sin_addr.s_addr == INADDR_NONE) {
h = gethostbyname((const char *) p);
if (h == NULL || h->h_addr_list[0] == NULL) {
@@ -385,16 +530,24 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
}
u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
+ sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
+ }
+
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ u->wildcard = 1;
}
ngx_free(p);
} else {
u->addr.in_addr = INADDR_ANY;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ u->wildcard = 1;
}
if (u->no_port) {
u->port = u->default_port;
+ sin->sin_port = htons(u->default_port);
}
if (u->listen) {
@@ -409,11 +562,134 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
}
+static ngx_int_t
+ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
+{
+#if (NGX_HAVE_INET6)
+ int rc;
+ u_char *p, *host, *port, *last, *uri;
+ size_t len;
+ ngx_int_t n;
+ struct sockaddr_in6 *sin6;
+
+ u->socklen = sizeof(struct sockaddr_in6);
+ sin6 = (struct sockaddr_in6 *) &u->sockaddr;
+ sin6->sin6_family = AF_INET6;
+
+ host = u->url.data + 1;
+
+ last = u->url.data + u->url.len;
+
+ p = ngx_strlchr(host, last, ']');
+
+ if (p == NULL) {
+ u->err = "invalid host";
+ return NGX_ERROR;
+ }
+
+ if (last - p) {
+
+ port = p + 1;
+
+ uri = ngx_strlchr(port, last, '/');
+
+ if (uri) {
+ if (u->listen || !u->uri_part) {
+ u->err = "invalid host";
+ return NGX_ERROR;
+ }
+
+ u->uri.len = last - uri;
+ u->uri.data = uri;
+ }
+
+ if (*port == ':') {
+ port++;
+
+ len = last - port;
+
+ if (len == 0) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
+
+ n = ngx_atoi(port, len);
+
+ if (n < 1 || n > 65536) {
+ u->err = "invalid port";
+ 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.data = port;
+
+ } else {
+ u->no_port = 1;
+ }
+ }
+
+ len = p - host;
+
+ if (len == 0) {
+ u->err = "no host";
+ return NGX_ERROR;
+ }
+
+ u->host.len = len++;
+ u->host.data = host;
+
+ p = ngx_alloc(len, pool->log);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ (void) ngx_cpystrn(p, host, len);
+
+ rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
+
+ ngx_free(p);
+
+ if (rc == 0) {
+ u->err = "invalid IPv6 address";
+ return NGX_ERROR;
+ }
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ u->wildcard = 1;
+ }
+
+ u->family = AF_INET6;
+
+ if (u->no_resolve) {
+ return NGX_OK;
+ }
+
+ if (u->no_port) {
+ u->port = u->default_port;
+ sin6->sin6_port = htons(u->default_port);
+ }
+
+ return NGX_OK;
+
+#else
+
+ u->err = "the INET6 sockets are not supported on this platform";
+
+ return NGX_ERROR;
+
+#endif
+}
+
+
ngx_int_t
ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
{
u_char *p, *host;
size_t len;
+ in_port_t port;
in_addr_t in_addr;
ngx_uint_t i;
struct hostent *h;
@@ -428,6 +704,9 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
/* AF_INET only */
+ sin = (struct sockaddr_in *) &u->sockaddr;
+ port = sin->sin_port;
+
in_addr = inet_addr((char *) host);
if (in_addr == INADDR_NONE) {
@@ -464,22 +743,22 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
}
sin->sin_family = AF_INET;
- sin->sin_port = htons(u->port);
+ sin->sin_port = port;
sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
u->addrs[i].sockaddr = (struct sockaddr *) sin;
u->addrs[i].socklen = sizeof(struct sockaddr_in);
- len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
+ len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
p = ngx_pnalloc(pool, len);
if (p == NULL) {
return NGX_ERROR;
}
- len = ngx_sock_ntop((struct sockaddr *) sin, p, len);
+ len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
- u->addrs[i].name.len = ngx_sprintf(&p[len], ":%d", u->port) - p;
+ u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
}
@@ -502,18 +781,19 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
u->naddrs = 1;
sin->sin_family = AF_INET;
- sin->sin_port = htons(u->port);
+ sin->sin_port = port;
sin->sin_addr.s_addr = in_addr;
u->addrs[0].sockaddr = (struct sockaddr *) sin;
u->addrs[0].socklen = sizeof(struct sockaddr_in);
- p = ngx_pnalloc(pool, u->host.len + sizeof(":65536") - 1);
+ p = ngx_pnalloc(pool, u->host.len + sizeof(":65535") - 1);
if (p == NULL) {
return NGX_ERROR;
}
- u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p;
+ u->addrs[0].name.len = ngx_sprintf(p, "%V:%d",
+ &u->host, ntohs(port)) - p;
u->addrs[0].name.data = p;
}
diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h
index be78142ea..d60c9c755 100644
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -12,7 +12,25 @@
#include <ngx_core.h>
-#define NGX_INET_ADDRSTRLEN (sizeof("255.255.255.255") - 1)
+#define NGX_INET_ADDRSTRLEN (sizeof("255.255.255.255") - 1)
+#define NGX_INET6_ADDRSTRLEN \
+ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1)
+
+#define NGX_SOCKADDR_STRLEN (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1)
+
+
+/*
+ * TODO: autoconfigure NGX_SOCKADDRLEN as
+ * sizeof(struct sockaddr_storage)
+ * sizeof(struct sockaddr_in6)
+ * sizeof(struct sockaddr_in)
+ */
+
+#if (NGX_HAVE_INET6)
+#define NGX_SOCKADDRLEN sizeof(struct sockaddr_in6)
+#else
+#define NGX_SOCKADDRLEN sizeof(struct sockaddr_in)
+#endif
typedef struct {
@@ -49,9 +67,13 @@ typedef struct {
unsigned one_addr:1;
unsigned no_port:1;
+ unsigned wildcard:1;
ngx_url_addr_t addr;
+ socklen_t socklen;
+ u_char sockaddr[NGX_SOCKADDRLEN];
+
ngx_peer_addr_t *addrs;
ngx_uint_t naddrs;
@@ -60,7 +82,8 @@ typedef struct {
in_addr_t ngx_inet_addr(u_char *text, size_t len);
-size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len);
+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_parse_url(ngx_pool_t *pool, ngx_url_t *u);
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index 379abb9c3..d39a497d8 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -9,10 +9,6 @@
#include <ngx_event.h>
-/* the buffer size is enough to hold "struct sockaddr_un" */
-#define NGX_SOCKLEN 512
-
-
static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle);
static void ngx_close_accepted_connection(ngx_connection_t *c);
@@ -29,7 +25,7 @@ ngx_event_accept(ngx_event_t *ev)
ngx_listening_t *ls;
ngx_connection_t *c, *lc;
ngx_event_conf_t *ecf;
- char sa[NGX_SOCKLEN];
+ u_char sa[NGX_SOCKADDRLEN];
ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
@@ -48,7 +44,7 @@ ngx_event_accept(ngx_event_t *ev)
"accept on %V, ready: %d", &ls->addr_text, ev->available);
do {
- socklen = NGX_SOCKLEN;
+ socklen = NGX_SOCKADDRLEN;
s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
@@ -153,8 +149,10 @@ ngx_event_accept(ngx_event_t *ev)
c->log = log;
c->pool->log = log;
- c->listening = ls;
c->socklen = socklen;
+ c->listening = ls;
+ c->local_sockaddr = ls->sockaddr;
+ c->local_socklen = ls->socklen;
c->unexpected_eof = 1;
@@ -208,7 +206,7 @@ ngx_event_accept(ngx_event_t *ev)
}
c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->addr_text.data,
- ls->addr_text_max_len);
+ ls->addr_text_max_len, 0);
if (c->addr_text.len == 0) {
ngx_close_accepted_connection(c);
return;
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index 12f0b9922..8cd2e0e13 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -9,8 +9,6 @@
#include <ngx_http.h>
-/* AF_INET only */
-
typedef struct {
in_addr_t mask;
in_addr_t addr;
@@ -103,6 +101,10 @@ ngx_http_access_handler(ngx_http_request_t *r)
/* AF_INET only */
+ if (r->connection->sockaddr->sa_family != AF_INET) {
+ return NGX_DECLINED;
+ }
+
sin = (struct sockaddr_in *) r->connection->sockaddr;
rule = alcf->rules->elts;
diff --git a/src/http/modules/ngx_http_browser_module.c b/src/http/modules/ngx_http_browser_module.c
index 083375ba1..e0710c1bf 100644
--- a/src/http/modules/ngx_http_browser_module.c
+++ b/src/http/modules/ngx_http_browser_module.c
@@ -318,6 +318,10 @@ ngx_http_browser(ngx_http_request_t *r, ngx_http_browser_conf_t *cf)
if (c == '.') {
version += ver * scale;
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "version: \"%ui\" \"%ui\"",
+ modern[i].version, version);
+
if (version > modern[i].version) {
return NGX_HTTP_MODERN_BROWSER;
}
@@ -339,6 +343,8 @@ ngx_http_browser(ngx_http_request_t *r, ngx_http_browser_conf_t *cf)
if (version >= modern[i].version) {
return NGX_HTTP_MODERN_BROWSER;
}
+
+ return NGX_HTTP_ANCIENT_BROWSER;
}
if (!cf->modern_unlisted_browsers) {
diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c
index 8450cae71..e6515df15 100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -122,6 +122,7 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
return rc;
}
+ r->headers_out.content_type_len = sizeof("image/gif") - 1;
r->headers_out.content_type.len = sizeof("image/gif") - 1;
r->headers_out.content_type.data = (u_char *) "image/gif";
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index bd6499ec7..a8f26854b 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -175,6 +175,10 @@ ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx)
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;
+ }
+
sin = (struct sockaddr_in *) r->connection->sockaddr;
return ntohl(sin->sin_addr.s_addr);
}
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index 44c74a182..58bdeeb37 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -14,8 +14,6 @@
#define NGX_HTTP_REALIP_HEADER 2
-/* AF_INET only */
-
typedef struct {
in_addr_t mask;
in_addr_t addr;
@@ -209,6 +207,10 @@ found:
/* AF_INET only */
+ if (r->connection->sockaddr->sa_family != AF_INET) {
+ return NGX_DECLINED;
+ }
+
sin = (struct sockaddr_in *) c->sockaddr;
from = rlcf->from->elts;
diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c
index 1d13481a9..dffbf22b2 100644
--- a/src/http/modules/ngx_http_upstream_ip_hash_module.c
+++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c
@@ -15,7 +15,6 @@ typedef struct {
ngx_uint_t hash;
- /* AF_INET only */
u_char addr[3];
u_char tries;
@@ -111,11 +110,20 @@ ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;
/* AF_INET only */
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- p = (u_char *) &sin->sin_addr.s_addr;
- iphp->addr[0] = p[0];
- iphp->addr[1] = p[1];
- iphp->addr[2] = p[2];
+
+ if (r->connection->sockaddr->sa_family == AF_INET) {
+
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
+ p = (u_char *) &sin->sin_addr.s_addr;
+ iphp->addr[0] = p[0];
+ iphp->addr[1] = p[1];
+ iphp->addr[2] = p[2];
+
+ } else {
+ iphp->addr[0] = 0;
+ iphp->addr[1] = 0;
+ iphp->addr[2] = 0;
+ }
iphp->hash = 89;
iphp->tries = 0;
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 90989da54..d33310e27 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '0.7.35';
+our $VERSION = '0.7.36';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 615788811..ecd9c97d7 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -19,11 +19,17 @@ static ngx_int_t ngx_http_init_phase_handlers(ngx_conf_t *cf,
static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
ngx_array_t *servers, ngx_array_t *in_ports);
+static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf,
+ ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports,
+ ngx_http_listen_t *listen);
+static ngx_int_t ngx_http_add_addresses(ngx_conf_t *cf,
+ ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
+ ngx_http_listen_t *listen);
static ngx_int_t ngx_http_add_address(ngx_conf_t *cf,
- ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_port_t *in_port,
+ ngx_http_core_srv_conf_t *cscf, ngx_http_conf_port_t *port,
ngx_http_listen_t *listen);
static ngx_int_t ngx_http_add_names(ngx_conf_t *cf,
- ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_addr_t *in_addr);
+ ngx_http_core_srv_conf_t *cscf, ngx_http_conf_addr_t *addr);
static char *ngx_http_merge_locations(ngx_conf_t *cf,
ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module,
@@ -43,13 +49,23 @@ static ngx_http_location_tree_node_t *
size_t prefix);
static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf,
- ngx_http_core_main_conf_t *cmcf, ngx_array_t *in_ports);
-static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two);
+ ngx_http_core_main_conf_t *cmcf, ngx_array_t *ports);
+static ngx_int_t ngx_http_server_names(ngx_conf_t *cf,
+ ngx_http_core_main_conf_t *cmcf, ngx_http_conf_addr_t *addr);
+static ngx_int_t ngx_http_cmp_conf_addrs(const void *one, const void *two);
static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one,
const void *two);
static ngx_int_t ngx_http_init_listening(ngx_conf_t *cf,
- ngx_http_conf_in_port_t *in_port);
+ ngx_http_conf_port_t *port);
+static ngx_listening_t *ngx_http_add_listening(ngx_conf_t *cf,
+ ngx_http_conf_addr_t *addr);
+static ngx_int_t ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
+ ngx_http_conf_addr_t *addr);
+#if (NGX_HAVE_INET6)
+static ngx_int_t ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
+ ngx_http_conf_addr_t *addr);
+#endif
ngx_uint_t ngx_http_max_module;
@@ -351,8 +367,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
* to find quickly the server core module configuration at run-time
*/
- /* AF_INET only */
-
if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) {
return NGX_CONF_ERROR;
}
@@ -360,8 +374,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
/* optimize the lists of ports, addresses and server names */
- /* AF_INET only */
-
if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) {
return NGX_CONF_ERROR;
}
@@ -1099,16 +1111,13 @@ inclusive:
static ngx_int_t
ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
- ngx_array_t *in_ports)
+ ngx_array_t *ports)
{
- ngx_uint_t s, l, p, a;
+ ngx_uint_t s, i;
ngx_http_listen_t *listen;
- ngx_http_conf_in_port_t *in_port;
- ngx_http_conf_in_addr_t *in_addr;
ngx_http_core_srv_conf_t **cscfp;
- if (ngx_array_init(in_ports, cf->temp_pool, 2,
- sizeof(ngx_http_conf_in_port_t))
+ if (ngx_array_init(ports, cf->temp_pool, 2, sizeof(ngx_http_conf_port_t))
!= NGX_OK)
{
return NGX_ERROR;
@@ -1122,96 +1131,149 @@ ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
/* "listen" directives */
listen = cscfp[s]->listen.elts;
- for (l = 0; l < cscfp[s]->listen.nelts; l++) {
+ for (i = 0; i < cscfp[s]->listen.nelts; i++) {
- /* AF_INET only */
+ if (ngx_http_add_ports(cf, cscfp[s], ports, &listen[i]) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+ }
- in_port = in_ports->elts;
- for (p = 0; p < in_ports->nelts; p++) {
+ return NGX_OK;
+}
- if (listen[l].port != in_port[p].port) {
- continue;
- }
- /* the port is already in the port list */
+static ngx_int_t
+ngx_http_add_ports(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+ ngx_array_t *ports, ngx_http_listen_t *listen)
+{
+ in_port_t p;
+ ngx_uint_t i;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ ngx_http_conf_port_t *port;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+#endif
- in_addr = in_port[p].addrs.elts;
- for (a = 0; a < in_port[p].addrs.nelts; a++) {
+ sa = (struct sockaddr *) &listen->sockaddr;
- if (listen[l].addr != in_addr[a].addr) {
- continue;
- }
+ switch (sa->sa_family) {
- /* the address is already in the address list */
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) sa;
+ p = sin6->sin6_port;
+ break;
+#endif
- if (ngx_http_add_names(cf, cscfp[s], &in_addr[a]) != NGX_OK)
- {
- return NGX_ERROR;
- }
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) sa;
+ p = sin->sin_port;
+ break;
+ }
+
+ port = ports->elts;
+ for (i = 0; i < ports->nelts; i++) {
- /*
- * check the duplicate "default" server
- * for this address:port
- */
+ if (p != port[i].port || sa->sa_family != port[i].family) {
+ continue;
+ }
- if (listen[l].conf.default_server) {
+ /* a port is already in the in_port list */
- if (in_addr[a].default_server) {
- ngx_log_error(NGX_LOG_ERR, cf->log, 0,
- "the duplicate default server in %s:%ui",
- listen[l].file_name, listen[l].line);
+ return ngx_http_add_addresses(cf, cscf, &port[i], listen);
+ }
- return NGX_ERROR;
- }
+ /* add a port to the in_port list */
- in_addr[a].core_srv_conf = cscfp[s];
- in_addr[a].default_server = 1;
-#if (NGX_HTTP_SSL)
- in_addr[a].ssl = listen[l].conf.ssl;
+ port = ngx_array_push(ports);
+ if (port == NULL) {
+ return NGX_ERROR;
+ }
+
+ port->family = sa->sa_family;
+ port->port = p;
+ port->addrs.elts = NULL;
+
+ return ngx_http_add_address(cf, cscf, port, listen);
+}
+
+
+static ngx_int_t
+ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
+ ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
+{
+ u_char *p;
+ size_t len, off;
+ ngx_uint_t i;
+ struct sockaddr *sa;
+ ngx_http_conf_addr_t *addr;
+
+ /*
+ * we can not compare whole sockaddr struct's as kernel
+ * may fill some fields in inherited sockaddr struct's
+ */
+
+ sa = (struct sockaddr *) &listen->sockaddr;
+
+ switch (sa->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ off = offsetof(struct sockaddr_in6, sin6_addr);
+ len = 16;
+ break;
#endif
- in_addr[a].listen_conf = &listen[l].conf;
- }
- goto found;
- }
+ default: /* AF_INET */
+ off = offsetof(struct sockaddr_in, sin_addr);
+ len = 4;
+ break;
+ }
- /*
- * add the address to the addresses list that
- * bound to this port
- */
+ p = listen->sockaddr + off;
- if (ngx_http_add_address(cf, cscfp[s], &in_port[p], &listen[l])
- != NGX_OK)
- {
- return NGX_ERROR;
- }
+ addr = port->addrs.elts;
- goto found;
- }
+ for (i = 0; i < port->addrs.nelts; i++) {
- /* add the port to the in_port list */
+ if (ngx_memcmp(p, (u_char *) addr[i].sockaddr + off, len) != 0) {
+ continue;
+ }
- in_port = ngx_array_push(in_ports);
- if (in_port == NULL) {
- return NGX_ERROR;
- }
+ /* the address is already in the address list */
- in_port->port = listen[l].port;
- in_port->addrs.elts = NULL;
+ if (ngx_http_add_names(cf, cscf, &addr[i]) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ /* check the duplicate "default" server for this address:port */
+
+ if (listen->conf.default_server) {
+
+ if (addr[i].default_server) {
+ ngx_log_error(NGX_LOG_ERR, cf->log, 0,
+ "the duplicate default server in %s:%ui",
+ listen->file_name, listen->line);
- if (ngx_http_add_address(cf, cscfp[s], in_port, &listen[l])
- != NGX_OK)
- {
return NGX_ERROR;
}
- found:
-
- continue;
+ addr[i].core_srv_conf = cscf;
+ addr[i].default_server = 1;
+#if (NGX_HTTP_SSL)
+ addr[i].ssl = listen->conf.ssl;
+#endif
+ addr[i].listen_conf = &listen->conf;
}
+
+ return NGX_OK;
}
- return NGX_OK;
+ /* add the address to the addresses list that bound to this port */
+
+ return ngx_http_add_address(cf, cscf, port, listen);
}
@@ -1222,60 +1284,62 @@ ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers,
static ngx_int_t
ngx_http_add_address(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
- ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *listen)
+ ngx_http_conf_port_t *port, ngx_http_listen_t *listen)
{
- ngx_http_conf_in_addr_t *in_addr;
+ ngx_http_conf_addr_t *addr;
- if (in_port->addrs.elts == NULL) {
- if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4,
- sizeof(ngx_http_conf_in_addr_t))
+ if (port->addrs.elts == NULL) {
+ if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
+ sizeof(ngx_http_conf_addr_t))
!= NGX_OK)
{
return NGX_ERROR;
}
}
- in_addr = ngx_array_push(&in_port->addrs);
- if (in_addr == NULL) {
+ addr = ngx_array_push(&port->addrs);
+ if (addr == NULL) {
return NGX_ERROR;
}
- in_addr->addr = listen->addr;
- in_addr->hash.buckets = NULL;
- in_addr->hash.size = 0;
- in_addr->wc_head = NULL;
- in_addr->wc_tail = NULL;
- in_addr->names.elts = NULL;
+ addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
+ addr->socklen = listen->socklen;
+ addr->hash.buckets = NULL;
+ addr->hash.size = 0;
+ addr->wc_head = NULL;
+ addr->wc_tail = NULL;
+ addr->names.elts = NULL;
#if (NGX_PCRE)
- in_addr->nregex = 0;
- in_addr->regex = NULL;
+ addr->nregex = 0;
+ addr->regex = NULL;
#endif
- in_addr->core_srv_conf = cscf;
- in_addr->default_server = listen->conf.default_server;
- in_addr->bind = listen->conf.bind;
+ addr->core_srv_conf = cscf;
+ addr->default_server = listen->conf.default_server;
+ addr->bind = listen->conf.bind;
+ addr->wildcard = listen->conf.wildcard;
#if (NGX_HTTP_SSL)
- in_addr->ssl = listen->conf.ssl;
+ addr->ssl = listen->conf.ssl;
#endif
- in_addr->listen_conf = &listen->conf;
+ addr->listen_conf = &listen->conf;
- return ngx_http_add_names(cf, cscf, in_addr);
+ return ngx_http_add_names(cf, cscf, addr);
}
/*
* add the server names and the server core module
- * configurations to the address:port (in_addr)
+ * configurations to the address:port
*/
static ngx_int_t
ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
- ngx_http_conf_in_addr_t *in_addr)
+ ngx_http_conf_addr_t *addr)
{
ngx_uint_t i;
ngx_http_server_name_t *server_names, *name;
- if (in_addr->names.elts == NULL) {
- if (ngx_array_init(&in_addr->names, cf->temp_pool, 4,
+ if (addr->names.elts == NULL) {
+ if (ngx_array_init(&addr->names, cf->temp_pool, 4,
sizeof(ngx_http_server_name_t))
!= NGX_OK)
{
@@ -1293,7 +1357,7 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
"name: %V", &server_names[i].name);
- name = ngx_array_push(&in_addr->names);
+ name = ngx_array_push(&addr->names);
if (name == NULL) {
return NGX_ERROR;
}
@@ -1307,187 +1371,184 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
static ngx_int_t
ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
- ngx_array_t *in_ports)
+ ngx_array_t *ports)
{
- ngx_int_t rc;
- ngx_uint_t s, p, a;
- ngx_hash_init_t hash;
- ngx_http_server_name_t *name;
- ngx_hash_keys_arrays_t ha;
- ngx_http_conf_in_port_t *in_port;
- ngx_http_conf_in_addr_t *in_addr;
-#if (NGX_PCRE)
- ngx_uint_t regex, i;
-#endif
+ ngx_uint_t s, p, a;
+ ngx_http_conf_port_t *port;
+ ngx_http_conf_addr_t *addr;
+ ngx_http_server_name_t *name;
- in_port = in_ports->elts;
- for (p = 0; p < in_ports->nelts; p++) {
+ port = ports->elts;
+ for (p = 0; p < ports->nelts; p++) {
- ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
- sizeof(ngx_http_conf_in_addr_t), ngx_http_cmp_conf_in_addrs);
+ ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
+ sizeof(ngx_http_conf_addr_t), ngx_http_cmp_conf_addrs);
/*
- * check whether all name-based servers have
- * the same configuraiton as the default server
+ * check whether all name-based servers have the same
+ * configuraiton as a default server for given address:port
*/
- in_addr = in_port[p].addrs.elts;
- for (a = 0; a < in_port[p].addrs.nelts; a++) {
+ addr = port[p].addrs.elts;
+ for (a = 0; a < port[p].addrs.nelts; a++) {
- name = in_addr[a].names.elts;
- for (s = 0; s < in_addr[a].names.nelts; s++) {
+ name = addr[a].names.elts;
+ for (s = 0; s < addr[a].names.nelts; s++) {
- if (in_addr[a].core_srv_conf != name[s].core_srv_conf) {
- goto virtual_names;
+ if (addr[a].core_srv_conf == name[s].core_srv_conf) {
+ continue;
}
+
+ if (ngx_http_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ break;
}
+ }
- /*
- * if all name-based servers have the same configuration
- * as the default server, then we do not need to check
- * them at run-time at all
- */
+ if (ngx_http_init_listening(cf, &port[p]) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
- in_addr[a].names.nelts = 0;
+ return NGX_OK;
+}
- continue;
- virtual_names:
+static ngx_int_t
+ngx_http_server_names(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf,
+ ngx_http_conf_addr_t *addr)
+{
+ ngx_int_t rc;
+ ngx_uint_t s;
+ ngx_hash_init_t hash;
+ ngx_http_server_name_t *name;
+ ngx_hash_keys_arrays_t ha;
+#if (NGX_PCRE)
+ ngx_uint_t regex, i;
- ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
+ regex = 0;
+#endif
- ha.temp_pool = ngx_create_pool(16384, cf->log);
- if (ha.temp_pool == NULL) {
- return NGX_ERROR;
- }
+ ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
- ha.pool = cf->pool;
+ ha.temp_pool = ngx_create_pool(16384, cf->log);
+ if (ha.temp_pool == NULL) {
+ return NGX_ERROR;
+ }
- if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
- goto failed;
- }
+ ha.pool = cf->pool;
-#if (NGX_PCRE)
- regex = 0;
-#endif
+ if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
+ goto failed;
+ }
- name = in_addr[a].names.elts;
+ name = addr->names.elts;
- for (s = 0; s < in_addr[a].names.nelts; s++) {
+ for (s = 0; s < addr->names.nelts; s++) {
#if (NGX_PCRE)
- if (name[s].regex) {
- regex++;
- continue;
- }
+ if (name[s].regex) {
+ regex++;
+ continue;
+ }
#endif
- rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
- NGX_HASH_WILDCARD_KEY);
+ rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
+ NGX_HASH_WILDCARD_KEY);
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
+ if (rc == NGX_ERROR) {
+ return NGX_ERROR;
+ }
- if (rc == NGX_DECLINED) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "invalid server name or wildcard \"%V\" on %s",
- &name[s].name, in_addr[a].listen_conf->addr);
- return NGX_ERROR;
- }
+ if (rc == NGX_DECLINED) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "invalid server name or wildcard \"%V\" on %s",
+ &name[s].name, addr->listen_conf->addr);
+ return NGX_ERROR;
+ }
- if (rc == NGX_BUSY) {
- ngx_log_error(NGX_LOG_WARN, cf->log, 0,
- "conflicting server name \"%V\" on %s, ignored",
- &name[s].name, in_addr[a].listen_conf->addr);
- }
- }
+ if (rc == NGX_BUSY) {
+ ngx_log_error(NGX_LOG_WARN, cf->log, 0,
+ "conflicting server name \"%V\" on %s, ignored",
+ &name[s].name, addr->listen_conf->addr);
+ }
+ }
- hash.key = ngx_hash_key_lc;
- hash.max_size = cmcf->server_names_hash_max_size;
- hash.bucket_size = cmcf->server_names_hash_bucket_size;
- hash.name = "server_names_hash";
- hash.pool = cf->pool;
+ hash.key = ngx_hash_key_lc;
+ hash.max_size = cmcf->server_names_hash_max_size;
+ hash.bucket_size = cmcf->server_names_hash_bucket_size;
+ hash.name = "server_names_hash";
+ hash.pool = cf->pool;
- if (ha.keys.nelts) {
- hash.hash = &in_addr[a].hash;
- hash.temp_pool = NULL;
+ if (ha.keys.nelts) {
+ hash.hash = &addr->hash;
+ hash.temp_pool = NULL;
- if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK)
- {
- goto failed;
- }
- }
+ if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
+ goto failed;
+ }
+ }
- if (ha.dns_wc_head.nelts) {
+ if (ha.dns_wc_head.nelts) {
- ngx_qsort(ha.dns_wc_head.elts,
- (size_t) ha.dns_wc_head.nelts,
- sizeof(ngx_hash_key_t),
- ngx_http_cmp_dns_wildcards);
+ ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
+ sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
- hash.hash = NULL;
- hash.temp_pool = ha.temp_pool;
+ hash.hash = NULL;
+ hash.temp_pool = ha.temp_pool;
- if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
- ha.dns_wc_head.nelts)
- != NGX_OK)
- {
- goto failed;
- }
+ if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
+ ha.dns_wc_head.nelts)
+ != NGX_OK)
+ {
+ goto failed;
+ }
- in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash;
- }
+ addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
+ }
- if (ha.dns_wc_tail.nelts) {
+ if (ha.dns_wc_tail.nelts) {
- ngx_qsort(ha.dns_wc_tail.elts,
- (size_t) ha.dns_wc_tail.nelts,
- sizeof(ngx_hash_key_t),
- ngx_http_cmp_dns_wildcards);
+ ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
+ sizeof(ngx_hash_key_t), ngx_http_cmp_dns_wildcards);
- hash.hash = NULL;
- hash.temp_pool = ha.temp_pool;
+ hash.hash = NULL;
+ hash.temp_pool = ha.temp_pool;
- if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
- ha.dns_wc_tail.nelts)
- != NGX_OK)
- {
- goto failed;
- }
+ if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
+ ha.dns_wc_tail.nelts)
+ != NGX_OK)
+ {
+ goto failed;
+ }
- in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash;
- }
+ addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
+ }
- ngx_destroy_pool(ha.temp_pool);
+ ngx_destroy_pool(ha.temp_pool);
#if (NGX_PCRE)
- if (regex == 0) {
- continue;
- }
-
- in_addr[a].nregex = regex;
- in_addr[a].regex = ngx_palloc(cf->pool,
- regex * sizeof(ngx_http_server_name_t));
-
- if (in_addr[a].regex == NULL) {
- return NGX_ERROR;
- }
+ if (regex == 0) {
+ return NGX_OK;
+ }
- for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) {
- if (name[s].regex) {
- in_addr[a].regex[i++] = name[s];
- }
- }
-#endif
- }
+ addr->nregex = regex;
+ addr->regex = ngx_palloc(cf->pool, regex * sizeof(ngx_http_server_name_t));
+ if (addr->regex == NULL) {
+ return NGX_ERROR;
+ }
- if (ngx_http_init_listening(cf, &in_port[p]) != NGX_OK) {
- return NGX_ERROR;
+ for (i = 0, s = 0; s < addr->names.nelts; s++) {
+ if (name[s].regex) {
+ addr->regex[i++] = name[s];
}
}
+#endif
+
return NGX_OK;
failed:
@@ -1499,15 +1560,15 @@ failed:
static ngx_int_t
-ngx_http_cmp_conf_in_addrs(const void *one, const void *two)
+ngx_http_cmp_conf_addrs(const void *one, const void *two)
{
- ngx_http_conf_in_addr_t *first, *second;
+ ngx_http_conf_addr_t *first, *second;
- first = (ngx_http_conf_in_addr_t *) one;
- second = (ngx_http_conf_in_addr_t *) two;
+ first = (ngx_http_conf_addr_t *) one;
+ second = (ngx_http_conf_addr_t *) two;
- if (first->addr == INADDR_ANY) {
- /* the INADDR_ANY must be the last resort, shift it to the end */
+ if (first->wildcard) {
+ /* a wildcard address must be the last resort, shift it to the end */
return 1;
}
@@ -1540,170 +1601,301 @@ ngx_http_cmp_dns_wildcards(const void *one, const void *two)
static ngx_int_t
-ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port)
+ngx_http_init_listening(ngx_conf_t *cf, ngx_http_conf_port_t *port)
{
- ngx_uint_t i, a, last, bind_all, done;
+ ngx_uint_t i, a, last, bind_wildcard;
ngx_listening_t *ls;
- ngx_http_in_port_t *hip;
- ngx_http_conf_in_addr_t *in_addr;
- ngx_http_virtual_names_t *vn;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_core_srv_conf_t *cscf;
+ ngx_http_port_t *hport;
+ ngx_http_conf_addr_t *addr;
- in_addr = in_port->addrs.elts;
- last = in_port->addrs.nelts;
+ addr = port->addrs.elts;
+ last = port->addrs.nelts;
/*
- * if there is a binding to a "*:port" then we need to bind()
- * to the "*:port" only and ignore other bindings
+ * If there is a binding to an "*:port" then we need to bind() to
+ * the "*:port" only and ignore other implicit bindings. The bindings
+ * have been already sorted: explicit bindings are on the start, then
+ * implicit bindings go, and wildcard binding is in the end.
*/
- if (in_addr[last - 1].addr == INADDR_ANY) {
- in_addr[last - 1].bind = 1;
- bind_all = 0;
+ if (addr[last - 1].wildcard) {
+ addr[last - 1].bind = 1;
+ bind_wildcard = 1;
} else {
- bind_all = 1;
+ bind_wildcard = 0;
}
a = 0;
while (a < last) {
- if (!bind_all && !in_addr[a].bind) {
+ if (bind_wildcard && !addr[a].bind) {
a++;
continue;
}
- ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
- in_port->port);
+ ls = ngx_http_add_listening(cf, &addr[a]);
if (ls == NULL) {
return NGX_ERROR;
}
- ls->addr_ntop = 1;
+ hport = ngx_pcalloc(cf->pool, sizeof(ngx_http_port_t));
+ if (hport == NULL) {
+ return NGX_ERROR;
+ }
- ls->handler = ngx_http_init_connection;
+ ls->servers = hport;
- cscf = in_addr[a].core_srv_conf;
- ls->pool_size = cscf->connection_pool_size;
- ls->post_accept_timeout = cscf->client_header_timeout;
+ hport->port = ntohs(port->port);
- clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
+ for (i = ls->addr_text.len - 1; i; i--) {
- ls->log = *clcf->err_log;
- ls->log.data = &ls->addr_text;
- ls->log.handler = ngx_accept_log_error;
+ if (ls->addr_text.data[i] == ':') {
+ hport->port_text.len = ls->addr_text.len - i;
+ hport->port_text.data = &ls->addr_text.data[i];
+ break;
+ }
+ }
-#if (NGX_WIN32)
- {
- ngx_iocp_conf_t *iocpcf;
+ if (a == last - 1) {
+ hport->naddrs = last;
- iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
- if (iocpcf->acceptex_read) {
- ls->post_accept_buffer_size = cscf->client_header_buffer_size;
+ } else {
+ hport->naddrs = 1;
+ a = 0;
}
+
+ switch (ls->sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ if (ngx_http_add_addrs6(cf, hport, addr) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ break;
+#endif
+ default: /* AF_INET */
+ if (ngx_http_add_addrs(cf, hport, addr) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ break;
}
+
+ addr++;
+ last--;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_listening_t *
+ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
+{
+ ngx_listening_t *ls;
+ struct sockaddr *sa;
+ ngx_http_core_loc_conf_t *clcf;
+ ngx_http_core_srv_conf_t *cscf;
+ u_char text[NGX_SOCKADDR_STRLEN];
+
+ ls = ngx_array_push(&cf->cycle->listening);
+ if (ls == NULL) {
+ return NULL;
+ }
+
+ ngx_memzero(ls, sizeof(ngx_listening_t));
+
+ sa = ngx_palloc(cf->pool, addr->socklen);
+ if (sa == NULL) {
+ return NULL;
+ }
+
+ ngx_memcpy(sa, addr->sockaddr, addr->socklen);
+
+ ls->sockaddr = sa;
+ ls->socklen = addr->socklen;
+
+ ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
+
+ ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len);
+ if (ls->addr_text.data == NULL) {
+ return NULL;
+ }
+
+ ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len);
+
+ ls->fd = (ngx_socket_t) -1;
+ ls->type = SOCK_STREAM;
+
+ switch (ls->sockaddr->sa_family) {
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
+ break;
#endif
+ case AF_INET:
+ ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
+ break;
+ default:
+ ls->addr_text_max_len = NGX_SOCKADDR_STRLEN;
+ break;
+ }
+
+ ls->addr_ntop = 1;
+
+ ls->handler = ngx_http_init_connection;
- ls->backlog = in_addr[a].listen_conf->backlog;
- ls->rcvbuf = in_addr[a].listen_conf->rcvbuf;
- ls->sndbuf = in_addr[a].listen_conf->sndbuf;
+ cscf = addr->core_srv_conf;
+ ls->pool_size = cscf->connection_pool_size;
+ ls->post_accept_timeout = cscf->client_header_timeout;
+
+ clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
+
+ ls->log = *clcf->err_log;
+ ls->log.data = &ls->addr_text;
+ ls->log.handler = ngx_accept_log_error;
+
+#if (NGX_WIN32)
+ {
+ ngx_iocp_conf_t *iocpcf;
+
+ iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
+ if (iocpcf->acceptex_read) {
+ ls->post_accept_buffer_size = cscf->client_header_buffer_size;
+ }
+ }
+#endif
+
+ ls->backlog = addr->listen_conf->backlog;
+ ls->rcvbuf = addr->listen_conf->rcvbuf;
+ ls->sndbuf = addr->listen_conf->sndbuf;
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
- ls->accept_filter = in_addr[a].listen_conf->accept_filter;
+ ls->accept_filter = addr->listen_conf->accept_filter;
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
- ls->deferred_accept = in_addr[a].listen_conf->deferred_accept;
+ ls->deferred_accept = addr->listen_conf->deferred_accept;
#endif
- hip = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
- if (hip == NULL) {
- return NGX_ERROR;
- }
+ return ls;
+}
- hip->port = in_port->port;
- hip->port_text.data = ngx_pnalloc(cf->pool, 7);
- if (hip->port_text.data == NULL) {
- return NGX_ERROR;
- }
+static ngx_int_t
+ngx_http_add_addrs(ngx_conf_t *cf, ngx_http_port_t *hport,
+ ngx_http_conf_addr_t *addr)
+{
+ ngx_uint_t i;
+ ngx_http_in_addr_t *addrs;
+ struct sockaddr_in *sin;
+ ngx_http_virtual_names_t *vn;
- ls->servers = hip;
+ hport->addrs = ngx_pcalloc(cf->pool,
+ hport->naddrs * sizeof(ngx_http_in_addr_t));
+ if (hport->addrs == NULL) {
+ return NGX_ERROR;
+ }
- hip->port_text.len = ngx_sprintf(hip->port_text.data, ":%d", hip->port)
- - hip->port_text.data;
+ addrs = hport->addrs;
- in_addr = in_port->addrs.elts;
+ for (i = 0; i < hport->naddrs; i++) {
- if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
- hip->naddrs = 1;
- done = 0;
+ sin = (struct sockaddr_in *) addr[i].sockaddr;
+ addrs[i].addr = sin->sin_addr.s_addr;
+ addrs[i].conf.core_srv_conf = addr[i].core_srv_conf;
+#if (NGX_HTTP_SSL)
+ addrs[i].conf.ssl = addr[i].ssl;
+#endif
- } else if (in_port->addrs.nelts > 1
- && in_addr[last - 1].addr == INADDR_ANY)
+ if (addr[i].hash.buckets == NULL
+ && (addr[i].wc_head == NULL
+ || addr[i].wc_head->hash.buckets == NULL)
+ && (addr[i].wc_head == NULL
+ || addr[i].wc_head->hash.buckets == NULL))
{
- hip->naddrs = last;
- done = 1;
-
- } else {
- hip->naddrs = 1;
- done = 0;
+ continue;
}
- hip->addrs = ngx_pcalloc(cf->pool,
- hip->naddrs * sizeof(ngx_http_in_addr_t));
- if (hip->addrs == NULL) {
+ vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
+ if (vn == NULL) {
return NGX_ERROR;
}
- for (i = 0; i < hip->naddrs; i++) {
- hip->addrs[i].addr = in_addr[i].addr;
- hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
+ addrs[i].conf.virtual_names = vn;
-#if (NGX_HTTP_SSL)
- hip->addrs[i].ssl = in_addr[i].ssl;
+ vn->names.hash = addr[i].hash;
+ vn->names.wc_head = addr[i].wc_head;
+ vn->names.wc_tail = addr[i].wc_tail;
+#if (NGX_PCRE)
+ vn->nregex = addr[i].nregex;
+ vn->regex = addr[i].regex;
#endif
+ }
- if (in_addr[i].hash.buckets == NULL
- && (in_addr[i].wc_head == NULL
- || in_addr[i].wc_head->hash.buckets == NULL)
- && (in_addr[i].wc_head == NULL
- || in_addr[i].wc_head->hash.buckets == NULL))
- {
- continue;
- }
+ return NGX_OK;
+}
- vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
- if (vn == NULL) {
- return NGX_ERROR;
- }
- hip->addrs[i].virtual_names = vn;
- vn->names.hash = in_addr[i].hash;
- vn->names.wc_head = in_addr[i].wc_head;
- vn->names.wc_tail = in_addr[i].wc_tail;
-#if (NGX_PCRE)
- vn->nregex = in_addr[i].nregex;
- vn->regex = in_addr[i].regex;
+#if (NGX_HAVE_INET6)
+
+static ngx_int_t
+ngx_http_add_addrs6(ngx_conf_t *cf, ngx_http_port_t *hport,
+ ngx_http_conf_addr_t *addr)
+{
+ ngx_uint_t i;
+ ngx_http_in6_addr_t *addrs6;
+ struct sockaddr_in6 *sin6;
+ ngx_http_virtual_names_t *vn;
+
+ hport->addrs = ngx_pcalloc(cf->pool,
+ hport->naddrs * sizeof(ngx_http_in6_addr_t));
+ if (hport->addrs == NULL) {
+ return NGX_ERROR;
+ }
+
+ addrs6 = hport->addrs;
+
+ for (i = 0; i < hport->naddrs; i++) {
+
+ sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
+ addrs6[i].addr6 = sin6->sin6_addr;
+ addrs6[i].conf.core_srv_conf = addr[i].core_srv_conf;
+#if (NGX_HTTP_SSL)
+ addrs6[i].conf.ssl = addr[i].ssl;
#endif
+
+ if (addr[i].hash.buckets == NULL
+ && (addr[i].wc_head == NULL
+ || addr[i].wc_head->hash.buckets == NULL)
+ && (addr[i].wc_head == NULL
+ || addr[i].wc_head->hash.buckets == NULL))
+ {
+ continue;
}
- if (done) {
- return NGX_OK;
+ vn = ngx_palloc(cf->pool, sizeof(ngx_http_virtual_names_t));
+ if (vn == NULL) {
+ return NGX_ERROR;
}
- in_addr++;
- in_port->addrs.elts = in_addr;
- last--;
+ addrs6[i].conf.virtual_names = vn;
- a = 0;
+ vn->names.hash = addr[i].hash;
+ vn->names.wc_head = addr[i].wc_head;
+ vn->names.wc_tail = addr[i].wc_tail;
+#if (NGX_PCRE)
+ vn->nregex = addr[i].nregex;
+ vn->regex = addr[i].regex;
+#endif
}
return NGX_OK;
}
+#endif
+
char *
ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 3f5cb29dc..a54a1217e 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1776,32 +1776,37 @@ ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
{
socklen_t len;
ngx_connection_t *c;
- struct sockaddr_in sin;
-
- /* AF_INET only */
+ struct sockaddr_in *sin;
+ u_char sa[NGX_SOCKADDRLEN];
c = r->connection;
- if (r->in_addr == 0) {
- len = sizeof(struct sockaddr_in);
- if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
+ if (c->local_sockaddr == NULL) {
+
+ len = NGX_SOCKADDRLEN;
+
+ if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) {
ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
return NGX_ERROR;
}
- r->in_addr = sin.sin_addr.s_addr;
+ c->local_sockaddr = ngx_palloc(r->connection->pool, len);
+ if (c->local_sockaddr == NULL) {
+ return NGX_ERROR;
+ }
- } else {
- sin.sin_family = c->sockaddr->sa_family;
- sin.sin_addr.s_addr = r->in_addr;
+ c->local_socklen = len;
+ ngx_memcpy(c->local_sockaddr, &sa, len);
}
+ sin = (struct sockaddr_in *) c->local_sockaddr;
+ r->in_addr = sin->sin_addr.s_addr;
+
if (s == NULL) {
return NGX_OK;
}
- s->len = ngx_sock_ntop((struct sockaddr *) &sin, s->data,
- NGX_INET_ADDRSTRLEN);
+ s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, 0);
return NGX_OK;
}
@@ -2729,7 +2734,8 @@ ngx_http_core_create_srv_conf(ngx_conf_t *cf)
* conf->client_large_buffers.num = 0;
*/
- if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t))
+ if (ngx_array_init(&cscf->listen, cf->temp_pool, 4,
+ sizeof(ngx_http_listen_t))
== NGX_ERROR)
{
return NGX_CONF_ERROR;
@@ -2761,6 +2767,7 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_core_srv_conf_t *conf = child;
ngx_http_listen_t *ls;
+ struct sockaddr_in *sin;
ngx_http_server_name_t *sn;
/* TODO: it does not merge, it inits only */
@@ -2773,14 +2780,15 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_memzero(ls, sizeof(ngx_http_listen_t));
- ls->addr = INADDR_ANY;
+ sin = (struct sockaddr_in *) &ls->sockaddr;
+
+ sin->sin_family = AF_INET;
#if (NGX_WIN32)
- ls->port = 80;
+ sin->sin_port = htons(80);
#else
- /* STUB: getuid() should be cached */
- ls->port = (getuid() == 0) ? 80 : 8000;
+ sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
#endif
- ls->family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
ls->conf.backlog = NGX_LISTEN_BACKLOG;
ls->conf.rcvbuf = -1;
@@ -3159,8 +3167,6 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
-/* AF_INET only */
-
static char *
ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
@@ -3201,17 +3207,18 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_memzero(ls, sizeof(ngx_http_listen_t));
- ls->family = u.family;
- ls->addr = u.addr.in_addr;
- ls->port = u.port;
+ ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
+
+ ls->socklen = u.socklen;
ls->file_name = cf->conf_file->file.name.data;
ls->line = cf->conf_file->line;
ls->conf.backlog = NGX_LISTEN_BACKLOG;
ls->conf.rcvbuf = -1;
ls->conf.sndbuf = -1;
+ ls->conf.wildcard = u.wildcard;
- n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, NGX_INET_ADDRSTRLEN);
- ngx_sprintf(&ls->conf.addr[n], ":%ui", ls->port);
+ (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr,
+ NGX_SOCKADDR_STRLEN, 1);
if (cf->args->nelts == 2) {
return NGX_CONF_OK;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 21a53552e..2fdc1020b 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -40,6 +40,7 @@ typedef struct ngx_http_core_loc_conf_s ngx_http_core_loc_conf_t;
typedef struct {
unsigned default_server:1;
unsigned bind:1;
+ unsigned wildcard:1;
#if (NGX_HTTP_SSL)
unsigned ssl:1;
#endif
@@ -55,15 +56,13 @@ typedef struct {
ngx_uint_t deferred_accept;
#endif
- u_char addr[NGX_INET_ADDRSTRLEN + sizeof(":65535")];
-
+ u_char addr[NGX_SOCKADDR_STRLEN + 1];
} ngx_http_listen_conf_t;
typedef struct {
- in_addr_t addr;
- in_port_t port;
- int family;
+ u_char sockaddr[NGX_SOCKADDRLEN];
+ socklen_t socklen;
u_char *file_name;
ngx_uint_t line;
@@ -173,8 +172,6 @@ typedef struct {
typedef struct {
- in_addr_t addr;
-
/* the default server configuration for this address:port */
ngx_http_core_srv_conf_t *core_srv_conf;
@@ -183,25 +180,45 @@ typedef struct {
#if (NGX_HTTP_SSL)
ngx_uint_t ssl; /* unsigned ssl:1; */
#endif
+} ngx_http_addr_conf_t;
+
+
+typedef struct {
+ in_addr_t addr;
+ ngx_http_addr_conf_t conf;
} ngx_http_in_addr_t;
+#if (NGX_HAVE_INET6)
+
+typedef struct {
+ struct in6_addr addr6;
+ ngx_http_addr_conf_t conf;
+} ngx_http_in6_addr_t;
+
+#endif
+
+
typedef struct {
in_port_t port;
ngx_str_t port_text;
- ngx_http_in_addr_t *addrs;
+
+ /* ngx_http_in_addr_t or ngx_http_in6_addr_t */
+ void *addrs;
ngx_uint_t naddrs;
-} ngx_http_in_port_t;
+} ngx_http_port_t;
typedef struct {
+ ngx_int_t family;
in_port_t port;
- ngx_array_t addrs; /* array of ngx_http_conf_in_addr_t */
-} ngx_http_conf_in_port_t;
+ ngx_array_t addrs; /* array of ngx_http_conf_addr_t */
+} ngx_http_conf_port_t;
typedef struct {
- in_addr_t addr;
+ struct sockaddr *sockaddr;
+ socklen_t socklen;
ngx_hash_t hash;
ngx_hash_wildcard_t *wc_head;
@@ -219,12 +236,13 @@ typedef struct {
unsigned default_server:1;
unsigned bind:1;
+ unsigned wildcard:1;
#if (NGX_HTTP_SSL)
unsigned ssl:1;
#endif
ngx_http_listen_conf_t *listen_conf;
-} ngx_http_conf_in_addr_t;
+} ngx_http_conf_addr_t;
struct ngx_http_server_name_s {
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index de9533391..f9476c695 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -161,8 +161,7 @@ ngx_http_header_filter(ngx_http_request_t *r)
ngx_table_elt_t *header;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
- /* AF_INET only */
- u_char addr[NGX_INET_ADDRSTRLEN];
+ u_char addr[NGX_SOCKADDR_STRLEN];
r->header_sent = 1;
@@ -290,6 +289,7 @@ ngx_http_header_filter(ngx_http_request_t *r)
host = r->headers_in.server;
} else {
+ host.len = NGX_SOCKADDR_STRLEN;
host.data = addr;
if (ngx_http_server_addr(r, &host) != NGX_OK) {
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 3a1c5f700..f03b574f9 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -232,13 +232,19 @@ ngx_http_init_request(ngx_event_t *rev)
ngx_uint_t i;
ngx_connection_t *c;
ngx_http_request_t *r;
- ngx_http_in_port_t *hip;
- ngx_http_in_addr_t *hia;
+ struct sockaddr_in *sin;
+ ngx_http_port_t *port;
+ ngx_http_in_addr_t *addr;
ngx_http_log_ctx_t *ctx;
+ ngx_http_addr_conf_t *addr_conf;
ngx_http_connection_t *hc;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_main_conf_t *cmcf;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+ ngx_http_in6_addr_t *addr6;
+#endif
#if (NGX_STAT_STUB)
ngx_atomic_fetch_add(ngx_stat_reading, -1);
@@ -292,58 +298,90 @@ ngx_http_init_request(ngx_event_t *rev)
/* find the server configuration for the address:port */
- /* AF_INET only */
-
- hip = c->listening->servers;
- hia = hip->addrs;
-
- r->port = hip->port;
- r->port_text = &hip->port_text;
+ port = c->listening->servers;
- i = 0;
+ r->port = port->port;
+ r->port_text = &port->port_text;
r->connection = c;
- if (hip->naddrs > 1) {
+ if (port->naddrs > 1) {
/*
- * There are several addresses on this port and one of them
- * is the "*:port" wildcard so getsockname() is needed to determine
- * the server address.
- *
- * AcceptEx() already has given this address.
+ * there are several addresses on this port and one of them
+ * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
+ * is required to determine a server address
*/
-#if (NGX_WIN32)
- if (c->local_sockaddr) {
- r->in_addr =
- ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
+ c->local_sockaddr = NULL;
- } else
-#endif
- {
- if (ngx_http_server_addr(r, NULL) != NGX_OK) {
- ngx_http_close_connection(c);
- return;
- }
+ if (ngx_http_server_addr(r, NULL) != NGX_OK) {
+ ngx_http_close_connection(c);
+ return;
}
- /* the last address is "*" */
+ switch (c->local_sockaddr->sa_family) {
- for ( /* void */ ; i < hip->naddrs - 1; i++) {
- if (hia[i].addr == r->in_addr) {
- break;
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
+
+ addr6 = (ngx_http_in6_addr_t *) port->addrs;
+
+ /* the last address is "*" */
+
+ for (i = 0; i < port->naddrs - 1; i++) {
+ if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
+ break;
+ }
}
+
+ addr_conf = &addr6[i].conf;
+
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) c->local_sockaddr;
+
+ addr = port->addrs;
+
+ /* the last address is "*" */
+
+ for (i = 0; i < port->naddrs - 1; i++) {
+ if (addr[i].addr == sin->sin_addr.s_addr) {
+ break;
+ }
+ }
+
+ addr_conf = &addr[i].conf;
+
+ break;
}
} else {
- r->in_addr = hia[0].addr;
+
+ switch (c->local_sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ addr6 = (ngx_http_in6_addr_t *) port->addrs;
+ addr_conf = &addr6[0].conf;
+ break;
+#endif
+
+ default: /* AF_INET */
+ addr = port->addrs;
+ addr_conf = &addr[0].conf;
+ r->in_addr = addr[0].addr;
+ break;
+ }
}
- r->virtual_names = hia[i].virtual_names;
+ r->virtual_names = addr_conf->virtual_names;
/* the default server configuration for the address:port */
- cscf = hia[i].core_srv_conf;
+ cscf = addr_conf->core_srv_conf;
r->main_conf = cscf->ctx->main_conf;
r->srv_conf = cscf->ctx->srv_conf;
@@ -357,13 +395,13 @@ ngx_http_init_request(ngx_event_t *rev)
ngx_http_ssl_srv_conf_t *sscf;
sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
- if (sscf->enable || hia[i].ssl) {
+ if (sscf->enable || addr_conf->ssl) {
if (c->ssl == NULL) {
c->log->action = "SSL handshaking";
- if (hia[i].ssl && sscf->ssl.ctx == NULL) {
+ if (addr_conf->ssl && sscf->ssl.ctx == NULL) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"no \"ssl_certificate\" is defined "
"in server listening on SSL port");
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 98fef371b..81c8528fe 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -828,17 +828,37 @@ static ngx_int_t
ngx_http_variable_binary_remote_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
- struct sockaddr_in *sin;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+#endif
- /* AF_INET only */
+ switch (r->connection->sockaddr->sa_family) {
- sin = (struct sockaddr_in *) r->connection->sockaddr;
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
- v->len = sizeof(in_addr_t);
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = (u_char *) &sin->sin_addr.s_addr;
+ v->len = sizeof(struct in6_addr);
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) &sin6->sin6_addr;
+
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
+
+ v->len = sizeof(in_addr_t);
+ v->valid = 1;
+ v->no_cacheable = 0;
+ v->not_found = 0;
+ v->data = (u_char *) &sin->sin_addr;
+
+ break;
+ }
return NGX_OK;
}
@@ -862,8 +882,11 @@ static ngx_int_t
ngx_http_variable_remote_port(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
- ngx_uint_t port;
- struct sockaddr_in *sin;
+ ngx_uint_t port;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+#endif
v->len = 0;
v->valid = 1;
@@ -875,16 +898,23 @@ ngx_http_variable_remote_port(ngx_http_request_t *r,
return NGX_ERROR;
}
- /* AF_INET only */
+ switch (r->connection->sockaddr->sa_family) {
- if (r->connection->sockaddr->sa_family == AF_INET) {
- sin = (struct sockaddr_in *) r->connection->sockaddr;
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+ port = ntohs(sin6->sin6_port);
+ break;
+#endif
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) r->connection->sockaddr;
port = ntohs(sin->sin_port);
+ break;
+ }
- if (port > 0 && port < 65536) {
- v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
- }
+ if (port > 0 && port < 65536) {
+ v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
}
return NGX_OK;
@@ -896,16 +926,22 @@ ngx_http_variable_server_addr(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
ngx_str_t s;
+ u_char addr[NGX_SOCKADDR_STRLEN];
- s.data = ngx_pnalloc(r->pool, NGX_INET_ADDRSTRLEN);
- if (s.data == NULL) {
+ s.len = NGX_SOCKADDR_STRLEN;
+ s.data = addr;
+
+ if (ngx_http_server_addr(r, &s) != NGX_OK) {
return NGX_ERROR;
}
- if (ngx_http_server_addr(r, &s) != NGX_OK) {
+ s.data = ngx_pnalloc(r->pool, s.len);
+ if (s.data == NULL) {
return NGX_ERROR;
}
+ ngx_memcpy(s.data, addr, s.len);
+
v->len = s.len;
v->valid = 1;
v->no_cacheable = 0;
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index 10e6c8b5e..a9cd6a4da 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -305,6 +305,11 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
+ if (u.family != AF_INET) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "listen supports IPv4 only");
+ return NGX_CONF_ERROR;
+ }
+
cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
imls = cmcf->listen.elts;