From e434499c48d7edbe43d3e2cd2424650751f5d4b9 Mon Sep 17 00:00:00 2001 From: Dobrica Pavlinusic Date: Sat, 21 Mar 2009 17:53:50 +0100 Subject: [PATCH] upstream nginx-0.7.36 --- nginx/CHANGES | 9 + nginx/CHANGES.ru | 9 + nginx/auto/options | 6 + nginx/auto/unix | 15 + nginx/src/core/nginx.h | 2 +- nginx/src/core/ngx_connection.c | 30 +- nginx/src/core/ngx_connection.h | 3 - nginx/src/core/ngx_cycle.c | 46 +- nginx/src/core/ngx_inet.c | 338 ++++++- nginx/src/core/ngx_inet.h | 27 +- nginx/src/event/ngx_event_accept.c | 14 +- .../src/http/modules/ngx_http_access_module.c | 6 +- .../http/modules/ngx_http_browser_module.c | 6 + .../http/modules/ngx_http_empty_gif_module.c | 1 + nginx/src/http/modules/ngx_http_geo_module.c | 4 + .../src/http/modules/ngx_http_realip_module.c | 6 +- .../ngx_http_upstream_ip_hash_module.c | 20 +- nginx/src/http/modules/perl/nginx.pm | 2 +- nginx/src/http/ngx_http.c | 860 +++++++++++------- nginx/src/http/ngx_http_core_module.c | 57 +- nginx/src/http/ngx_http_core_module.h | 44 +- .../src/http/ngx_http_header_filter_module.c | 4 +- nginx/src/http/ngx_http_request.c | 110 ++- nginx/src/http/ngx_http_variables.c | 74 +- nginx/src/mail/ngx_mail_core_module.c | 5 + 25 files changed, 1191 insertions(+), 507 deletions(-) diff --git a/nginx/CHANGES b/nginx/CHANGES index d8972e2..ff91948 100644 --- a/nginx/CHANGES +++ b/nginx/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/nginx/CHANGES.ru b/nginx/CHANGES.ru index ad56b05..76f95f3 100644 --- a/nginx/CHANGES.ru +++ b/nginx/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/nginx/auto/options b/nginx/auto/options index 9e6e1a2..fabd5d0 100644 --- a/nginx/auto/options +++ b/nginx/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/nginx/auto/unix b/nginx/auto/unix index 245d4f7..7d6e480 100755 --- a/nginx/auto/unix +++ b/nginx/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 + #include + #include " + 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/nginx/src/core/nginx.h b/nginx/src/core/nginx.h index 5a59792..a757604 100644 --- a/nginx/src/core/nginx.h +++ b/nginx/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/nginx/src/core/ngx_connection.c b/nginx/src/core/ngx_connection.c index 28c904b..f48eefb 100644 --- a/nginx/src/core/ngx_connection.c +++ b/nginx/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/nginx/src/core/ngx_connection.h b/nginx/src/core/ngx_connection.h index 573fb3c..d9b80f9 100644 --- a/nginx/src/core/ngx_connection.h +++ b/nginx/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/nginx/src/core/ngx_cycle.c b/nginx/src/core/ngx_cycle.c index aa0d9ce..9ee7e65 100644 --- a/nginx/src/core/ngx_cycle.c +++ b/nginx/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/nginx/src/core/ngx_inet.c b/nginx/src/core/ngx_inet.c index 5c88a9d..7ccf664 100644 --- a/nginx/src/core/ngx_inet.c +++ b/nginx/src/core/ngx_inet.c @@ -8,12 +8,14 @@ #include +#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/nginx/src/core/ngx_inet.h b/nginx/src/core/ngx_inet.h index be78142..d60c9c7 100644 --- a/nginx/src/core/ngx_inet.h +++ b/nginx/src/core/ngx_inet.h @@ -12,7 +12,25 @@ #include -#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/nginx/src/event/ngx_event_accept.c b/nginx/src/event/ngx_event_accept.c index 379abb9..d39a497 100644 --- a/nginx/src/event/ngx_event_accept.c +++ b/nginx/src/event/ngx_event_accept.c @@ -9,10 +9,6 @@ #include -/* 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/nginx/src/http/modules/ngx_http_access_module.c b/nginx/src/http/modules/ngx_http_access_module.c index 12f0b99..8cd2e0e 100644 --- a/nginx/src/http/modules/ngx_http_access_module.c +++ b/nginx/src/http/modules/ngx_http_access_module.c @@ -9,8 +9,6 @@ #include -/* 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/nginx/src/http/modules/ngx_http_browser_module.c b/nginx/src/http/modules/ngx_http_browser_module.c index 083375b..e0710c1 100644 --- a/nginx/src/http/modules/ngx_http_browser_module.c +++ b/nginx/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/nginx/src/http/modules/ngx_http_empty_gif_module.c b/nginx/src/http/modules/ngx_http_empty_gif_module.c index 8450cae..e6515df 100644 --- a/nginx/src/http/modules/ngx_http_empty_gif_module.c +++ b/nginx/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/nginx/src/http/modules/ngx_http_geo_module.c b/nginx/src/http/modules/ngx_http_geo_module.c index bd6499e..a8f2685 100644 --- a/nginx/src/http/modules/ngx_http_geo_module.c +++ b/nginx/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/nginx/src/http/modules/ngx_http_realip_module.c b/nginx/src/http/modules/ngx_http_realip_module.c index 44c74a1..58bdeeb 100644 --- a/nginx/src/http/modules/ngx_http_realip_module.c +++ b/nginx/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/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c b/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c index 1d13481..dffbf22 100644 --- a/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +++ b/nginx/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/nginx/src/http/modules/perl/nginx.pm b/nginx/src/http/modules/perl/nginx.pm index 90989da..d33310e 100644 --- a/nginx/src/http/modules/perl/nginx.pm +++ b/nginx/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/nginx/src/http/ngx_http.c b/nginx/src/http/ngx_http.c index 6157888..ecd9c97 100644 --- a/nginx/src/http/ngx_http.c +++ b/nginx/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/nginx/src/http/ngx_http_core_module.c b/nginx/src/http/ngx_http_core_module.c index 3f5cb29..a54a121 100644 --- a/nginx/src/http/ngx_http_core_module.c +++ b/nginx/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/nginx/src/http/ngx_http_core_module.h b/nginx/src/http/ngx_http_core_module.h index 21a5355..2fdc102 100644 --- a/nginx/src/http/ngx_http_core_module.h +++ b/nginx/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/nginx/src/http/ngx_http_header_filter_module.c b/nginx/src/http/ngx_http_header_filter_module.c index de95333..f9476c6 100644 --- a/nginx/src/http/ngx_http_header_filter_module.c +++ b/nginx/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/nginx/src/http/ngx_http_request.c b/nginx/src/http/ngx_http_request.c index 3a1c5f7..f03b574 100644 --- a/nginx/src/http/ngx_http_request.c +++ b/nginx/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/nginx/src/http/ngx_http_variables.c b/nginx/src/http/ngx_http_variables.c index 98fef37..81c8528 100644 --- a/nginx/src/http/ngx_http_variables.c +++ b/nginx/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/nginx/src/mail/ngx_mail_core_module.c b/nginx/src/mail/ngx_mail_core_module.c index 10e6c8b..a9cd6a4 100644 --- a/nginx/src/mail/ngx_mail_core_module.c +++ b/nginx/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; -- 2.20.1