summaryrefslogtreecommitdiffstats
path: root/usr.sbin/nginx/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/nginx/src/core')
-rw-r--r--usr.sbin/nginx/src/core/nginx.c9
-rw-r--r--usr.sbin/nginx/src/core/nginx.h4
-rw-r--r--usr.sbin/nginx/src/core/ngx_conf_file.c96
-rw-r--r--usr.sbin/nginx/src/core/ngx_conf_file.h6
-rw-r--r--usr.sbin/nginx/src/core/ngx_config.h4
-rw-r--r--usr.sbin/nginx/src/core/ngx_connection.c129
-rw-r--r--usr.sbin/nginx/src/core/ngx_connection.h11
-rw-r--r--usr.sbin/nginx/src/core/ngx_core.h2
-rw-r--r--usr.sbin/nginx/src/core/ngx_cycle.c128
-rw-r--r--usr.sbin/nginx/src/core/ngx_cycle.h2
-rw-r--r--usr.sbin/nginx/src/core/ngx_file.c108
-rw-r--r--usr.sbin/nginx/src/core/ngx_file.h3
-rw-r--r--usr.sbin/nginx/src/core/ngx_hash.c15
-rw-r--r--usr.sbin/nginx/src/core/ngx_inet.c98
-rw-r--r--usr.sbin/nginx/src/core/ngx_inet.h6
-rw-r--r--usr.sbin/nginx/src/core/ngx_list.c10
-rw-r--r--usr.sbin/nginx/src/core/ngx_log.c385
-rw-r--r--usr.sbin/nginx/src/core/ngx_log.h29
-rw-r--r--usr.sbin/nginx/src/core/ngx_open_file_cache.c68
-rw-r--r--usr.sbin/nginx/src/core/ngx_palloc.c7
-rw-r--r--usr.sbin/nginx/src/core/ngx_proxy_protocol.c91
-rw-r--r--usr.sbin/nginx/src/core/ngx_proxy_protocol.h23
-rw-r--r--usr.sbin/nginx/src/core/ngx_resolver.c1335
-rw-r--r--usr.sbin/nginx/src/core/ngx_resolver.h36
-rw-r--r--usr.sbin/nginx/src/core/ngx_slab.c9
-rw-r--r--usr.sbin/nginx/src/core/ngx_slab.h2
-rw-r--r--usr.sbin/nginx/src/core/ngx_string.c91
-rw-r--r--usr.sbin/nginx/src/core/ngx_string.h2
-rw-r--r--usr.sbin/nginx/src/core/ngx_syslog.c342
-rw-r--r--usr.sbin/nginx/src/core/ngx_syslog.h30
-rw-r--r--usr.sbin/nginx/src/core/ngx_times.c21
-rw-r--r--usr.sbin/nginx/src/core/ngx_times.h1
32 files changed, 2291 insertions, 812 deletions
diff --git a/usr.sbin/nginx/src/core/nginx.c b/usr.sbin/nginx/src/core/nginx.c
index 7f0011d879f..5960fa85658 100644
--- a/usr.sbin/nginx/src/core/nginx.c
+++ b/usr.sbin/nginx/src/core/nginx.c
@@ -389,13 +389,8 @@ main(int argc, char *const *argv)
return 1;
}
- if (cycle->log->file->fd != ngx_stderr) {
-
- if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- ngx_set_stderr_n " failed");
- return 1;
- }
+ if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
+ return 1;
}
if (log->file->fd != ngx_stderr) {
diff --git a/usr.sbin/nginx/src/core/nginx.h b/usr.sbin/nginx/src/core/nginx.h
index 77c88bf5f94..0ef0f2e110f 100644
--- a/usr.sbin/nginx/src/core/nginx.h
+++ b/usr.sbin/nginx/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1004007
-#define NGINX_VERSION "1.4.7"
+#define nginx_version 1006000
+#define NGINX_VERSION "1.6.0"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/usr.sbin/nginx/src/core/ngx_conf_file.c b/usr.sbin/nginx/src/core/ngx_conf_file.c
index a262672139c..f61bfcabf99 100644
--- a/usr.sbin/nginx/src/core/ngx_conf_file.c
+++ b/usr.sbin/nginx/src/core/ngx_conf_file.c
@@ -12,7 +12,6 @@
static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf);
-static ngx_int_t ngx_conf_test_full_name(ngx_str_t *name);
static void ngx_conf_flush_files(ngx_cycle_t *cycle);
@@ -225,6 +224,11 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
* "types { ... }" directive
*/
+ if (rc == NGX_CONF_BLOCK_START) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"{\"");
+ goto failed;
+ }
+
rv = (*cf->handler)(cf, NULL, cf->handler_conf);
if (rv == NGX_CONF_OK) {
continue;
@@ -796,95 +800,11 @@ ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_int_t
ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix)
{
- size_t len;
- u_char *p, *n, *prefix;
- ngx_int_t rc;
-
- rc = ngx_conf_test_full_name(name);
-
- if (rc == NGX_OK) {
- return rc;
- }
-
- if (conf_prefix) {
- len = cycle->conf_prefix.len;
- prefix = cycle->conf_prefix.data;
-
- } else {
- len = cycle->prefix.len;
- prefix = cycle->prefix.data;
- }
-
-#if (NGX_WIN32)
-
- if (rc == 2) {
- len = rc;
- }
-
-#endif
-
- n = ngx_pnalloc(cycle->pool, len + name->len + 1);
- if (n == NULL) {
- return NGX_ERROR;
- }
-
- p = ngx_cpymem(n, prefix, len);
- ngx_cpystrn(p, name->data, name->len + 1);
-
- name->len += len;
- name->data = n;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_conf_test_full_name(ngx_str_t *name)
-{
-#if (NGX_WIN32)
- u_char c0, c1;
-
- c0 = name->data[0];
-
- if (name->len < 2) {
- if (c0 == '/') {
- return 2;
- }
+ ngx_str_t *prefix;
- return NGX_DECLINED;
- }
-
- c1 = name->data[1];
-
- if (c1 == ':') {
- c0 |= 0x20;
+ prefix = conf_prefix ? &cycle->conf_prefix : &cycle->prefix;
- if ((c0 >= 'a' && c0 <= 'z')) {
- return NGX_OK;
- }
-
- return NGX_DECLINED;
- }
-
- if (c1 == '/') {
- return NGX_OK;
- }
-
- if (c0 == '/') {
- return 2;
- }
-
- return NGX_DECLINED;
-
-#else
-
- if (name->data[0] == '/') {
- return NGX_OK;
- }
-
- return NGX_DECLINED;
-
-#endif
+ return ngx_get_full_name(cycle->pool, prefix, name);
}
diff --git a/usr.sbin/nginx/src/core/ngx_conf_file.h b/usr.sbin/nginx/src/core/ngx_conf_file.h
index 237e6ecea6e..d73a6c8bf55 100644
--- a/usr.sbin/nginx/src/core/ngx_conf_file.h
+++ b/usr.sbin/nginx/src/core/ngx_conf_file.h
@@ -5,8 +5,8 @@
*/
-#ifndef _NGX_HTTP_CONF_FILE_H_INCLUDED_
-#define _NGX_HTTP_CONF_FILE_H_INCLUDED_
+#ifndef _NGX_CONF_FILE_H_INCLUDED_
+#define _NGX_CONF_FILE_H_INCLUDED_
#include <ngx_config.h>
@@ -337,4 +337,4 @@ extern ngx_uint_t ngx_max_module;
extern ngx_module_t *ngx_modules[];
-#endif /* _NGX_HTTP_CONF_FILE_H_INCLUDED_ */
+#endif /* _NGX_CONF_FILE_H_INCLUDED_ */
diff --git a/usr.sbin/nginx/src/core/ngx_config.h b/usr.sbin/nginx/src/core/ngx_config.h
index b0cb17fca80..1da71f8d1a1 100644
--- a/usr.sbin/nginx/src/core/ngx_config.h
+++ b/usr.sbin/nginx/src/core/ngx_config.h
@@ -80,8 +80,8 @@ typedef uintptr_t ngx_uint_t;
typedef intptr_t ngx_flag_t;
-#define NGX_INT32_LEN sizeof("-2147483648") - 1
-#define NGX_INT64_LEN sizeof("-9223372036854775808") - 1
+#define NGX_INT32_LEN (sizeof("-2147483648") - 1)
+#define NGX_INT64_LEN (sizeof("-9223372036854775808") - 1)
#if (NGX_PTR_SIZE == 4)
#define NGX_INT_T_LEN NGX_INT32_LEN
diff --git a/usr.sbin/nginx/src/core/ngx_connection.c b/usr.sbin/nginx/src/core/ngx_connection.c
index 986bf0d0208..6b6e3b3a512 100644
--- a/usr.sbin/nginx/src/core/ngx_connection.c
+++ b/usr.sbin/nginx/src/core/ngx_connection.c
@@ -41,7 +41,7 @@ ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)
ls->sockaddr = sa;
ls->socklen = socklen;
- len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
+ len = ngx_sock_ntop(sa, socklen, text, NGX_SOCKADDR_STRLEN, 1);
ls->addr_text.len = len;
switch (ls->sockaddr->sa_family) {
@@ -82,6 +82,10 @@ ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)
ls->setfib = -1;
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ ls->fastopen = -1;
+#endif
+
return ls;
}
@@ -93,8 +97,10 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
ngx_uint_t i;
ngx_listening_t *ls;
socklen_t olen;
-#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+#if (NGX_HAVE_DEFERRED_ACCEPT || NGX_HAVE_TCP_FASTOPEN)
ngx_err_t err;
+#endif
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
struct accept_filter_arg af;
#endif
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
@@ -123,7 +129,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
#if (NGX_HAVE_INET6)
case AF_INET6:
ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
- len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
+ len = NGX_INET6_ADDRSTRLEN + sizeof("[]:65535") - 1;
break;
#endif
@@ -152,7 +158,8 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
return NGX_ERROR;
}
- len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data, len, 1);
+ len = ngx_sock_ntop(ls[i].sockaddr, ls[i].socklen,
+ ls[i].addr_text.data, len, 1);
if (len == 0) {
return NGX_ERROR;
}
@@ -192,7 +199,9 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
#if (NGX_HAVE_SETFIB)
- if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB,
+ olen = sizeof(int);
+
+ if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
(void *) &ls[i].setfib, &olen)
== -1)
{
@@ -206,6 +215,27 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
#endif
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+
+ olen = sizeof(int);
+
+ if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
+ (void *) &ls[i].fastopen, &olen)
+ == -1)
+ {
+ err = ngx_socket_errno;
+
+ if (err != NGX_EOPNOTSUPP && err != NGX_ENOPROTOOPT) {
+ ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
+ "getsockopt(TCP_FASTOPEN) %V failed, ignored",
+ &ls[i].addr_text);
+ }
+
+ ls[i].fastopen = -1;
+ }
+
+#endif
+
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
ngx_memzero(&af, sizeof(struct accept_filter_arg));
@@ -214,7 +244,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
== -1)
{
- err = ngx_errno;
+ err = ngx_socket_errno;
if (err == NGX_EINVAL) {
continue;
@@ -247,7 +277,13 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
== -1)
{
- ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
+ err = ngx_socket_errno;
+
+ if (err == NGX_EOPNOTSUPP) {
+ continue;
+ }
+
+ ngx_log_error(NGX_LOG_NOTICE, cycle->log, err,
"getsockopt(TCP_DEFER_ACCEPT) for %V failed, ignored",
&ls[i].addr_text);
continue;
@@ -296,7 +332,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
continue;
}
- if (ls[i].fd != -1) {
+ if (ls[i].fd != (ngx_socket_t) -1) {
continue;
}
@@ -311,7 +347,7 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0);
- if (s == -1) {
+ if (s == (ngx_socket_t) -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
ngx_socket_n " %V failed", &ls[i].addr_text);
return NGX_ERROR;
@@ -463,16 +499,13 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle)
void
ngx_configure_listening_sockets(ngx_cycle_t *cycle)
{
- int keepalive;
+ int value;
ngx_uint_t i;
ngx_listening_t *ls;
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
struct accept_filter_arg af;
#endif
-#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
- int timeout;
-#endif
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
@@ -502,39 +535,51 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
}
if (ls[i].keepalive) {
- keepalive = (ls[i].keepalive == 1) ? 1 : 0;
+ value = (ls[i].keepalive == 1) ? 1 : 0;
if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,
- (const void *) &keepalive, sizeof(int))
+ (const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(SO_KEEPALIVE, %d) %V failed, ignored",
- keepalive, &ls[i].addr_text);
+ value, &ls[i].addr_text);
}
}
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
if (ls[i].keepidle) {
+ value = ls[i].keepidle;
+
+#if (NGX_KEEPALIVE_FACTOR)
+ value *= NGX_KEEPALIVE_FACTOR;
+#endif
+
if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
- (const void *) &ls[i].keepidle, sizeof(int))
+ (const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
- ls[i].keepidle, &ls[i].addr_text);
+ value, &ls[i].addr_text);
}
}
if (ls[i].keepintvl) {
+ value = ls[i].keepintvl;
+
+#if (NGX_KEEPALIVE_FACTOR)
+ value *= NGX_KEEPALIVE_FACTOR;
+#endif
+
if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPINTVL,
- (const void *) &ls[i].keepintvl, sizeof(int))
+ (const void *) &value, sizeof(int))
== -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(TCP_KEEPINTVL, %d) %V failed, ignored",
- ls[i].keepintvl, &ls[i].addr_text);
+ value, &ls[i].addr_text);
}
}
@@ -564,6 +609,19 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
}
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ if (ls[i].fastopen != -1) {
+ if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_FASTOPEN,
+ (const void *) &ls[i].fastopen, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(TCP_FASTOPEN, %d) %V failed, ignored",
+ ls[i].fastopen, &ls[i].addr_text);
+ }
+ }
+#endif
+
#if 0
if (1) {
int tcp_nodelay = 1;
@@ -603,7 +661,7 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0)
== -1)
{
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(SO_ACCEPTFILTER, NULL) "
"for %V failed, ignored",
&ls[i].addr_text);
@@ -630,7 +688,7 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
&af, sizeof(struct accept_filter_arg))
== -1)
{
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(SO_ACCEPTFILTER, \"%s\") "
"for %V failed, ignored",
ls[i].accept_filter, &ls[i].addr_text);
@@ -653,20 +711,20 @@ ngx_configure_listening_sockets(ngx_cycle_t *cycle)
* if syncookies were used), hence we use 1 second timeout
* here.
*/
- timeout = 1;
+ value = 1;
} else {
- timeout = 0;
+ value = 0;
}
if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
- &timeout, sizeof(int))
+ &value, sizeof(int))
== -1)
{
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
"setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
"ignored",
- timeout, &ls[i].addr_text);
+ value, &ls[i].addr_text);
continue;
}
@@ -859,7 +917,7 @@ ngx_close_connection(ngx_connection_t *c)
ngx_uint_t log_error, level;
ngx_socket_t fd;
- if (c->fd == -1) {
+ if (c->fd == (ngx_socket_t) -1) {
ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
return;
}
@@ -1034,6 +1092,10 @@ ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
struct sockaddr_in6 *sin6;
#endif
+ if (c->local_socklen == 0) {
+ return NGX_ERROR;
+ }
+
switch (c->local_sockaddr->sa_family) {
#if (NGX_HAVE_INET6)
@@ -1047,6 +1109,12 @@ ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
break;
#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+ addr = 1;
+ break;
+#endif
+
default: /* AF_INET */
sin = (struct sockaddr_in *) c->local_sockaddr;
addr = sin->sin_addr.s_addr;
@@ -1068,13 +1136,16 @@ ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
}
ngx_memcpy(c->local_sockaddr, &sa, len);
+
+ c->local_socklen = len;
}
if (s == NULL) {
return NGX_OK;
}
- s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, port);
+ s->len = ngx_sock_ntop(c->local_sockaddr, c->local_socklen,
+ s->data, s->len, port);
return NGX_OK;
}
diff --git a/usr.sbin/nginx/src/core/ngx_connection.h b/usr.sbin/nginx/src/core/ngx_connection.h
index 3daf2eee4cb..ed14e6023e7 100644
--- a/usr.sbin/nginx/src/core/ngx_connection.h
+++ b/usr.sbin/nginx/src/core/ngx_connection.h
@@ -80,6 +80,10 @@ struct ngx_listening_s {
int setfib;
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ int fastopen;
+#endif
+
};
@@ -108,6 +112,7 @@ typedef enum {
#define NGX_LOWLEVEL_BUFFERED 0x0f
#define NGX_SSL_BUFFERED 0x01
+#define NGX_SPDY_BUFFERED 0x02
struct ngx_connection_s {
@@ -134,11 +139,14 @@ struct ngx_connection_s {
socklen_t socklen;
ngx_str_t addr_text;
+ ngx_str_t proxy_protocol_addr;
+
#if (NGX_SSL)
ngx_ssl_connection_t *ssl;
#endif
struct sockaddr *local_sockaddr;
+ socklen_t local_socklen;
ngx_buf_t *buffer;
@@ -166,12 +174,15 @@ struct ngx_connection_s {
unsigned tcp_nodelay:2; /* ngx_connection_tcp_nodelay_e */
unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */
+ unsigned need_last_buf:1;
+
#if (NGX_HAVE_IOCP)
unsigned accept_context_updated:1;
#endif
#if (NGX_HAVE_AIO_SENDFILE)
unsigned aio_sendfile:1;
+ unsigned busy_count:2;
ngx_buf_t *busy_sendfile;
#endif
diff --git a/usr.sbin/nginx/src/core/ngx_core.h b/usr.sbin/nginx/src/core/ngx_core.h
index dfcf2d56cf8..c479a59546d 100644
--- a/usr.sbin/nginx/src/core/ngx_core.h
+++ b/usr.sbin/nginx/src/core/ngx_core.h
@@ -77,6 +77,8 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_open_file_cache.h>
#include <ngx_os.h>
#include <ngx_connection.h>
+#include <ngx_syslog.h>
+#include <ngx_proxy_protocol.h>
#define LF (u_char) 10
diff --git a/usr.sbin/nginx/src/core/ngx_cycle.c b/usr.sbin/nginx/src/core/ngx_cycle.c
index 0c354c65665..aa42406ffe3 100644
--- a/usr.sbin/nginx/src/core/ngx_cycle.c
+++ b/usr.sbin/nginx/src/core/ngx_cycle.c
@@ -11,7 +11,6 @@
static void ngx_destroy_cycle_pools(ngx_conf_t *conf);
-static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2);
static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle,
ngx_shm_zone_t *shm_zone);
static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
@@ -36,8 +35,6 @@ ngx_tls_key_t ngx_core_tls_key;
static ngx_connection_t dumb;
/* STUB */
-static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
-
ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
@@ -84,13 +81,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
cycle->pool = pool;
cycle->log = log;
- cycle->new_log.log_level = NGX_LOG_ERR;
-#if (NGX_ENABLE_SYSLOG)
- cycle->new_log.facility = SYSLOG_FACILITY;
- cycle->new_log.facility = ERR_SYSLOG_PRIORITY;
- cycle->new_log.syslog_on = 0;
- cycle->new_log.syslog_set = 0;
-#endif
cycle->old_cycle = old_cycle;
cycle->conf_prefix.len = old_cycle->conf_prefix.len;
@@ -345,11 +335,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
- if (cycle->new_log.file == NULL) {
- cycle->new_log.file = ngx_conf_open_file(cycle, &error_log);
- if (cycle->new_log.file == NULL) {
- goto failed;
- }
+ if (ngx_log_open_default(cycle) != NGX_OK) {
+ goto failed;
}
/* open the new files */
@@ -506,13 +493,15 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
continue;
}
- if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK)
+ if (ngx_cmp_sockaddr(nls[n].sockaddr, nls[n].socklen,
+ ls[i].sockaddr, ls[i].socklen, 1)
+ == NGX_OK)
{
nls[n].fd = ls[i].fd;
nls[n].previous = &ls[i];
ls[i].remain = 1;
- if (ls[n].backlog != nls[i].backlog) {
+ if (ls[i].backlog != nls[n].backlog) {
nls[n].listen = 1;
}
@@ -543,7 +532,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
- if (ls[n].deferred_accept && !nls[n].deferred_accept) {
+ if (ls[i].deferred_accept && !nls[n].deferred_accept) {
nls[n].delete_deferred = 1;
} else if (ls[i].deferred_accept != nls[n].deferred_accept)
@@ -555,8 +544,18 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
}
}
- if (nls[n].fd == -1) {
+ if (nls[n].fd == (ngx_socket_t) -1) {
nls[n].open = 1;
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+ if (nls[n].accept_filter) {
+ nls[n].add_deferred = 1;
+ }
+#endif
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+ if (nls[n].deferred_accept) {
+ nls[n].add_deferred = 1;
+ }
+#endif
}
}
@@ -588,12 +587,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
/* commit the new cycle configuration */
- if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) {
-
- if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
- ngx_set_stderr_n " failed");
- }
+ if (!ngx_use_stderr) {
+ (void) ngx_log_redirect_stderr(cycle);
}
pool->log = cycle->log;
@@ -665,7 +660,7 @@ old_shm_zone_done:
ls = old_cycle->listening.elts;
for (i = 0; i < old_cycle->listening.nelts; i++) {
- if (ls[i].remain || ls[i].fd == -1) {
+ if (ls[i].remain || ls[i].fd == (ngx_socket_t) -1) {
continue;
}
@@ -829,7 +824,7 @@ failed:
ls = cycle->listening.elts;
for (i = 0; i < cycle->listening.nelts; i++) {
- if (ls[i].fd == -1 || !ls[i].open) {
+ if (ls[i].fd == (ngx_socket_t) -1 || !ls[i].open) {
continue;
}
@@ -855,74 +850,6 @@ 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;
-#if (NGX_HAVE_INET6)
- struct sockaddr_in6 *sin61, *sin62;
-#endif
-#if (NGX_HAVE_UNIX_DOMAIN)
- struct sockaddr_un *saun1, *saun2;
-#endif
-
- if (sa1->sa_family != sa2->sa_family) {
- return NGX_DECLINED;
- }
-
- switch (sa1->sa_family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin61 = (struct sockaddr_in6 *) sa1;
- sin62 = (struct sockaddr_in6 *) sa2;
-
- if (sin61->sin6_port != sin62->sin6_port) {
- return NGX_DECLINED;
- }
-
- if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
- return NGX_DECLINED;
- }
-
- break;
-#endif
-
-#if (NGX_HAVE_UNIX_DOMAIN)
- case AF_UNIX:
- saun1 = (struct sockaddr_un *) sa1;
- saun2 = (struct sockaddr_un *) sa2;
-
- if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
- sizeof(saun1->sun_path))
- != 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;
-}
-
-
-static ngx_int_t
ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)
{
u_char *file;
@@ -1238,16 +1165,7 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
file[i].fd = fd;
}
-#if !(NGX_WIN32)
-
- if (cycle->log->file->fd != STDERR_FILENO) {
- if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
- ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
- "dup2(STDERR) failed");
- }
- }
-
-#endif
+ (void) ngx_log_redirect_stderr(cycle);
}
diff --git a/usr.sbin/nginx/src/core/ngx_cycle.h b/usr.sbin/nginx/src/core/ngx_cycle.h
index 2e4bc4ba278..21bf5ca3f25 100644
--- a/usr.sbin/nginx/src/core/ngx_cycle.h
+++ b/usr.sbin/nginx/src/core/ngx_cycle.h
@@ -41,6 +41,8 @@ struct ngx_cycle_s {
ngx_log_t *log;
ngx_log_t new_log;
+ ngx_uint_t log_use_stderr; /* unsigned log_use_stderr:1; */
+
ngx_connection_t **files;
ngx_connection_t *free_connections;
ngx_uint_t free_connection_n;
diff --git a/usr.sbin/nginx/src/core/ngx_file.c b/usr.sbin/nginx/src/core/ngx_file.c
index ce09bb6021f..4bbdc940211 100644
--- a/usr.sbin/nginx/src/core/ngx_file.c
+++ b/usr.sbin/nginx/src/core/ngx_file.c
@@ -9,11 +9,102 @@
#include <ngx_core.h>
+static ngx_int_t ngx_test_full_name(ngx_str_t *name);
+
+
static ngx_atomic_t temp_number = 0;
ngx_atomic_t *ngx_temp_number = &temp_number;
ngx_atomic_int_t ngx_random_number = 123456;
+ngx_int_t
+ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix, ngx_str_t *name)
+{
+ size_t len;
+ u_char *p, *n;
+ ngx_int_t rc;
+
+ rc = ngx_test_full_name(name);
+
+ if (rc == NGX_OK) {
+ return rc;
+ }
+
+ len = prefix->len;
+
+#if (NGX_WIN32)
+
+ if (rc == 2) {
+ len = rc;
+ }
+
+#endif
+
+ n = ngx_pnalloc(pool, len + name->len + 1);
+ if (n == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = ngx_cpymem(n, prefix->data, len);
+ ngx_cpystrn(p, name->data, name->len + 1);
+
+ name->len += len;
+ name->data = n;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_test_full_name(ngx_str_t *name)
+{
+#if (NGX_WIN32)
+ u_char c0, c1;
+
+ c0 = name->data[0];
+
+ if (name->len < 2) {
+ if (c0 == '/') {
+ return 2;
+ }
+
+ return NGX_DECLINED;
+ }
+
+ c1 = name->data[1];
+
+ if (c1 == ':') {
+ c0 |= 0x20;
+
+ if ((c0 >= 'a' && c0 <= 'z')) {
+ return NGX_OK;
+ }
+
+ return NGX_DECLINED;
+ }
+
+ if (c1 == '/') {
+ return NGX_OK;
+ }
+
+ if (c0 == '/') {
+ return 2;
+ }
+
+ return NGX_DECLINED;
+
+#else
+
+ if (name->data[0] == '/') {
+ return NGX_OK;
+ }
+
+ return NGX_DECLINED;
+
+#endif
+}
+
+
ssize_t
ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain)
{
@@ -268,9 +359,6 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NULL;
}
- path->len = 0;
- path->manager = NULL;
- path->loader = NULL;
path->conf_file = cf->conf_file->file.name.data;
path->line = cf->conf_file->line;
@@ -311,7 +399,7 @@ ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev,
return NGX_CONF_OK;
}
- *path = ngx_palloc(cf->pool, sizeof(ngx_path_t));
+ *path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t));
if (*path == NULL) {
return NGX_CONF_ERROR;
}
@@ -330,10 +418,6 @@ ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev,
+ init->level[1] + (init->level[1] ? 1 : 0)
+ init->level[2] + (init->level[2] ? 1 : 0);
- (*path)->manager = NULL;
- (*path)->loader = NULL;
- (*path)->conf_file = NULL;
-
if (ngx_add_path(cf, path) != NGX_OK) {
return NGX_CONF_ERROR;
}
@@ -417,6 +501,14 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot)
if (p[i]->name.len == path->name.len
&& ngx_strcmp(p[i]->name.data, path->name.data) == 0)
{
+ if (p[i]->data != path->data) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the same path name \"%V\" "
+ "used in %s:%ui and",
+ &p[i]->name, p[i]->conf_file, p[i]->line);
+ return NGX_ERROR;
+ }
+
for (n = 0; n < 3; n++) {
if (p[i]->level[n] != path->level[n]) {
if (path->conf_file == NULL) {
diff --git a/usr.sbin/nginx/src/core/ngx_file.h b/usr.sbin/nginx/src/core/ngx_file.h
index 18abf142316..3ea6c28c863 100644
--- a/usr.sbin/nginx/src/core/ngx_file.h
+++ b/usr.sbin/nginx/src/core/ngx_file.h
@@ -122,6 +122,9 @@ struct ngx_tree_ctx_s {
};
+ngx_int_t ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix,
+ ngx_str_t *name);
+
ssize_t ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain);
ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path,
ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean,
diff --git a/usr.sbin/nginx/src/core/ngx_hash.c b/usr.sbin/nginx/src/core/ngx_hash.c
index b532945027c..c7bfed70979 100644
--- a/usr.sbin/nginx/src/core/ngx_hash.c
+++ b/usr.sbin/nginx/src/core/ngx_hash.c
@@ -282,7 +282,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
start = hinit->max_size - 1000;
}
- for (size = start; size < hinit->max_size; size++) {
+ for (size = start; size <= hinit->max_size; size++) {
ngx_memzero(test, size * sizeof(u_short));
@@ -312,15 +312,12 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
continue;
}
- ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
- "could not build the %s, you should increase "
- "either %s_max_size: %i or %s_bucket_size: %i",
+ ngx_log_error(NGX_LOG_WARN, hinit->pool->log, 0,
+ "could not build optimal %s, you should increase "
+ "either %s_max_size: %i or %s_bucket_size: %i; "
+ "ignoring %s_bucket_size",
hinit->name, hinit->name, hinit->max_size,
- hinit->name, hinit->bucket_size);
-
- ngx_free(test);
-
- return NGX_ERROR;
+ hinit->name, hinit->bucket_size, hinit->name);
found:
diff --git a/usr.sbin/nginx/src/core/ngx_inet.c b/usr.sbin/nginx/src/core/ngx_inet.c
index 7757ab7d905..26c5bc4b0bb 100644
--- a/usr.sbin/nginx/src/core/ngx_inet.c
+++ b/usr.sbin/nginx/src/core/ngx_inet.c
@@ -174,7 +174,8 @@ ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
size_t
-ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
+ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, u_char *text, size_t len,
+ ngx_uint_t port)
{
u_char *p;
struct sockaddr_in *sin;
@@ -230,9 +231,18 @@ ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
case AF_UNIX:
saun = (struct sockaddr_un *) sa;
+ /* on Linux sockaddr might not include sun_path at all */
+
+ if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)) {
+ p = ngx_snprintf(text, len, "unix:%Z");
+
+ } else {
+ p = ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path);
+ }
+
/* we do not include trailing zero in address length */
- return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
+ return (p - text - 1);
#endif
@@ -953,6 +963,9 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
ngx_memzero(&hints, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags = AI_ADDRCONFIG;
+#endif
if (getaddrinfo((char *) host, NULL, &hints, &res) != 0) {
u->err = "host not found";
@@ -1020,7 +1033,7 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
goto failed;
}
- len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
+ len = ngx_sock_ntop((struct sockaddr *) sin, rp->ai_addrlen, p, len, 1);
u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
@@ -1053,7 +1066,8 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
goto failed;
}
- len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, 1);
+ len = ngx_sock_ntop((struct sockaddr *) sin6, rp->ai_addrlen, p,
+ len, 1);
u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
@@ -1138,7 +1152,8 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
return NGX_ERROR;
}
- len = ngx_sock_ntop((struct sockaddr *) sin, p, len, 1);
+ len = ngx_sock_ntop((struct sockaddr *) sin,
+ sizeof(struct sockaddr_in), p, len, 1);
u->addrs[i].name.len = len;
u->addrs[i].name.data = p;
@@ -1181,3 +1196,76 @@ ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
}
#endif /* NGX_HAVE_GETADDRINFO && NGX_HAVE_INET6 */
+
+
+ngx_int_t
+ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
+ struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port)
+{
+ struct sockaddr_in *sin1, *sin2;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin61, *sin62;
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ struct sockaddr_un *saun1, *saun2;
+#endif
+
+ if (sa1->sa_family != sa2->sa_family) {
+ return NGX_DECLINED;
+ }
+
+ switch (sa1->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+
+ sin61 = (struct sockaddr_in6 *) sa1;
+ sin62 = (struct sockaddr_in6 *) sa2;
+
+ if (cmp_port && sin61->sin6_port != sin62->sin6_port) {
+ return NGX_DECLINED;
+ }
+
+ if (ngx_memcmp(&sin61->sin6_addr, &sin62->sin6_addr, 16) != 0) {
+ return NGX_DECLINED;
+ }
+
+ break;
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+
+ /* TODO length */
+
+ saun1 = (struct sockaddr_un *) sa1;
+ saun2 = (struct sockaddr_un *) sa2;
+
+ if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
+ sizeof(saun1->sun_path))
+ != 0)
+ {
+ return NGX_DECLINED;
+ }
+
+ break;
+#endif
+
+ default: /* AF_INET */
+
+ sin1 = (struct sockaddr_in *) sa1;
+ sin2 = (struct sockaddr_in *) sa2;
+
+ if (cmp_port && 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/usr.sbin/nginx/src/core/ngx_inet.h b/usr.sbin/nginx/src/core/ngx_inet.h
index 6a5a3687d8c..05557509d65 100644
--- a/usr.sbin/nginx/src/core/ngx_inet.h
+++ b/usr.sbin/nginx/src/core/ngx_inet.h
@@ -107,14 +107,16 @@ in_addr_t ngx_inet_addr(u_char *text, size_t len);
ngx_int_t ngx_inet6_addr(u_char *p, size_t len, u_char *addr);
size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
#endif
-size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
- ngx_uint_t port);
+size_t ngx_sock_ntop(struct sockaddr *sa, socklen_t socklen, 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, ngx_cidr_t *cidr);
ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
size_t len);
ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
+ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, socklen_t slen1,
+ struct sockaddr *sa2, socklen_t slen2, ngx_uint_t cmp_port);
#endif /* _NGX_INET_H_INCLUDED_ */
diff --git a/usr.sbin/nginx/src/core/ngx_list.c b/usr.sbin/nginx/src/core/ngx_list.c
index 89ea8235275..d0eb15930a8 100644
--- a/usr.sbin/nginx/src/core/ngx_list.c
+++ b/usr.sbin/nginx/src/core/ngx_list.c
@@ -19,18 +19,10 @@ ngx_list_create(ngx_pool_t *pool, ngx_uint_t n, size_t size)
return NULL;
}
- list->part.elts = ngx_palloc(pool, n * size);
- if (list->part.elts == NULL) {
+ if (ngx_list_init(list, pool, n, size) != NGX_OK) {
return NULL;
}
- list->part.nelts = 0;
- list->part.next = NULL;
- list->last = &list->part;
- list->size = size;
- list->nalloc = n;
- list->pool = pool;
-
return list;
}
diff --git a/usr.sbin/nginx/src/core/ngx_log.c b/usr.sbin/nginx/src/core/ngx_log.c
index ddc2bbf6847..375d52f65d4 100644
--- a/usr.sbin/nginx/src/core/ngx_log.c
+++ b/usr.sbin/nginx/src/core/ngx_log.c
@@ -10,15 +10,8 @@
static char *ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-#if (NGX_ENABLE_SYSLOG)
-static char *ngx_set_syslog(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-void log_exit(ngx_cycle_t *cycle);
-
-typedef struct{
- ngx_str_t name;
- ngx_int_t macro;
-} ngx_string_to_macro_t;
-#endif
+static char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
+static void ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log);
static ngx_command_t ngx_errlog_commands[] = {
@@ -30,15 +23,6 @@ static ngx_command_t ngx_errlog_commands[] = {
0,
NULL},
-#if (NGX_ENABLE_SYSLOG)
- {ngx_string("syslog"),
- NGX_MAIN_CONF|NGX_CONF_TAKE12,
- ngx_set_syslog,
- 0,
- 0,
- NULL},
-#endif
-
ngx_null_command
};
@@ -61,11 +45,7 @@ ngx_module_t ngx_errlog_module = {
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
-#if (NGX_ENABLE_SYSLOG)
- log_exit, /* exit master */
-#else
- NULL,
-#endif
+ NULL, /* exit master */
NGX_MODULE_V1_PADDING
};
@@ -74,48 +54,6 @@ static ngx_log_t ngx_log;
static ngx_open_file_t ngx_log_file;
ngx_uint_t ngx_use_stderr = 1;
-#if (NGX_ENABLE_SYSLOG)
-static ngx_string_to_macro_t ngx_syslog_facilities[] = {
- {ngx_string("auth"), LOG_AUTH},
-#if !(NGX_SOLARIS)
- {ngx_string("authpriv"), LOG_AUTHPRIV},
-#endif
- {ngx_string("cron"), LOG_CRON},
- {ngx_string("daemon"), LOG_DAEMON},
-#if !(NGX_SOLARIS)
- {ngx_string("ftp"), LOG_FTP},
-#endif
- {ngx_string("kern"), LOG_KERN},
- {ngx_string("local0"), LOG_LOCAL0},
- {ngx_string("local1"), LOG_LOCAL1},
- {ngx_string("local2"), LOG_LOCAL2},
- {ngx_string("local3"), LOG_LOCAL3},
- {ngx_string("local4"), LOG_LOCAL4},
- {ngx_string("local5"), LOG_LOCAL5},
- {ngx_string("local6"), LOG_LOCAL6},
- {ngx_string("local7"), LOG_LOCAL7},
- {ngx_string("lpr"), LOG_LPR},
- {ngx_string("mail"), LOG_MAIL},
- {ngx_string("news"), LOG_NEWS},
- {ngx_string("syslog"), LOG_SYSLOG},
- {ngx_string("user"), LOG_USER},
- {ngx_string("uucp"), LOG_UUCP},
- { ngx_null_string, 0}
-};
-
-static ngx_string_to_macro_t ngx_syslog_priorities[] = {
- {ngx_string("emerg"), LOG_EMERG},
- {ngx_string("alert"), LOG_ALERT},
- {ngx_string("crit"), LOG_CRIT},
- {ngx_string("error"), LOG_ERR},
- {ngx_string("err"), LOG_ERR},
- {ngx_string("warn"), LOG_WARNING},
- {ngx_string("notice"),LOG_NOTICE},
- {ngx_string("info"), LOG_INFO},
- {ngx_string("debug"), LOG_DEBUG},
- { ngx_null_string, 0}
-};
-#endif
static ngx_str_t err_levels[] = {
ngx_null_string,
@@ -150,19 +88,11 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
- va_list args;
-#endif
- u_char *p, *last, *msg;
-#if (NGX_ENABLE_SYSLOG)
- u_char *errstr_syslog;
-#endif
- u_char errstr[NGX_MAX_ERROR_STR];
-
-#if !(NGX_ENABLE_SYSLOG)
- if (log->file->fd == NGX_INVALID_FILE) {
- return;
- }
+ va_list args;
#endif
+ u_char *p, *last, *msg;
+ u_char errstr[NGX_MAX_ERROR_STR];
+ ngx_uint_t wrote_stderr, debug_connection;
last = errstr + NGX_MAX_ERROR_STR;
@@ -171,10 +101,6 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
p = errstr + ngx_cached_err_log_time.len;
-#if (NGX_ENABLE_SYSLOG)
- errstr_syslog = p;
-#endif
-
p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);
/* pid#tid */
@@ -213,27 +139,33 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
ngx_linefeed(p);
-#if (NGX_ENABLE_SYSLOG)
- if (log->file != NULL && log->file->name.len != 0) {
- (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
- }
+ wrote_stderr = 0;
+ debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;
+
+ while (log) {
+
+ if (log->log_level < level && !debug_connection) {
+ break;
+ }
+
+ if (log->writer) {
+ log->writer(log, level, errstr, p - errstr);
+ log = log->next;
+ continue;
+ }
+
+ (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
- /* Don't send the debug level info to syslog */
- if (log->syslog_on && level < NGX_LOG_DEBUG) {
- /* write to syslog */
- syslog(log->priority, "%.*s", (int)(p - errstr_syslog), errstr_syslog);
+ if (log->file->fd == ngx_stderr) {
+ wrote_stderr = 1;
+ }
+
+ log = log->next;
}
-#else
- (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
-#endif
if (!ngx_use_stderr
|| level > NGX_LOG_WARN
-#if (NGX_ENABLE_SYSLOG)
- || (log->file != NULL && log->file->fd == ngx_stderr))
-#else
- || log->file->fd == ngx_stderr)
-#endif
+ || wrote_stderr)
{
return;
}
@@ -437,75 +369,93 @@ ngx_log_init(u_char *prefix)
}
-ngx_log_t *
-ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name)
+ngx_int_t
+ngx_log_open_default(ngx_cycle_t *cycle)
{
- ngx_log_t *log;
+ ngx_log_t *log;
+ static ngx_str_t error_log = ngx_string(NGX_ERROR_LOG_PATH);
+
+ if (ngx_log_get_file_log(&cycle->new_log) != NULL) {
+ return NGX_OK;
+ }
+
+ if (cycle->new_log.log_level != 0) {
+ /* there are some error logs, but no files */
- log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t));
- if (log == NULL) {
- return NULL;
+ log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t));
+ if (log == NULL) {
+ return NGX_ERROR;
+ }
+
+ log->log_level = NGX_LOG_ERR;
+ ngx_log_insert(&cycle->new_log, log);
+
+ } else {
+ /* no error logs at all */
+ log = &cycle->new_log;
+ log->log_level = NGX_LOG_ERR;
}
- log->file = ngx_conf_open_file(cycle, name);
+ log->file = ngx_conf_open_file(cycle, &error_log);
if (log->file == NULL) {
- return NULL;
+ return NGX_ERROR;
}
- return log;
+ return NGX_OK;
}
-#if (NGX_ENABLE_SYSLOG)
ngx_int_t
-ngx_log_get_priority(ngx_conf_t *cf, ngx_str_t *priority)
+ngx_log_redirect_stderr(ngx_cycle_t *cycle)
{
- ngx_int_t p = 0;
- ngx_uint_t n, match = 0;
-
- for (n = 0; ngx_syslog_priorities[n].name.len != 0; n++) {
- if (ngx_strncmp(priority->data, ngx_syslog_priorities[n].name.data,
- ngx_syslog_priorities[n].name.len) == 0) {
- p = ngx_syslog_priorities[n].macro;
- match = 1;
- }
+ ngx_fd_t fd;
+
+ if (cycle->log_use_stderr) {
+ return NGX_OK;
}
- if (!match) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid syslog priority \"%V\"", priority);
- return -1;
+ /* file log always exists when we are called */
+ fd = ngx_log_get_file_log(cycle->log)->file->fd;
+
+ if (fd != ngx_stderr) {
+ if (ngx_set_stderr(fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+ ngx_set_stderr_n " failed");
+
+ return NGX_ERROR;
+ }
}
- return p;
+ return NGX_OK;
}
-char *
-ngx_log_set_priority(ngx_conf_t *cf, ngx_str_t *priority, ngx_log_t *log)
+ngx_log_t *
+ngx_log_get_file_log(ngx_log_t *head)
{
- log->priority = ERR_SYSLOG_PRIORITY;
-
- if (priority->len == 0) {
- return NGX_CONF_OK;
- }
+ ngx_log_t *log;
- log->priority = ngx_log_get_priority(cf, priority);
- if (log->priority == (-1)) {
- return NGX_CONF_ERROR;
+ for (log = head; log; log = log->next) {
+ if (log->file != NULL) {
+ return log;
+ }
}
- return NGX_CONF_OK;
+ return NULL;
}
-#endif
-char *
+static char *
ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log)
{
ngx_uint_t i, n, d, found;
ngx_str_t *value;
+ if (cf->args->nelts == 2) {
+ log->log_level = NGX_LOG_ERR;
+ return NGX_CONF_OK;
+ }
+
value = cf->args->elts;
for (i = 2; i < cf->args->nelts; i++) {
@@ -561,136 +511,109 @@ ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log)
static char *
ngx_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
- ngx_str_t *value, name;
-#if (NGX_ENABLE_SYSLOG)
- u_char *off = NULL;
- ngx_str_t priority;
+ ngx_log_t *dummy;
- ngx_str_null(&name);
- ngx_str_null(&priority);
-#endif
+ dummy = &cf->cycle->new_log;
- if (cf->cycle->new_log.file) {
- return "is duplicate";
- }
+ return ngx_log_set_log(cf, &dummy);
+}
- value = cf->args->elts;
-#if (NGX_ENABLE_SYSLOG)
- if (ngx_strncmp(value[1].data, "syslog", sizeof("syslog") - 1) == 0) {
- if (!cf->cycle->new_log.syslog_set) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "You must set the syslog directive and enable it first.");
+char *
+ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head)
+{
+ ngx_log_t *new_log;
+ ngx_str_t *value, name;
+ ngx_syslog_peer_t *peer;
+
+ if (*head != NULL && (*head)->log_level == 0) {
+ new_log = *head;
+
+ } else {
+
+ new_log = ngx_pcalloc(cf->pool, sizeof(ngx_log_t));
+ if (new_log == NULL) {
return NGX_CONF_ERROR;
}
- cf->cycle->new_log.syslog_on = 1;
+ if (*head == NULL) {
+ *head = new_log;
+ }
+ }
- if (value[1].data[sizeof("syslog") - 1] == ':') {
- priority.len = value[1].len - sizeof("syslog");
- priority.data = value[1].data + sizeof("syslog");
+ value = cf->args->elts;
- off = (u_char *)ngx_strchr(priority.data, (int) '|');
- if (off != NULL) {
- priority.len = off - priority.data;
+ if (ngx_strcmp(value[1].data, "stderr") == 0) {
+ ngx_str_null(&name);
+ cf->cycle->log_use_stderr = 1;
- off++;
- name.len = value[1].data + value[1].len - off;
- name.data = off;
- }
+ new_log->file = ngx_conf_open_file(cf->cycle, &name);
+ if (new_log->file == NULL) {
+ return NGX_CONF_ERROR;
}
- else {
- if (value[1].len > sizeof("syslog")) {
- name.len = value[1].len - sizeof("syslog");
- name.data = value[1].data + sizeof("syslog");
- }
+
+
+ } else if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) {
+ peer = ngx_pcalloc(cf->pool, sizeof(ngx_syslog_peer_t));
+ if (peer == NULL) {
+ return NGX_CONF_ERROR;
}
- if (ngx_log_set_priority(cf, &priority, &cf->cycle->new_log) == NGX_CONF_ERROR) {
+ if (ngx_syslog_process_conf(cf, peer) != NGX_CONF_OK) {
return NGX_CONF_ERROR;
}
- }
- else if (ngx_strcmp(value[1].data, "stderr") == 0) {
-#else
- if (ngx_strcmp(value[1].data, "stderr") == 0) {
-#endif
- ngx_str_null(&name);
+
+ new_log->writer = ngx_syslog_writer;
+ new_log->wdata = peer;
} else {
- name = value[1];
+ new_log->file = ngx_conf_open_file(cf->cycle, &value[1]);
+ if (new_log->file == NULL) {
+ return NGX_CONF_ERROR;
+ }
}
- cf->cycle->new_log.file = ngx_conf_open_file(cf->cycle, &name);
- if (cf->cycle->new_log.file == NULL) {
- return NULL;
+ if (ngx_log_set_levels(cf, new_log) != NGX_CONF_OK) {
+ return NGX_CONF_ERROR;
}
- if (cf->args->nelts == 2) {
- cf->cycle->new_log.log_level = NGX_LOG_ERR;
- return NGX_CONF_OK;
+ if (*head != new_log) {
+ ngx_log_insert(*head, new_log);
}
- cf->cycle->new_log.log_level = 0;
-
- return ngx_log_set_levels(cf, &cf->cycle->new_log);
+ return NGX_CONF_OK;
}
-#if (NGX_ENABLE_SYSLOG)
-
-#define SYSLOG_IDENT_NAME "nginx"
-
-static char *
-ngx_set_syslog(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+static void
+ngx_log_insert(ngx_log_t *log, ngx_log_t *new_log)
{
- char *program;
- ngx_str_t *value;
- ngx_int_t facility = SYSLOG_FACILITY, match = 0;
- ngx_uint_t n;
+ ngx_log_t tmp;
- value = cf->args->elts;
+ if (new_log->log_level > log->log_level) {
- if (cf->cycle->new_log.syslog_set) {
- return "is duplicate";
- }
+ /*
+ * list head address is permanent, insert new log after
+ * head and swap its contents with head
+ */
- cf->cycle->new_log.syslog_set = 1;
+ tmp = *log;
+ *log = *new_log;
+ *new_log = tmp;
- for (n = 0; ngx_syslog_facilities[n].name.len != 0; n++) {
- if (ngx_strncmp(value[1].data, ngx_syslog_facilities[n].name.data,
- ngx_syslog_facilities[n].name.len) == 0) {
- facility = ngx_syslog_facilities[n].macro;
- match = 1;
- break;
- }
+ log->next = new_log;
+ return;
}
- if (match) {
- cf->cycle->new_log.facility = facility;
- cf->cycle->new_log.priority = ERR_SYSLOG_PRIORITY;
- }
- else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid syslog facility \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
+ while (log->next) {
+ if (new_log->log_level > log->next->log_level) {
+ new_log->next = log->next;
+ log->next = new_log;
+ return;
+ }
- program = SYSLOG_IDENT_NAME;
- if (cf->args->nelts > 2) {
- program = (char *) value[2].data;
+ log = log->next;
}
- openlog(program, LOG_ODELAY, facility);
-
- return NGX_CONF_OK;
+ log->next = new_log;
}
-
-
-void log_exit(ngx_cycle_t *cycle)
-{
- if (cycle->new_log.syslog_set) {
- closelog();
- }
-}
-#endif
-
diff --git a/usr.sbin/nginx/src/core/ngx_log.h b/usr.sbin/nginx/src/core/ngx_log.h
index 5e7fdbf4b4e..c1a52c44f0b 100644
--- a/usr.sbin/nginx/src/core/ngx_log.h
+++ b/usr.sbin/nginx/src/core/ngx_log.h
@@ -12,13 +12,6 @@
#include <ngx_config.h>
#include <ngx_core.h>
-#if (NGX_ENABLE_SYSLOG)
-#include <syslog.h>
-
-#define SYSLOG_FACILITY LOG_LOCAL5
-#define ERR_SYSLOG_PRIORITY LOG_ERR
-#endif
-
#define NGX_LOG_STDERR 0
#define NGX_LOG_EMERG 1
@@ -50,6 +43,8 @@
typedef u_char *(*ngx_log_handler_pt) (ngx_log_t *log, u_char *buf, size_t len);
+typedef void (*ngx_log_writer_pt) (ngx_log_t *log, ngx_uint_t level,
+ u_char *buf, size_t len);
struct ngx_log_s {
@@ -61,6 +56,9 @@ struct ngx_log_s {
ngx_log_handler_pt handler;
void *data;
+ ngx_log_writer_pt writer;
+ void *wdata;
+
/*
* we declare "action" as "char *" because the actions are usually
* the static strings and in the "u_char *" case we have to override
@@ -69,12 +67,7 @@ struct ngx_log_s {
char *action;
-#if (NGX_ENABLE_SYSLOG)
- ngx_int_t priority;
- ngx_int_t facility;
- unsigned syslog_on:1; /* unsigned :1 syslog_on */
- unsigned syslog_set:1; /*unsigned :1 syslog_set */
-#endif
+ ngx_log_t *next;
};
@@ -234,15 +227,13 @@ void ngx_cdecl ngx_log_debug_core(ngx_log_t *log, ngx_err_t err,
/*********************************/
ngx_log_t *ngx_log_init(u_char *prefix);
-ngx_log_t *ngx_log_create(ngx_cycle_t *cycle, ngx_str_t *name);
-#if (NGX_ENABLE_SYSLOG)
-ngx_int_t ngx_log_get_priority(ngx_conf_t *cf, ngx_str_t *priority);
-char * ngx_log_set_priority(ngx_conf_t *cf, ngx_str_t *priority, ngx_log_t *log);
-#endif
-char *ngx_log_set_levels(ngx_conf_t *cf, ngx_log_t *log);
void ngx_cdecl ngx_log_abort(ngx_err_t err, const char *fmt, ...);
void ngx_cdecl ngx_log_stderr(ngx_err_t err, const char *fmt, ...);
u_char *ngx_log_errno(u_char *buf, u_char *last, ngx_err_t err);
+ngx_int_t ngx_log_open_default(ngx_cycle_t *cycle);
+ngx_int_t ngx_log_redirect_stderr(ngx_cycle_t *cycle);
+ngx_log_t *ngx_log_get_file_log(ngx_log_t *head);
+char *ngx_log_set_log(ngx_conf_t *cf, ngx_log_t **head);
/*
diff --git a/usr.sbin/nginx/src/core/ngx_open_file_cache.c b/usr.sbin/nginx/src/core/ngx_open_file_cache.c
index c44ac96b8b7..4df2134b2bd 100644
--- a/usr.sbin/nginx/src/core/ngx_open_file_cache.c
+++ b/usr.sbin/nginx/src/core/ngx_open_file_cache.c
@@ -25,6 +25,10 @@ static void ngx_open_file_cache_cleanup(void *data);
#if (NGX_HAVE_OPENAT)
static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log);
+#if (NGX_HAVE_O_PATH)
+static ngx_int_t ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi,
+ ngx_log_t *log);
+#endif
#endif
static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
@@ -124,7 +128,7 @@ ngx_open_file_cache_cleanup(void *data)
if (cache->current) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
- "%d items still leave in open file cache",
+ "%ui items still leave in open file cache",
cache->current);
}
@@ -517,10 +521,17 @@ ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
goto failed;
}
+#if (NGX_HAVE_O_PATH)
+ if (ngx_file_o_path_info(fd, &fi, log) == NGX_ERROR) {
+ err = ngx_errno;
+ goto failed;
+ }
+#else
if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
err = ngx_errno;
goto failed;
}
+#endif
if (fi.st_uid != atfi.st_uid) {
err = NGX_ELOOP;
@@ -541,8 +552,63 @@ failed:
return NGX_INVALID_FILE;
}
+
+#if (NGX_HAVE_O_PATH)
+
+static ngx_int_t
+ngx_file_o_path_info(ngx_fd_t fd, ngx_file_info_t *fi, ngx_log_t *log)
+{
+ static ngx_uint_t use_fstat = 1;
+
+ /*
+ * In Linux 2.6.39 the O_PATH flag was introduced that allows to obtain
+ * a descriptor without actually opening file or directory. It requires
+ * less permissions for path components, but till Linux 3.6 fstat() returns
+ * EBADF on such descriptors, and fstatat() with the AT_EMPTY_PATH flag
+ * should be used instead.
+ *
+ * Three scenarios are handled in this function:
+ *
+ * 1) The kernel is newer than 3.6 or fstat() with O_PATH support was
+ * backported by vendor. Then fstat() is used.
+ *
+ * 2) The kernel is newer than 2.6.39 but older than 3.6. In this case
+ * the first call of fstat() returns EBADF and we fallback to fstatat()
+ * with AT_EMPTY_PATH which was introduced at the same time as O_PATH.
+ *
+ * 3) The kernel is older than 2.6.39 but nginx was build with O_PATH
+ * support. Since descriptors are opened with O_PATH|O_RDONLY flags
+ * and O_PATH is ignored by the kernel then the O_RDONLY flag is
+ * actually used. In this case fstat() just works.
+ */
+
+ if (use_fstat) {
+ if (ngx_fd_info(fd, fi) != NGX_FILE_ERROR) {
+ return NGX_OK;
+ }
+
+ if (ngx_errno != NGX_EBADF) {
+ return NGX_ERROR;
+ }
+
+ ngx_log_error(NGX_LOG_NOTICE, log, 0,
+ "fstat(O_PATH) failed with EBADF, "
+ "switching to fstatat(AT_EMPTY_PATH)");
+
+ use_fstat = 0;
+ }
+
+ if (ngx_file_at_info(fd, "", fi, AT_EMPTY_PATH) != NGX_FILE_ERROR) {
+ return NGX_OK;
+ }
+
+ return NGX_ERROR;
+}
+
#endif
+#endif /* NGX_HAVE_OPENAT */
+
static ngx_fd_t
ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
diff --git a/usr.sbin/nginx/src/core/ngx_palloc.c b/usr.sbin/nginx/src/core/ngx_palloc.c
index efbc24452bd..1f70f9eee29 100644
--- a/usr.sbin/nginx/src/core/ngx_palloc.c
+++ b/usr.sbin/nginx/src/core/ngx_palloc.c
@@ -105,11 +105,14 @@ ngx_reset_pool(ngx_pool_t *pool)
}
}
- pool->large = NULL;
-
for (p = pool; p; p = p->d.next) {
p->d.last = (u_char *) p + sizeof(ngx_pool_t);
+ p->d.failed = 0;
}
+
+ pool->current = pool;
+ pool->chain = NULL;
+ pool->large = NULL;
}
diff --git a/usr.sbin/nginx/src/core/ngx_proxy_protocol.c b/usr.sbin/nginx/src/core/ngx_proxy_protocol.c
new file mode 100644
index 00000000000..59ef010fc06
--- /dev/null
+++ b/usr.sbin/nginx/src/core/ngx_proxy_protocol.c
@@ -0,0 +1,91 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+u_char *
+ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf, u_char *last)
+{
+ size_t len;
+ u_char ch, *p, *addr;
+
+ p = buf;
+ len = last - buf;
+
+ if (len < 8 || ngx_strncmp(p, "PROXY ", 6) != 0) {
+ goto invalid;
+ }
+
+ p += 6;
+ len -= 6;
+
+ if (len >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
+ ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
+ "PROXY protocol unknown protocol");
+ p += 7;
+ goto skip;
+ }
+
+ if (len < 5 || ngx_strncmp(p, "TCP", 3) != 0
+ || (p[3] != '4' && p[3] != '6') || p[4] != ' ')
+ {
+ goto invalid;
+ }
+
+ p += 5;
+ addr = p;
+
+ for ( ;; ) {
+ if (p == last) {
+ goto invalid;
+ }
+
+ ch = *p++;
+
+ if (ch == ' ') {
+ break;
+ }
+
+ if (ch != ':' && ch != '.'
+ && (ch < 'a' || ch > 'f')
+ && (ch < 'A' || ch > 'F')
+ && (ch < '0' || ch > '9'))
+ {
+ goto invalid;
+ }
+ }
+
+ len = p - addr - 1;
+ c->proxy_protocol_addr.data = ngx_pnalloc(c->pool, len);
+
+ if (c->proxy_protocol_addr.data == NULL) {
+ return NULL;
+ }
+
+ ngx_memcpy(c->proxy_protocol_addr.data, addr, len);
+ c->proxy_protocol_addr.len = len;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
+ "PROXY protocol address: \"%V\"", &c->proxy_protocol_addr);
+
+skip:
+
+ for ( /* void */ ; p < last - 1; p++) {
+ if (p[0] == CR && p[1] == LF) {
+ return p + 2;
+ }
+ }
+
+invalid:
+
+ ngx_log_error(NGX_LOG_ERR, c->log, 0,
+ "broken header: \"%*s\"", (size_t) (last - buf), buf);
+
+ return NULL;
+}
diff --git a/usr.sbin/nginx/src/core/ngx_proxy_protocol.h b/usr.sbin/nginx/src/core/ngx_proxy_protocol.h
new file mode 100644
index 00000000000..4f3912512f1
--- /dev/null
+++ b/usr.sbin/nginx/src/core/ngx_proxy_protocol.h
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright (C) Roman Arutyunyan
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_PROXY_PROTOCOL_H_INCLUDED_
+#define _NGX_PROXY_PROTOCOL_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#define NGX_PROXY_PROTOCOL_MAX_HEADER 107
+
+
+u_char *ngx_proxy_protocol_parse(ngx_connection_t *c, u_char *buf,
+ u_char *last);
+
+
+#endif /* _NGX_PROXY_PROTOCOL_H_INCLUDED_ */
diff --git a/usr.sbin/nginx/src/core/ngx_resolver.c b/usr.sbin/nginx/src/core/ngx_resolver.c
index d59d0c47162..645738ce531 100644
--- a/usr.sbin/nginx/src/core/ngx_resolver.c
+++ b/usr.sbin/nginx/src/core/ngx_resolver.c
@@ -26,7 +26,7 @@ typedef struct {
u_char nns_lo;
u_char nar_hi;
u_char nar_lo;
-} ngx_resolver_query_t;
+} ngx_resolver_hdr_t;
typedef struct {
@@ -70,7 +70,8 @@ static void ngx_resolver_read_response(ngx_event_t *rev);
static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
size_t n);
static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
- ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans);
+ ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
+ ngx_uint_t nan, ngx_uint_t ans);
static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
@@ -88,10 +89,17 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
static void ngx_resolver_free(ngx_resolver_t *r, void *p);
static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
-static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
- ngx_uint_t n);
+static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r,
+ ngx_resolver_node_t *rn, ngx_uint_t rotate);
static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
+#if (NGX_HAVE_INET6)
+static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
+static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
+ struct in6_addr *addr, uint32_t hash);
+#endif
+
ngx_resolver_t *
ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
@@ -134,6 +142,17 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
ngx_queue_init(&r->name_expire_queue);
ngx_queue_init(&r->addr_expire_queue);
+#if (NGX_HAVE_INET6)
+ r->ipv6 = 1;
+
+ ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel,
+ ngx_resolver_rbtree_insert_addr6_value);
+
+ ngx_queue_init(&r->addr6_resend_queue);
+
+ ngx_queue_init(&r->addr6_expire_queue);
+#endif
+
r->event->handler = ngx_resolver_resend_handler;
r->event->data = r;
r->event->log = &cf->cycle->new_log;
@@ -171,6 +190,25 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
continue;
}
+#if (NGX_HAVE_INET6)
+ if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {
+
+ if (ngx_strcmp(&names[i].data[5], "on") == 0) {
+ r->ipv6 = 1;
+
+ } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
+ r->ipv6 = 0;
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter: %V", &names[i]);
+ return NULL;
+ }
+
+ continue;
+ }
+#endif
+
ngx_memzero(&u, sizeof(ngx_url_t));
u.url = names[i];
@@ -220,6 +258,10 @@ ngx_resolver_cleanup(void *data)
ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
+#if (NGX_HAVE_INET6)
+ ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
+#endif
+
if (r->event) {
ngx_free(r->event);
}
@@ -281,7 +323,11 @@ ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
temp->state = NGX_OK;
temp->naddrs = 1;
temp->addrs = &temp->addr;
- temp->addr = addr;
+ temp->addr.sockaddr = (struct sockaddr *) &temp->sin;
+ temp->addr.socklen = sizeof(struct sockaddr_in);
+ ngx_memzero(&temp->sin, sizeof(struct sockaddr_in));
+ temp->sin.sin_family = AF_INET;
+ temp->sin.sin_addr.s_addr = addr;
temp->quick = 1;
return temp;
@@ -310,6 +356,10 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx)
r = ctx->resolver;
+ if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') {
+ ctx->name.len--;
+ }
+
ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
"resolve: \"%V\"", &ctx->name);
@@ -411,18 +461,18 @@ done:
}
-/* NGX_RESOLVE_A only */
-
static ngx_int_t
ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
{
uint32_t hash;
- in_addr_t addr, *addrs;
ngx_int_t rc;
ngx_uint_t naddrs;
+ ngx_addr_t *addrs;
ngx_resolver_ctx_t *next;
ngx_resolver_node_t *rn;
+ ngx_strlow(ctx->name.data, ctx->name.data, ctx->name.len);
+
hash = ngx_crc32_short(ctx->name.data, ctx->name.len);
rn = ngx_resolver_lookup_name(r, &ctx->name, hash);
@@ -439,22 +489,21 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
- naddrs = rn->naddrs;
+ naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
+#if (NGX_HAVE_INET6)
+ naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
+#endif
if (naddrs) {
- /* NGX_RESOLVE_A answer */
+ if (naddrs == 1 && rn->naddrs == 1) {
+ addrs = NULL;
- if (naddrs != 1) {
- addr = 0;
- addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
+ } else {
+ addrs = ngx_resolver_export(r, rn, 1);
if (addrs == NULL) {
return NGX_ERROR;
}
-
- } else {
- addr = rn->u.addr;
- addrs = NULL;
}
ctx->next = rn->waiting;
@@ -465,8 +514,19 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
do {
ctx->state = NGX_OK;
ctx->naddrs = naddrs;
- ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
- ctx->addr = addr;
+
+ if (addrs == NULL) {
+ ctx->addrs = &ctx->addr;
+ ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
+ ctx->addr.socklen = sizeof(struct sockaddr_in);
+ ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
+ ctx->sin.sin_family = AF_INET;
+ ctx->sin.sin_addr.s_addr = rn->u.addr;
+
+ } else {
+ ctx->addrs = addrs;
+ }
+
next = ctx->next;
ctx->handler(ctx);
@@ -474,7 +534,8 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
ctx = next;
} while (ctx);
- if (addrs) {
+ if (addrs != NULL) {
+ ngx_resolver_free(r, addrs->sockaddr);
ngx_resolver_free(r, addrs);
}
@@ -524,16 +585,25 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
if (rn->query) {
ngx_resolver_free_locked(r, rn->query);
rn->query = NULL;
+#if (NGX_HAVE_INET6)
+ rn->query6 = NULL;
+#endif
}
if (rn->cnlen) {
ngx_resolver_free_locked(r, rn->u.cname);
}
- if (rn->naddrs > 1) {
+ if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
ngx_resolver_free_locked(r, rn->u.addrs);
}
+#if (NGX_HAVE_INET6)
+ if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
+ ngx_resolver_free_locked(r, rn->u6.addrs6);
+ }
+#endif
+
/* unlock alloc mutex */
} else {
@@ -552,6 +622,9 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
rn->node.key = hash;
rn->nlen = (u_short) ctx->name.len;
rn->query = NULL;
+#if (NGX_HAVE_INET6)
+ rn->query6 = NULL;
+#endif
ngx_rbtree_insert(&r->name_rbtree, &rn->node);
}
@@ -575,6 +648,11 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
return NGX_OK;
}
+ rn->naddrs = (u_short) -1;
+#if (NGX_HAVE_INET6)
+ rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
+#endif
+
if (ngx_resolver_send_query(r, rn) != NGX_OK) {
goto failed;
}
@@ -601,9 +679,10 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);
+ rn->code = 0;
rn->cnlen = 0;
- rn->naddrs = 0;
rn->valid = 0;
+ rn->ttl = NGX_MAX_UINT32_VALUE;
rn->waiting = ctx;
ctx->state = NGX_AGAIN;
@@ -630,16 +709,57 @@ ngx_int_t
ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
{
u_char *name;
+ in_addr_t addr;
+ ngx_queue_t *resend_queue, *expire_queue;
+ ngx_rbtree_t *tree;
ngx_resolver_t *r;
+ struct sockaddr_in *sin;
ngx_resolver_node_t *rn;
+#if (NGX_HAVE_INET6)
+ uint32_t hash;
+ struct sockaddr_in6 *sin6;
+#endif
+
+#if (NGX_SUPPRESS_WARN)
+ addr = 0;
+#if (NGX_HAVE_INET6)
+ hash = 0;
+ sin6 = NULL;
+#endif
+#endif
r = ctx->resolver;
- ctx->addr = ntohl(ctx->addr);
+ switch (ctx->addr.sockaddr->sa_family) {
- /* lock addr mutex */
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
+ hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
+
+ /* lock addr mutex */
+
+ rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
+
+ tree = &r->addr6_rbtree;
+ resend_queue = &r->addr6_resend_queue;
+ expire_queue = &r->addr6_expire_queue;
+
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) ctx->addr.sockaddr;
+ addr = ntohl(sin->sin_addr.s_addr);
- rn = ngx_resolver_lookup_addr(r, ctx->addr);
+ /* lock addr mutex */
+
+ rn = ngx_resolver_lookup_addr(r, addr);
+
+ tree = &r->addr_rbtree;
+ resend_queue = &r->addr_resend_queue;
+ expire_queue = &r->addr_expire_queue;
+ }
if (rn) {
@@ -651,7 +771,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
rn->expire = ngx_time() + r->expire;
- ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
+ ngx_queue_insert_head(expire_queue, &rn->queue);
name = ngx_resolver_dup(r, rn->name, rn->nlen);
if (name == NULL) {
@@ -687,6 +807,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
ngx_resolver_free(r, rn->query);
rn->query = NULL;
+#if (NGX_HAVE_INET6)
+ rn->query6 = NULL;
+#endif
} else {
rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
@@ -694,16 +817,36 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
goto failed;
}
- rn->node.key = ctx->addr;
+ switch (ctx->addr.sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ rn->addr6 = sin6->sin6_addr;
+ rn->node.key = hash;
+ break;
+#endif
+
+ default: /* AF_INET */
+ rn->node.key = addr;
+ }
+
rn->query = NULL;
+#if (NGX_HAVE_INET6)
+ rn->query6 = NULL;
+#endif
- ngx_rbtree_insert(&r->addr_rbtree, &rn->node);
+ ngx_rbtree_insert(tree, &rn->node);
}
if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) {
goto failed;
}
+ rn->naddrs = (u_short) -1;
+#if (NGX_HAVE_INET6)
+ rn->naddrs6 = (u_short) -1;
+#endif
+
if (ngx_resolver_send_query(r, rn) != NGX_OK) {
goto failed;
}
@@ -720,19 +863,20 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
ngx_add_timer(ctx->event, ctx->timeout);
- if (ngx_queue_empty(&r->addr_resend_queue)) {
+ if (ngx_queue_empty(resend_queue)) {
ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
}
rn->expire = ngx_time() + r->resend_timeout;
- ngx_queue_insert_head(&r->addr_resend_queue, &rn->queue);
+ ngx_queue_insert_head(resend_queue, &rn->queue);
+ rn->code = 0;
rn->cnlen = 0;
- rn->naddrs = 0;
rn->name = NULL;
rn->nlen = 0;
rn->valid = 0;
+ rn->ttl = NGX_MAX_UINT32_VALUE;
rn->waiting = ctx;
/* unlock addr mutex */
@@ -744,7 +888,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
failed:
if (rn) {
- ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
+ ngx_rbtree_delete(tree, &rn->node);
if (rn->query) {
ngx_resolver_free(r, rn->query);
@@ -769,12 +913,33 @@ void
ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
{
in_addr_t addr;
+ ngx_queue_t *expire_queue;
+ ngx_rbtree_t *tree;
ngx_resolver_t *r;
ngx_resolver_ctx_t *w, **p;
+ struct sockaddr_in *sin;
ngx_resolver_node_t *rn;
+#if (NGX_HAVE_INET6)
+ uint32_t hash;
+ struct sockaddr_in6 *sin6;
+#endif
r = ctx->resolver;
+ switch (ctx->addr.sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ tree = &r->addr6_rbtree;
+ expire_queue = &r->addr6_expire_queue;
+ break;
+#endif
+
+ default: /* AF_INET */
+ tree = &r->addr_rbtree;
+ expire_queue = &r->addr_expire_queue;
+ }
+
ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
"resolve addr done: %i", ctx->state);
@@ -786,7 +951,21 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {
- rn = ngx_resolver_lookup_addr(r, ctx->addr);
+ switch (ctx->addr.sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
+ hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
+ rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
+ break;
+#endif
+
+ default: /* AF_INET */
+ sin = (struct sockaddr_in *) ctx->addr.sockaddr;
+ addr = ntohl(sin->sin_addr.s_addr);
+ rn = ngx_resolver_lookup_addr(r, addr);
+ }
if (rn) {
p = &rn->waiting;
@@ -804,17 +983,22 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
}
}
- addr = ntohl(ctx->addr);
+ {
+ u_char text[NGX_SOCKADDR_STRLEN];
+ ngx_str_t addrtext;
- ngx_log_error(NGX_LOG_ALERT, r->log, 0,
- "could not cancel %ud.%ud.%ud.%ud resolving",
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff);
+ addrtext.data = text;
+ addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen,
+ text, NGX_SOCKADDR_STRLEN, 0);
+
+ ngx_log_error(NGX_LOG_ALERT, r->log, 0,
+ "could not cancel %V resolving", &addrtext);
+ }
}
done:
- ngx_resolver_expire(r, &r->addr_rbtree, &r->addr_expire_queue);
+ ngx_resolver_expire(r, tree, expire_queue);
/* unlock addr mutex */
@@ -896,16 +1080,33 @@ ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
uc->connection->read->resolver = 1;
}
- n = ngx_send(uc->connection, rn->query, rn->qlen);
+ if (rn->naddrs == (u_short) -1) {
+ n = ngx_send(uc->connection, rn->query, rn->qlen);
- if (n == -1) {
- return NGX_ERROR;
+ if (n == -1) {
+ return NGX_ERROR;
+ }
+
+ if ((size_t) n != (size_t) rn->qlen) {
+ ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
+ return NGX_ERROR;
+ }
}
- if ((size_t) n != (size_t) rn->qlen) {
- ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
- return NGX_ERROR;
+#if (NGX_HAVE_INET6)
+ if (rn->query6 && rn->naddrs6 == (u_short) -1) {
+ n = ngx_send(uc->connection, rn->query6, rn->qlen);
+
+ if (n == -1) {
+ return NGX_ERROR;
+ }
+
+ if ((size_t) n != (size_t) rn->qlen) {
+ ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
+ return NGX_ERROR;
+ }
}
+#endif
return NGX_OK;
}
@@ -915,6 +1116,9 @@ static void
ngx_resolver_resend_handler(ngx_event_t *ev)
{
time_t timer, atimer, ntimer;
+#if (NGX_HAVE_INET6)
+ time_t a6timer;
+#endif
ngx_resolver_t *r;
r = ev->data;
@@ -934,16 +1138,36 @@ ngx_resolver_resend_handler(ngx_event_t *ev)
/* unlock addr mutex */
- if (ntimer == 0) {
+#if (NGX_HAVE_INET6)
+
+ /* lock addr6 mutex */
+
+ a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue);
+
+ /* unlock addr6 mutex */
+
+#endif
+
+ timer = ntimer;
+
+ if (timer == 0) {
timer = atimer;
- } else if (atimer == 0) {
- timer = ntimer;
+ } else if (atimer) {
+ timer = ngx_min(timer, atimer);
+ }
- } else {
- timer = (atimer < ntimer) ? atimer : ntimer;
+#if (NGX_HAVE_INET6)
+
+ if (timer == 0) {
+ timer = a6timer;
+
+ } else if (a6timer) {
+ timer = ngx_min(timer, a6timer);
}
+#endif
+
if (timer) {
ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000));
}
@@ -1021,39 +1245,42 @@ ngx_resolver_read_response(ngx_event_t *rev)
static void
ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
{
- char *err;
- size_t len;
- ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
- qtype, qclass;
- ngx_queue_t *q;
- ngx_resolver_qs_t *qs;
- ngx_resolver_node_t *rn;
- ngx_resolver_query_t *query;
-
- if ((size_t) n < sizeof(ngx_resolver_query_t)) {
+ char *err;
+ ngx_uint_t i, times, ident, qident, flags, code, nqs, nan,
+ qtype, qclass;
+#if (NGX_HAVE_INET6)
+ ngx_uint_t qident6;
+#endif
+ ngx_queue_t *q;
+ ngx_resolver_qs_t *qs;
+ ngx_resolver_hdr_t *response;
+ ngx_resolver_node_t *rn;
+
+ if (n < sizeof(ngx_resolver_hdr_t)) {
goto short_response;
}
- query = (ngx_resolver_query_t *) buf;
+ response = (ngx_resolver_hdr_t *) buf;
- ident = (query->ident_hi << 8) + query->ident_lo;
- flags = (query->flags_hi << 8) + query->flags_lo;
- nqs = (query->nqs_hi << 8) + query->nqs_lo;
- nan = (query->nan_hi << 8) + query->nan_lo;
+ ident = (response->ident_hi << 8) + response->ident_lo;
+ flags = (response->flags_hi << 8) + response->flags_lo;
+ nqs = (response->nqs_hi << 8) + response->nqs_lo;
+ nan = (response->nan_hi << 8) + response->nan_lo;
ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
"resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
ident, flags, nqs, nan,
- (query->nns_hi << 8) + query->nns_lo,
- (query->nar_hi << 8) + query->nar_lo);
+ (response->nns_hi << 8) + response->nns_lo,
+ (response->nar_hi << 8) + response->nar_lo);
- if (!(flags & 0x8000)) {
+ /* response to a standard query */
+ if ((flags & 0xf870) != 0x8000) {
ngx_log_error(r->log_level, r->log, 0,
"invalid DNS response %ui fl:%04Xui", ident, flags);
return;
}
- code = flags & 0x7f;
+ code = flags & 0xf;
if (code == NGX_RESOLVE_FORMERR) {
@@ -1067,12 +1294,18 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
qident = (rn->query[0] << 8) + rn->query[1];
if (qident == ident) {
- ngx_log_error(r->log_level, r->log, 0,
- "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
- code, ngx_resolver_strerror(code), ident,
- rn->nlen, rn->name);
- return;
+ goto dns_error_name;
+ }
+
+#if (NGX_HAVE_INET6)
+ if (rn->query6) {
+ qident6 = (rn->query6[0] << 8) + rn->query6[1];
+
+ if (qident6 == ident) {
+ goto dns_error_name;
+ }
}
+#endif
}
goto dns_error;
@@ -1087,22 +1320,21 @@ ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
goto done;
}
- i = sizeof(ngx_resolver_query_t);
+ i = sizeof(ngx_resolver_hdr_t);
while (i < (ngx_uint_t) n) {
if (buf[i] == '\0') {
goto found;
}
- len = buf[i];
- i += 1 + len;
+ i += 1 + buf[i];
}
goto short_response;
found:
- if (i++ == 0) {
+ if (i++ == sizeof(ngx_resolver_hdr_t)) {
err = "zero-length domain name in DNS response";
goto done;
}
@@ -1130,8 +1362,11 @@ found:
switch (qtype) {
case NGX_RESOLVE_A:
+#if (NGX_HAVE_INET6)
+ case NGX_RESOLVE_AAAA:
+#endif
- ngx_resolver_process_a(r, buf, n, ident, code, nan,
+ ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan,
i + sizeof(ngx_resolver_qs_t));
break;
@@ -1152,7 +1387,7 @@ found:
short_response:
- err = "short dns response";
+ err = "short DNS response";
done:
@@ -1160,6 +1395,14 @@ done:
return;
+dns_error_name:
+
+ ngx_log_error(r->log_level, r->log, 0,
+ "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
+ code, ngx_resolver_strerror(code), ident,
+ rn->nlen, rn->name);
+ return;
+
dns_error:
ngx_log_error(r->log_level, r->log, 0,
@@ -1171,21 +1414,29 @@ dns_error:
static void
ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
- ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans)
+ ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
+ ngx_uint_t nan, ngx_uint_t ans)
{
char *err;
u_char *cname;
size_t len;
int32_t ttl;
uint32_t hash;
- in_addr_t addr, *addrs;
+ in_addr_t *addr;
ngx_str_t name;
- ngx_uint_t qtype, qident, naddrs, a, i, n, start;
+ ngx_addr_t *addrs;
+ ngx_uint_t type, class, qident, naddrs, a, i, n, start;
+#if (NGX_HAVE_INET6)
+ struct in6_addr *addr6;
+#endif
ngx_resolver_an_t *an;
ngx_resolver_ctx_t *ctx, *next;
ngx_resolver_node_t *rn;
- if (ngx_resolver_copy(r, &name, buf, &buf[12], &buf[last]) != NGX_OK) {
+ if (ngx_resolver_copy(r, &name, buf,
+ buf + sizeof(ngx_resolver_hdr_t), buf + last)
+ != NGX_OK)
+ {
return;
}
@@ -1197,28 +1448,113 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
rn = ngx_resolver_lookup_name(r, &name, hash);
- if (rn == NULL || rn->query == NULL) {
+ if (rn == NULL) {
ngx_log_error(r->log_level, r->log, 0,
"unexpected response for %V", &name);
+ ngx_resolver_free(r, name.data);
goto failed;
}
- qident = (rn->query[0] << 8) + rn->query[1];
+ switch (qtype) {
+
+#if (NGX_HAVE_INET6)
+ case NGX_RESOLVE_AAAA:
+
+ if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
+ ngx_log_error(r->log_level, r->log, 0,
+ "unexpected response for %V", &name);
+ ngx_resolver_free(r, name.data);
+ goto failed;
+ }
+
+ rn->naddrs6 = 0;
+ qident = (rn->query6[0] << 8) + rn->query6[1];
+
+ break;
+#endif
+
+ default: /* NGX_RESOLVE_A */
+
+ if (rn->query == NULL || rn->naddrs != (u_short) -1) {
+ ngx_log_error(r->log_level, r->log, 0,
+ "unexpected response for %V", &name);
+ ngx_resolver_free(r, name.data);
+ goto failed;
+ }
+
+ rn->naddrs = 0;
+ qident = (rn->query[0] << 8) + rn->query[1];
+ }
if (ident != qident) {
ngx_log_error(r->log_level, r->log, 0,
"wrong ident %ui response for %V, expect %ui",
ident, &name, qident);
+ ngx_resolver_free(r, name.data);
goto failed;
}
ngx_resolver_free(r, name.data);
+ if (code == 0 && rn->code) {
+ code = rn->code;
+ }
+
if (code == 0 && nan == 0) {
- code = 3; /* NXDOMAIN */
+
+#if (NGX_HAVE_INET6)
+ switch (qtype) {
+
+ case NGX_RESOLVE_AAAA:
+
+ if (rn->naddrs == (u_short) -1) {
+ goto next;
+ }
+
+ if (rn->naddrs) {
+ goto export;
+ }
+
+ break;
+
+ default: /* NGX_RESOLVE_A */
+
+ if (rn->naddrs6 == (u_short) -1) {
+ goto next;
+ }
+
+ if (rn->naddrs6) {
+ goto export;
+ }
+ }
+#endif
+
+ code = NGX_RESOLVE_NXDOMAIN;
}
if (code) {
+
+#if (NGX_HAVE_INET6)
+ switch (qtype) {
+
+ case NGX_RESOLVE_AAAA:
+
+ if (rn->naddrs == (u_short) -1) {
+ rn->code = (u_char) code;
+ goto next;
+ }
+
+ break;
+
+ default: /* NGX_RESOLVE_A */
+
+ if (rn->naddrs6 == (u_short) -1) {
+ rn->code = (u_char) code;
+ goto next;
+ }
+ }
+#endif
+
next = rn->waiting;
rn->waiting = NULL;
@@ -1231,11 +1567,11 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
/* unlock name mutex */
while (next) {
- ctx = next;
- ctx->state = code;
- next = ctx->next;
+ ctx = next;
+ ctx->state = code;
+ next = ctx->next;
- ctx->handler(ctx);
+ ctx->handler(ctx);
}
return;
@@ -1243,11 +1579,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
i = ans;
naddrs = 0;
- addr = 0;
- addrs = NULL;
cname = NULL;
- qtype = 0;
- ttl = 0;
for (a = 0; a < nan; a++) {
@@ -1273,7 +1605,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
test_length:
if (i - start < 2) {
- err = "invalid name in dns response";
+ err = "invalid name in DNS response";
goto invalid;
}
@@ -1285,115 +1617,239 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
an = (ngx_resolver_an_t *) &buf[i];
- qtype = (an->type_hi << 8) + an->type_lo;
+ type = (an->type_hi << 8) + an->type_lo;
+ class = (an->class_hi << 8) + an->class_lo;
len = (an->len_hi << 8) + an->len_lo;
ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
+ (an->ttl[2] << 8) + (an->ttl[3]);
+ if (class != 1) {
+ ngx_log_error(r->log_level, r->log, 0,
+ "unexpected RR class %ui", class);
+ goto failed;
+ }
+
if (ttl < 0) {
ttl = 0;
}
- if (qtype == NGX_RESOLVE_A) {
+ rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);
- i += sizeof(ngx_resolver_an_t);
+ i += sizeof(ngx_resolver_an_t);
+
+ switch (type) {
+
+ case NGX_RESOLVE_A:
+
+ if (qtype != NGX_RESOLVE_A) {
+ err = "unexpected A record in DNS response";
+ goto invalid;
+ }
- if (i + len > last) {
+ if (len != 4) {
+ err = "invalid A record in DNS response";
+ goto invalid;
+ }
+
+ if (i + 4 > last) {
goto short_response;
}
- addr = htonl((buf[i] << 24) + (buf[i + 1] << 16)
- + (buf[i + 2] << 8) + (buf[i + 3]));
+ naddrs++;
+
+ break;
+
+#if (NGX_HAVE_INET6)
+ case NGX_RESOLVE_AAAA:
+
+ if (qtype != NGX_RESOLVE_AAAA) {
+ err = "unexpected AAAA record in DNS response";
+ goto invalid;
+ }
+
+ if (len != 16) {
+ err = "invalid AAAA record in DNS response";
+ goto invalid;
+ }
+
+ if (i + 16 > last) {
+ goto short_response;
+ }
naddrs++;
- i += len;
+ break;
+#endif
- } else if (qtype == NGX_RESOLVE_CNAME) {
- cname = &buf[i] + sizeof(ngx_resolver_an_t);
- i += sizeof(ngx_resolver_an_t) + len;
+ case NGX_RESOLVE_CNAME:
- } else if (qtype == NGX_RESOLVE_DNAME) {
- i += sizeof(ngx_resolver_an_t) + len;
+ cname = &buf[i];
+
+ break;
+
+ case NGX_RESOLVE_DNAME:
+
+ break;
+
+ default:
- } else {
ngx_log_error(r->log_level, r->log, 0,
- "unexpected qtype %ui", qtype);
+ "unexpected RR type %ui", type);
}
+
+ i += len;
}
ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
- "resolver naddrs:%ui cname:%p ttl:%d",
- naddrs, cname, ttl);
+ "resolver naddrs:%ui cname:%p ttl:%uD",
+ naddrs, cname, rn->ttl);
if (naddrs) {
- if (naddrs == 1) {
- rn->u.addr = addr;
+ switch (qtype) {
- } else {
+#if (NGX_HAVE_INET6)
+ case NGX_RESOLVE_AAAA:
- addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
- if (addrs == NULL) {
- return;
+ if (naddrs == 1) {
+ addr6 = &rn->u6.addr6;
+ rn->naddrs6 = 1;
+
+ } else {
+ addr6 = ngx_resolver_alloc(r, naddrs * sizeof(struct in6_addr));
+ if (addr6 == NULL) {
+ goto failed;
+ }
+
+ rn->u6.addrs6 = addr6;
+ rn->naddrs6 = (u_short) naddrs;
}
- n = 0;
- i = ans;
+#if (NGX_SUPPRESS_WARN)
+ addr = NULL;
+#endif
- for (a = 0; a < nan; a++) {
+ break;
+#endif
- for ( ;; ) {
+ default: /* NGX_RESOLVE_A */
- if (buf[i] & 0xc0) {
- i += 2;
- goto ok;
- }
+ if (naddrs == 1) {
+ addr = &rn->u.addr;
+ rn->naddrs = 1;
- if (buf[i] == 0) {
- i++;
- goto ok;
- }
+ } else {
+ addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
+ if (addr == NULL) {
+ goto failed;
+ }
+
+ rn->u.addrs = addr;
+ rn->naddrs = (u_short) naddrs;
+ }
+
+#if (NGX_HAVE_INET6 && NGX_SUPPRESS_WARN)
+ addr6 = NULL;
+#endif
+ }
- i += 1 + buf[i];
+ n = 0;
+ i = ans;
+
+ for (a = 0; a < nan; a++) {
+
+ for ( ;; ) {
+
+ if (buf[i] & 0xc0) {
+ i += 2;
+ break;
+ }
+
+ if (buf[i] == 0) {
+ i++;
+ break;
}
- ok:
+ i += 1 + buf[i];
+ }
+
+ an = (ngx_resolver_an_t *) &buf[i];
- an = (ngx_resolver_an_t *) &buf[i];
+ type = (an->type_hi << 8) + an->type_lo;
+ len = (an->len_hi << 8) + an->len_lo;
- qtype = (an->type_hi << 8) + an->type_lo;
- len = (an->len_hi << 8) + an->len_lo;
+ i += sizeof(ngx_resolver_an_t);
- i += sizeof(ngx_resolver_an_t);
+ if (type == NGX_RESOLVE_A) {
- if (qtype == NGX_RESOLVE_A) {
+ addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
+ + (buf[i + 2] << 8) + (buf[i + 3]));
- addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
- + (buf[i + 2] << 8) + (buf[i + 3]));
+ if (++n == naddrs) {
- if (n == naddrs) {
- break;
+#if (NGX_HAVE_INET6)
+ if (rn->naddrs6 == (u_short) -1) {
+ goto next;
}
+#endif
+
+ break;
}
+ }
+
+#if (NGX_HAVE_INET6)
+ else if (type == NGX_RESOLVE_AAAA) {
+
+ ngx_memcpy(addr6[n].s6_addr, &buf[i], 16);
+
+ if (++n == naddrs) {
+
+ if (rn->naddrs == (u_short) -1) {
+ goto next;
+ }
- i += len;
+ break;
+ }
}
+#endif
- rn->u.addrs = addrs;
+ i += len;
+ }
+ }
- addrs = ngx_resolver_dup(r, rn->u.addrs,
- naddrs * sizeof(in_addr_t));
+ if (rn->naddrs != (u_short) -1
+#if (NGX_HAVE_INET6)
+ && rn->naddrs6 != (u_short) -1
+#endif
+ && rn->naddrs
+#if (NGX_HAVE_INET6)
+ + rn->naddrs6
+#endif
+ > 0)
+ {
+
+#if (NGX_HAVE_INET6)
+ export:
+#endif
+
+ naddrs = rn->naddrs;
+#if (NGX_HAVE_INET6)
+ naddrs += rn->naddrs6;
+#endif
+
+ if (naddrs == 1 && rn->naddrs == 1) {
+ addrs = NULL;
+
+ } else {
+ addrs = ngx_resolver_export(r, rn, 0);
if (addrs == NULL) {
- return;
+ goto failed;
}
}
- rn->naddrs = (u_short) naddrs;
-
ngx_queue_remove(&rn->queue);
- rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
+ rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
rn->expire = ngx_time() + r->expire;
ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
@@ -1404,31 +1860,56 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
/* unlock name mutex */
while (next) {
- ctx = next;
- ctx->state = NGX_OK;
- ctx->naddrs = naddrs;
- ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
- ctx->addr = addr;
- next = ctx->next;
+ ctx = next;
+ ctx->state = NGX_OK;
+ ctx->naddrs = naddrs;
+
+ if (addrs == NULL) {
+ ctx->addrs = &ctx->addr;
+ ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
+ ctx->addr.socklen = sizeof(struct sockaddr_in);
+ ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
+ ctx->sin.sin_family = AF_INET;
+ ctx->sin.sin_addr.s_addr = rn->u.addr;
+
+ } else {
+ ctx->addrs = addrs;
+ }
- ctx->handler(ctx);
+ next = ctx->next;
+
+ ctx->handler(ctx);
}
- if (naddrs > 1) {
+ if (addrs != NULL) {
+ ngx_resolver_free(r, addrs->sockaddr);
ngx_resolver_free(r, addrs);
}
ngx_resolver_free(r, rn->query);
rn->query = NULL;
+#if (NGX_HAVE_INET6)
+ rn->query6 = NULL;
+#endif
return;
+ }
- } else if (cname) {
+ if (cname) {
/* CNAME only */
- if (ngx_resolver_copy(r, &name, buf, cname, &buf[last]) != NGX_OK) {
- return;
+ if (rn->naddrs == (u_short) -1
+#if (NGX_HAVE_INET6)
+ || rn->naddrs6 == (u_short) -1
+#endif
+ )
+ {
+ goto next;
+ }
+
+ if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
+ goto failed;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
@@ -1439,7 +1920,7 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
rn->cnlen = (u_short) name.len;
rn->u.cname = name.data;
- rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
+ rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
rn->expire = ngx_time() + r->expire;
ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);
@@ -1455,18 +1936,22 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
ngx_resolver_free(r, rn->query);
rn->query = NULL;
+#if (NGX_HAVE_INET6)
+ rn->query6 = NULL;
+#endif
+
+ /* unlock name mutex */
return;
}
ngx_log_error(r->log_level, r->log, 0,
- "no A or CNAME types in DNS responses, unknown query type: %ui",
- qtype);
+ "no A or CNAME types in DNS response");
return;
short_response:
- err = "short dns response";
+ err = "short DNS response";
invalid:
@@ -1478,9 +1963,9 @@ invalid:
failed:
- /* unlock name mutex */
+next:
- ngx_resolver_free(r, name.data);
+ /* unlock name mutex */
return;
}
@@ -1492,47 +1977,123 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
{
char *err;
size_t len;
+ u_char text[NGX_SOCKADDR_STRLEN];
in_addr_t addr;
int32_t ttl;
- ngx_int_t digit;
+ ngx_int_t octet;
ngx_str_t name;
- ngx_uint_t i, mask, qident;
+ ngx_uint_t i, mask, qident, class;
+ ngx_queue_t *expire_queue;
+ ngx_rbtree_t *tree;
ngx_resolver_an_t *an;
ngx_resolver_ctx_t *ctx, *next;
ngx_resolver_node_t *rn;
+#if (NGX_HAVE_INET6)
+ uint32_t hash;
+ ngx_int_t digit;
+ struct in6_addr addr6;
+#endif
- if (ngx_resolver_copy(r, NULL, buf, &buf[12], &buf[n]) != NGX_OK) {
- goto invalid_in_addr_arpa;
+ if (ngx_resolver_copy(r, NULL, buf,
+ buf + sizeof(ngx_resolver_hdr_t), buf + n)
+ != NGX_OK)
+ {
+ return;
}
+ /* AF_INET */
+
addr = 0;
- i = 12;
+ i = sizeof(ngx_resolver_hdr_t);
for (mask = 0; mask < 32; mask += 8) {
len = buf[i++];
- digit = ngx_atoi(&buf[i], len);
- if (digit == NGX_ERROR || digit > 255) {
+ octet = ngx_atoi(&buf[i], len);
+ if (octet == NGX_ERROR || octet > 255) {
goto invalid_in_addr_arpa;
}
- addr += digit << mask;
+ addr += octet << mask;
i += len;
}
- if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") != 0) {
- goto invalid_in_addr_arpa;
+ if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
+ i += sizeof("\7in-addr\4arpa");
+
+ /* lock addr mutex */
+
+ rn = ngx_resolver_lookup_addr(r, addr);
+
+ tree = &r->addr_rbtree;
+ expire_queue = &r->addr_expire_queue;
+
+ addr = htonl(addr);
+ name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN);
+ name.data = text;
+
+ goto valid;
}
- /* lock addr mutex */
+invalid_in_addr_arpa:
+
+#if (NGX_HAVE_INET6)
+
+ i = sizeof(ngx_resolver_hdr_t);
+
+ for (octet = 15; octet >= 0; octet--) {
+ if (buf[i++] != '\1') {
+ goto invalid_ip6_arpa;
+ }
+
+ digit = ngx_hextoi(&buf[i++], 1);
+ if (digit == NGX_ERROR) {
+ goto invalid_ip6_arpa;
+ }
+
+ addr6.s6_addr[octet] = (u_char) digit;
+
+ if (buf[i++] != '\1') {
+ goto invalid_ip6_arpa;
+ }
+
+ digit = ngx_hextoi(&buf[i++], 1);
+ if (digit == NGX_ERROR) {
+ goto invalid_ip6_arpa;
+ }
+
+ addr6.s6_addr[octet] += (u_char) (digit * 16);
+ }
+
+ if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
+ i += sizeof("\3ip6\4arpa");
+
+ /* lock addr mutex */
+
+ hash = ngx_crc32_short(addr6.s6_addr, 16);
+ rn = ngx_resolver_lookup_addr6(r, &addr6, hash);
+
+ tree = &r->addr6_rbtree;
+ expire_queue = &r->addr6_expire_queue;
+
+ name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN);
+ name.data = text;
+
+ goto valid;
+ }
- rn = ngx_resolver_lookup_addr(r, addr);
+invalid_ip6_arpa:
+#endif
+
+ ngx_log_error(r->log_level, r->log, 0,
+ "invalid in-addr.arpa or ip6.arpa name in DNS response");
+ return;
+
+valid:
if (rn == NULL || rn->query == NULL) {
ngx_log_error(r->log_level, r->log, 0,
- "unexpected response for %ud.%ud.%ud.%ud",
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff);
+ "unexpected response for %V", &name);
goto failed;
}
@@ -1540,14 +2101,13 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
if (ident != qident) {
ngx_log_error(r->log_level, r->log, 0,
- "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui",
- ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff, qident);
+ "wrong ident %ui response for %V, expect %ui",
+ ident, &name, qident);
goto failed;
}
if (code == 0 && nan == 0) {
- code = 3; /* NXDOMAIN */
+ code = NGX_RESOLVE_NXDOMAIN;
}
if (code) {
@@ -1556,42 +2116,49 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
ngx_queue_remove(&rn->queue);
- ngx_rbtree_delete(&r->addr_rbtree, &rn->node);
+ ngx_rbtree_delete(tree, &rn->node);
ngx_resolver_free_node(r, rn);
/* unlock addr mutex */
while (next) {
- ctx = next;
- ctx->state = code;
- next = ctx->next;
+ ctx = next;
+ ctx->state = code;
+ next = ctx->next;
- ctx->handler(ctx);
+ ctx->handler(ctx);
}
return;
}
- i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t);
+ i += sizeof(ngx_resolver_qs_t);
- if (i + 2 + sizeof(ngx_resolver_an_t) > (ngx_uint_t) n) {
+ if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
goto short_response;
}
- /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */
+ /* compression pointer to *.arpa */
- if (buf[i] != 0xc0 || buf[i + 1] != 0x0c) {
- err = "invalid in-addr.arpa name in DNS response";
+ if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
+ err = "invalid in-addr.arpa or ip6.arpa name in DNS response";
goto invalid;
}
an = (ngx_resolver_an_t *) &buf[i + 2];
+ class = (an->class_hi << 8) + an->class_lo;
len = (an->len_hi << 8) + an->len_lo;
ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
+ (an->ttl[2] << 8) + (an->ttl[3]);
+ if (class != 1) {
+ ngx_log_error(r->log_level, r->log, 0,
+ "unexpected RR class %ui", class);
+ goto failed;
+ }
+
if (ttl < 0) {
ttl = 0;
}
@@ -1599,16 +2166,16 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
"resolver qt:%ui cl:%ui len:%uz",
(an->type_hi << 8) + an->type_lo,
- (an->class_hi << 8) + an->class_lo, len);
+ class, len);
i += 2 + sizeof(ngx_resolver_an_t);
- if (i + len > (ngx_uint_t) n) {
+ if (i + len > n) {
goto short_response;
}
- if (ngx_resolver_copy(r, &name, buf, &buf[i], &buf[n]) != NGX_OK) {
- return;
+ if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
+ goto failed;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);
@@ -1634,7 +2201,7 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
rn->expire = ngx_time() + r->expire;
- ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
+ ngx_queue_insert_head(expire_queue, &rn->queue);
next = rn->waiting;
rn->waiting = NULL;
@@ -1642,24 +2209,18 @@ ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
/* unlock addr mutex */
while (next) {
- ctx = next;
- ctx->state = NGX_OK;
- ctx->name = name;
- next = ctx->next;
+ ctx = next;
+ ctx->state = NGX_OK;
+ ctx->name = name;
+ next = ctx->next;
- ctx->handler(ctx);
+ ctx->handler(ctx);
}
ngx_resolver_free(r, name.data);
return;
-invalid_in_addr_arpa:
-
- ngx_log_error(r->log_level, r->log, 0,
- "invalid in-addr.arpa name in DNS response");
- return;
-
short_response:
err = "short DNS response";
@@ -1752,6 +2313,52 @@ ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
}
+#if (NGX_HAVE_INET6)
+
+static ngx_resolver_node_t *
+ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
+ uint32_t hash)
+{
+ ngx_int_t rc;
+ ngx_rbtree_node_t *node, *sentinel;
+ ngx_resolver_node_t *rn;
+
+ node = r->addr6_rbtree.root;
+ sentinel = r->addr6_rbtree.sentinel;
+
+ while (node != sentinel) {
+
+ if (hash < node->key) {
+ node = node->left;
+ continue;
+ }
+
+ if (hash > node->key) {
+ node = node->right;
+ continue;
+ }
+
+ /* hash == node->key */
+
+ rn = (ngx_resolver_node_t *) node;
+
+ rc = ngx_memcmp(addr, &rn->addr6, 16);
+
+ if (rc == 0) {
+ return rn;
+ }
+
+ node = (rc < 0) ? node->left : node->right;
+ }
+
+ /* not found */
+
+ return NULL;
+}
+
+#endif
+
+
static void
ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
@@ -1793,20 +2400,74 @@ ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
}
+#if (NGX_HAVE_INET6)
+
+static void
+ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
+ ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
+{
+ ngx_rbtree_node_t **p;
+ ngx_resolver_node_t *rn, *rn_temp;
+
+ for ( ;; ) {
+
+ if (node->key < temp->key) {
+
+ p = &temp->left;
+
+ } else if (node->key > temp->key) {
+
+ p = &temp->right;
+
+ } else { /* node->key == temp->key */
+
+ rn = (ngx_resolver_node_t *) node;
+ rn_temp = (ngx_resolver_node_t *) temp;
+
+ p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)
+ < 0) ? &temp->left : &temp->right;
+ }
+
+ if (*p == sentinel) {
+ break;
+ }
+
+ temp = *p;
+ }
+
+ *p = node;
+ node->parent = temp;
+ node->left = sentinel;
+ node->right = sentinel;
+ ngx_rbt_red(node);
+}
+
+#endif
+
+
static ngx_int_t
ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
{
- u_char *p, *s;
- size_t len, nlen;
- ngx_uint_t ident;
- ngx_resolver_qs_t *qs;
- ngx_resolver_query_t *query;
+ u_char *p, *s;
+ size_t len, nlen;
+ ngx_uint_t ident;
+#if (NGX_HAVE_INET6)
+ ngx_resolver_t *r;
+#endif
+ ngx_resolver_qs_t *qs;
+ ngx_resolver_hdr_t *query;
nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1;
- len = sizeof(ngx_resolver_query_t) + nlen + sizeof(ngx_resolver_qs_t);
+ len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
+#if (NGX_HAVE_INET6)
+ r = ctx->resolver;
+
+ p = ngx_resolver_alloc(ctx->resolver, r->ipv6 ? len * 2 : len);
+#else
p = ngx_resolver_alloc(ctx->resolver, len);
+#endif
if (p == NULL) {
return NGX_ERROR;
}
@@ -1814,12 +2475,18 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
rn->qlen = (u_short) len;
rn->query = p;
- query = (ngx_resolver_query_t *) p;
+#if (NGX_HAVE_INET6)
+ if (r->ipv6) {
+ rn->query6 = p + len;
+ }
+#endif
+
+ query = (ngx_resolver_hdr_t *) p;
ident = ngx_random();
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
- "resolve: \"%V\" %i", &ctx->name, ident & 0xffff);
+ "resolve: \"%V\" A %i", &ctx->name, ident & 0xffff);
query->ident_hi = (u_char) ((ident >> 8) & 0xff);
query->ident_lo = (u_char) (ident & 0xff);
@@ -1833,14 +2500,14 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
query->nns_hi = 0; query->nns_lo = 0;
query->nar_hi = 0; query->nar_lo = 0;
- p += sizeof(ngx_resolver_query_t) + nlen;
+ p += sizeof(ngx_resolver_hdr_t) + nlen;
qs = (ngx_resolver_qs_t *) p;
/* query type */
- qs->type_hi = 0; qs->type_lo = (u_char) ctx->type;
+ qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_A;
- /* IP query class */
+ /* IN query class */
qs->class_hi = 0; qs->class_lo = 1;
/* convert "www.example.com" to "\3www\7example\3com\0" */
@@ -1876,24 +2543,66 @@ ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
*p = (u_char) len;
+#if (NGX_HAVE_INET6)
+ if (!r->ipv6) {
+ return NGX_OK;
+ }
+
+ p = rn->query6;
+
+ ngx_memcpy(p, rn->query, rn->qlen);
+
+ query = (ngx_resolver_hdr_t *) p;
+
+ ident = ngx_random();
+
+ ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
+ "resolve: \"%V\" AAAA %i", &ctx->name, ident & 0xffff);
+
+ query->ident_hi = (u_char) ((ident >> 8) & 0xff);
+ query->ident_lo = (u_char) (ident & 0xff);
+
+ p += sizeof(ngx_resolver_hdr_t) + nlen;
+
+ qs = (ngx_resolver_qs_t *) p;
+
+ qs->type_lo = NGX_RESOLVE_AAAA;
+#endif
+
return NGX_OK;
}
-/* AF_INET only */
-
static ngx_int_t
ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
{
- u_char *p, *d;
- size_t len;
- ngx_int_t n;
- ngx_uint_t ident;
- ngx_resolver_query_t *query;
+ u_char *p, *d;
+ size_t len;
+ in_addr_t addr;
+ ngx_int_t n;
+ ngx_uint_t ident;
+ ngx_resolver_hdr_t *query;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ struct sockaddr_in6 *sin6;
+#endif
+
+ switch (ctx->addr.sockaddr->sa_family) {
- len = sizeof(ngx_resolver_query_t)
- + sizeof(".255.255.255.255.in-addr.arpa.") - 1
- + sizeof(ngx_resolver_qs_t);
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ len = sizeof(ngx_resolver_hdr_t)
+ + 64 + sizeof(".ip6.arpa.") - 1
+ + sizeof(ngx_resolver_qs_t);
+
+ break;
+#endif
+
+ default: /* AF_INET */
+ len = sizeof(ngx_resolver_hdr_t)
+ + sizeof(".255.255.255.255.in-addr.arpa.") - 1
+ + sizeof(ngx_resolver_qs_t);
+ }
p = ngx_resolver_alloc(ctx->resolver, len);
if (p == NULL) {
@@ -1901,7 +2610,7 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
}
rn->query = p;
- query = (ngx_resolver_query_t *) p;
+ query = (ngx_resolver_hdr_t *) p;
ident = ngx_random();
@@ -1917,20 +2626,43 @@ ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
query->nns_hi = 0; query->nns_lo = 0;
query->nar_hi = 0; query->nar_lo = 0;
- p += sizeof(ngx_resolver_query_t);
+ p += sizeof(ngx_resolver_hdr_t);
+
+ switch (ctx->addr.sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
+
+ for (n = 15; n >= 0; n--) {
+ p = ngx_sprintf(p, "\1%xd\1%xd",
+ sin6->sin6_addr.s6_addr[n] & 0xf,
+ (sin6->sin6_addr.s6_addr[n] >> 4) & 0xf);
+ }
+
+ p = ngx_cpymem(p, "\3ip6\4arpa\0", 10);
- for (n = 0; n < 32; n += 8) {
- d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);
- *p = (u_char) (d - &p[1]);
- p = d;
+ break;
+#endif
+
+ default: /* AF_INET */
+
+ sin = (struct sockaddr_in *) ctx->addr.sockaddr;
+ addr = ntohl(sin->sin_addr.s_addr);
+
+ for (n = 0; n < 32; n += 8) {
+ d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff);
+ *p = (u_char) (d - &p[1]);
+ p = d;
+ }
+
+ p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14);
}
- /* query type "PTR", IP query class */
- ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18);
+ /* query type "PTR", IN query class */
+ p = ngx_cpymem(p, "\0\14\0\1", 4);
- rn->qlen = (u_short)
- (p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t)
- - rn->query);
+ rn->qlen = (u_short) (p - rn->query);
return NGX_OK;
}
@@ -2012,7 +2744,7 @@ done:
n = *src++;
} else {
- ngx_memcpy(dst, src, n);
+ ngx_strlow(dst, src, n);
dst += n;
src += n;
@@ -2061,10 +2793,16 @@ ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
ngx_resolver_free_locked(r, rn->u.cname);
}
- if (rn->naddrs > 1) {
+ if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
ngx_resolver_free_locked(r, rn->u.addrs);
}
+#if (NGX_HAVE_INET6)
+ if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
+ ngx_resolver_free_locked(r, rn->u6.addrs6);
+ }
+#endif
+
ngx_resolver_free_locked(r, rn);
/* unlock alloc mutex */
@@ -2136,27 +2874,84 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
}
-static in_addr_t *
-ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
+static ngx_addr_t *
+ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
+ ngx_uint_t rotate)
{
- void *dst, *p;
- ngx_uint_t j;
+ ngx_addr_t *dst;
+ ngx_uint_t d, i, j, n;
+ u_char (*sockaddr)[NGX_SOCKADDRLEN];
+ in_addr_t *addr;
+ struct sockaddr_in *sin;
+#if (NGX_HAVE_INET6)
+ struct in6_addr *addr6;
+ struct sockaddr_in6 *sin6;
+#endif
- dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
+ n = rn->naddrs;
+#if (NGX_HAVE_INET6)
+ n += rn->naddrs6;
+#endif
+ dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t));
if (dst == NULL) {
- return dst;
+ return NULL;
}
- j = ngx_random() % n;
+ sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN);
+ if (sockaddr == NULL) {
+ ngx_resolver_free(r, dst);
+ return NULL;
+ }
- if (j == 0) {
- ngx_memcpy(dst, src, n * sizeof(in_addr_t));
- return dst;
+ i = 0;
+ d = rotate ? ngx_random() % n : 0;
+
+ if (rn->naddrs) {
+ j = rotate ? ngx_random() % rn->naddrs : 0;
+
+ addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;
+
+ do {
+ sin = (struct sockaddr_in *) sockaddr[d];
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = addr[j++];
+ dst[d].sockaddr = (struct sockaddr *) sin;
+ dst[d++].socklen = sizeof(struct sockaddr_in);
+
+ if (d == n) {
+ d = 0;
+ }
+
+ if (j == rn->naddrs) {
+ j = 0;
+ }
+ } while (++i < rn->naddrs);
}
- p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
- ngx_memcpy(p, src, j * sizeof(in_addr_t));
+#if (NGX_HAVE_INET6)
+ if (rn->naddrs6) {
+ j = rotate ? ngx_random() % rn->naddrs6 : 0;
+
+ addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;
+
+ do {
+ sin6 = (struct sockaddr_in6 *) sockaddr[d];
+ sin6->sin6_family = AF_INET6;
+ ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16);
+ dst[d].sockaddr = (struct sockaddr *) sin6;
+ dst[d++].socklen = sizeof(struct sockaddr_in6);
+
+ if (d == n) {
+ d = 0;
+ }
+
+ if (j == rn->naddrs6) {
+ j = 0;
+ }
+ } while (++i < n);
+ }
+#endif
return dst;
}
@@ -2221,7 +3016,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);
- if (s == -1) {
+ if (s == (ngx_socket_t) -1) {
ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
ngx_socket_n " failed");
return NGX_ERROR;
@@ -2242,14 +3037,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
ngx_nonblocking_n " failed");
- ngx_free_connection(c);
-
- if (ngx_close_socket(s) == -1) {
- ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
- ngx_close_socket_n " failed");
- }
-
- return NGX_ERROR;
+ goto failed;
}
rev = c->read;
@@ -2274,7 +3062,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
#endif
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
- "connect to %V, fd:%d #%d", &uc->server, s, c->number);
+ "connect to %V, fd:%d #%uA", &uc->server, s, c->number);
rc = connect(s, uc->sockaddr, uc->socklen);
@@ -2284,7 +3072,7 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
"connect() failed");
- return NGX_ERROR;
+ goto failed;
}
/* UDP sockets are always ready to write */
@@ -2298,16 +3086,23 @@ ngx_udp_connect(ngx_udp_connection_t *uc)
/* eventport event type has no meaning: oneshot only */
if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
- return NGX_ERROR;
+ goto failed;
}
} else {
/* rtsig */
if (ngx_add_conn(c) == NGX_ERROR) {
- return NGX_ERROR;
+ goto failed;
}
}
return NGX_OK;
+
+failed:
+
+ ngx_close_connection(c);
+ uc->connection = NULL;
+
+ return NGX_ERROR;
}
diff --git a/usr.sbin/nginx/src/core/ngx_resolver.h b/usr.sbin/nginx/src/core/ngx_resolver.h
index ae34ca56d3a..264c8c42b98 100644
--- a/usr.sbin/nginx/src/core/ngx_resolver.h
+++ b/usr.sbin/nginx/src/core/ngx_resolver.h
@@ -18,6 +18,9 @@
#define NGX_RESOLVE_PTR 12
#define NGX_RESOLVE_MX 15
#define NGX_RESOLVE_TXT 16
+#if (NGX_HAVE_INET6)
+#define NGX_RESOLVE_AAAA 28
+#endif
#define NGX_RESOLVE_DNAME 39
#define NGX_RESOLVE_FORMERR 1
@@ -54,10 +57,18 @@ typedef struct {
/* PTR: resolved name, A: name to resolve */
u_char *name;
+#if (NGX_HAVE_INET6)
+ /* PTR: IPv6 address to resolve (IPv4 address is in rbtree node key) */
+ struct in6_addr addr6;
+#endif
+
u_short nlen;
u_short qlen;
u_char *query;
+#if (NGX_HAVE_INET6)
+ u_char *query6;
+#endif
union {
in_addr_t addr;
@@ -65,11 +76,22 @@ typedef struct {
u_char *cname;
} u;
+ u_char code;
u_short naddrs;
u_short cnlen;
+#if (NGX_HAVE_INET6)
+ union {
+ struct in6_addr addr6;
+ struct in6_addr *addrs6;
+ } u6;
+
+ u_short naddrs6;
+#endif
+
time_t expire;
time_t valid;
+ uint32_t ttl;
ngx_resolver_ctx_t *waiting;
} ngx_resolver_node_t;
@@ -100,6 +122,14 @@ typedef struct {
ngx_queue_t name_expire_queue;
ngx_queue_t addr_expire_queue;
+#if (NGX_HAVE_INET6)
+ ngx_uint_t ipv6; /* unsigned ipv6:1; */
+ ngx_rbtree_t addr6_rbtree;
+ ngx_rbtree_node_t addr6_sentinel;
+ ngx_queue_t addr6_resend_queue;
+ ngx_queue_t addr6_expire_queue;
+#endif
+
time_t resend_timeout;
time_t expire;
time_t valid;
@@ -117,12 +147,12 @@ struct ngx_resolver_ctx_s {
ngx_int_t ident;
ngx_int_t state;
- ngx_int_t type;
ngx_str_t name;
ngx_uint_t naddrs;
- in_addr_t *addrs;
- in_addr_t addr;
+ ngx_addr_t *addrs;
+ ngx_addr_t addr;
+ struct sockaddr_in sin;
ngx_resolver_handler_pt handler;
void *data;
diff --git a/usr.sbin/nginx/src/core/ngx_slab.c b/usr.sbin/nginx/src/core/ngx_slab.c
index ae9d6f3fc0e..be7927ce067 100644
--- a/usr.sbin/nginx/src/core/ngx_slab.c
+++ b/usr.sbin/nginx/src/core/ngx_slab.c
@@ -129,6 +129,7 @@ ngx_slab_init(ngx_slab_pool_t *pool)
pool->pages->slab = pages;
}
+ pool->log_nomem = 1;
pool->log_ctx = &pool->zero;
pool->zero = '\0';
}
@@ -440,7 +441,8 @@ ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p)
n = ((uintptr_t) p & (ngx_pagesize - 1)) >> shift;
m = (uintptr_t) 1 << (n & (sizeof(uintptr_t) * 8 - 1));
n /= (sizeof(uintptr_t) * 8);
- bitmap = (uintptr_t *) ((uintptr_t) p & ~(ngx_pagesize - 1));
+ bitmap = (uintptr_t *)
+ ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1));
if (bitmap[n] & m) {
@@ -657,7 +659,10 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *pool, ngx_uint_t pages)
}
}
- ngx_slab_error(pool, NGX_LOG_CRIT, "ngx_slab_alloc() failed: no memory");
+ if (pool->log_nomem) {
+ ngx_slab_error(pool, NGX_LOG_CRIT,
+ "ngx_slab_alloc() failed: no memory");
+ }
return NULL;
}
diff --git a/usr.sbin/nginx/src/core/ngx_slab.h b/usr.sbin/nginx/src/core/ngx_slab.h
index c5e420bfa8e..5735e3bb3b9 100644
--- a/usr.sbin/nginx/src/core/ngx_slab.h
+++ b/usr.sbin/nginx/src/core/ngx_slab.h
@@ -39,6 +39,8 @@ typedef struct {
u_char *log_ctx;
u_char zero;
+ unsigned log_nomem:1;
+
void *data;
void *addr;
} ngx_slab_pool_t;
diff --git a/usr.sbin/nginx/src/core/ngx_string.c b/usr.sbin/nginx/src/core/ngx_string.c
index 1d1989da24d..a4cfcdc7a5e 100644
--- a/usr.sbin/nginx/src/core/ngx_string.c
+++ b/usr.sbin/nginx/src/core/ngx_string.c
@@ -11,6 +11,8 @@
static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64,
u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width);
+static void ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
+ const u_char *basis, ngx_uint_t padding);
static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
const u_char *basis);
@@ -486,7 +488,7 @@ ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero,
if (hexadecimal == 0) {
- if (ui64 <= NGX_MAX_UINT32_VALUE) {
+ if (ui64 <= (uint64_t) NGX_MAX_UINT32_VALUE) {
/*
* To divide 64-bit numbers and to find remainders
@@ -853,6 +855,46 @@ ngx_dns_strcmp(u_char *s1, u_char *s2)
ngx_int_t
+ngx_filename_cmp(u_char *s1, u_char *s2, size_t n)
+{
+ ngx_uint_t c1, c2;
+
+ while (n) {
+ c1 = (ngx_uint_t) *s1++;
+ c2 = (ngx_uint_t) *s2++;
+
+#if (NGX_HAVE_CASELESS_FILESYSTEM)
+ c1 = tolower(c1);
+ c2 = tolower(c2);
+#endif
+
+ if (c1 == c2) {
+
+ if (c1) {
+ n--;
+ continue;
+ }
+
+ return 0;
+ }
+
+ /* we need '/' to be the lowest character */
+
+ if (c1 == 0 || c2 == 0) {
+ return c1 - c2;
+ }
+
+ c1 = (c1 == '/') ? 0 : c1;
+ c2 = (c2 == '/') ? 0 : c2;
+
+ return c1 - c2;
+ }
+
+ return 0;
+}
+
+
+ngx_int_t
ngx_atoi(u_char *line, size_t n)
{
ngx_int_t value;
@@ -1060,38 +1102,61 @@ ngx_hex_dump(u_char *dst, u_char *src, size_t len)
void
ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src)
{
- u_char *d, *s;
- size_t len;
static u_char basis64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ ngx_encode_base64_internal(dst, src, basis64, 1);
+}
+
+
+void
+ngx_encode_base64url(ngx_str_t *dst, ngx_str_t *src)
+{
+ static u_char basis64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+ ngx_encode_base64_internal(dst, src, basis64, 0);
+}
+
+
+static void
+ngx_encode_base64_internal(ngx_str_t *dst, ngx_str_t *src, const u_char *basis,
+ ngx_uint_t padding)
+{
+ u_char *d, *s;
+ size_t len;
+
len = src->len;
s = src->data;
d = dst->data;
while (len > 2) {
- *d++ = basis64[(s[0] >> 2) & 0x3f];
- *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
- *d++ = basis64[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
- *d++ = basis64[s[2] & 0x3f];
+ *d++ = basis[(s[0] >> 2) & 0x3f];
+ *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
+ *d++ = basis[((s[1] & 0x0f) << 2) | (s[2] >> 6)];
+ *d++ = basis[s[2] & 0x3f];
s += 3;
len -= 3;
}
if (len) {
- *d++ = basis64[(s[0] >> 2) & 0x3f];
+ *d++ = basis[(s[0] >> 2) & 0x3f];
if (len == 1) {
- *d++ = basis64[(s[0] & 3) << 4];
- *d++ = '=';
+ *d++ = basis[(s[0] & 3) << 4];
+ if (padding) {
+ *d++ = '=';
+ }
} else {
- *d++ = basis64[((s[0] & 3) << 4) | (s[1] >> 4)];
- *d++ = basis64[(s[1] & 0x0f) << 2];
+ *d++ = basis[((s[0] & 3) << 4) | (s[1] >> 4)];
+ *d++ = basis[(s[1] & 0x0f) << 2];
}
- *d++ = '=';
+ if (padding) {
+ *d++ = '=';
+ }
}
dst->len = d - dst->data;
diff --git a/usr.sbin/nginx/src/core/ngx_string.h b/usr.sbin/nginx/src/core/ngx_string.h
index 52c6f338d89..dc0be5b5532 100644
--- a/usr.sbin/nginx/src/core/ngx_string.h
+++ b/usr.sbin/nginx/src/core/ngx_string.h
@@ -167,6 +167,7 @@ ngx_int_t ngx_rstrncmp(u_char *s1, u_char *s2, size_t n);
ngx_int_t ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n);
ngx_int_t ngx_memn2cmp(u_char *s1, u_char *s2, size_t n1, size_t n2);
ngx_int_t ngx_dns_strcmp(u_char *s1, u_char *s2);
+ngx_int_t ngx_filename_cmp(u_char *s1, u_char *s2, size_t n);
ngx_int_t ngx_atoi(u_char *line, size_t n);
ngx_int_t ngx_atofp(u_char *line, size_t n, size_t point);
@@ -182,6 +183,7 @@ u_char *ngx_hex_dump(u_char *dst, u_char *src, size_t len);
#define ngx_base64_decoded_length(len) (((len + 3) / 4) * 3)
void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
+void ngx_encode_base64url(ngx_str_t *dst, ngx_str_t *src);
ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);
ngx_int_t ngx_decode_base64url(ngx_str_t *dst, ngx_str_t *src);
diff --git a/usr.sbin/nginx/src/core/ngx_syslog.c b/usr.sbin/nginx/src/core/ngx_syslog.c
new file mode 100644
index 00000000000..7c5de38b6cb
--- /dev/null
+++ b/usr.sbin/nginx/src/core/ngx_syslog.c
@@ -0,0 +1,342 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+
+
+#define NGX_SYSLOG_MAX_STR \
+ NGX_MAX_ERROR_STR + sizeof("<255>Jan 01 00:00:00 ") - 1 \
+ + (NGX_MAXHOSTNAMELEN - 1) + 1 /* space */ \
+ + 32 /* tag */ + 2 /* colon, space */
+
+
+static char *ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer);
+static ngx_int_t ngx_syslog_init_peer(ngx_syslog_peer_t *peer);
+static void ngx_syslog_cleanup(void *data);
+
+
+static char *facilities[] = {
+ "kern", "user", "mail", "daemon", "auth", "intern", "lpr", "news", "uucp",
+ "clock", "authpriv", "ftp", "ntp", "audit", "alert", "cron", "local0",
+ "local1", "local2", "local3", "local4", "local5", "local6", "local7",
+ NULL
+};
+
+/* note 'error/warn' like in nginx.conf, not 'err/warning' */
+static char *severities[] = {
+ "emerg", "alert", "crit", "error", "warn", "notice", "info", "debug", NULL
+};
+
+static ngx_log_t ngx_syslog_dummy_log;
+static ngx_event_t ngx_syslog_dummy_event;
+
+
+char *
+ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
+{
+ peer->pool = cf->pool;
+ peer->facility = NGX_CONF_UNSET_UINT;
+ peer->severity = NGX_CONF_UNSET_UINT;
+
+ if (ngx_syslog_parse_args(cf, peer) != NGX_CONF_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (peer->server.sockaddr == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "no syslog server specified");
+ return NGX_CONF_ERROR;
+ }
+
+ if (peer->facility == NGX_CONF_UNSET_UINT) {
+ peer->facility = 23; /* local7 */
+ }
+
+ if (peer->severity == NGX_CONF_UNSET_UINT) {
+ peer->severity = 6; /* info */
+ }
+
+ if (peer->tag.data == NULL) {
+ ngx_str_set(&peer->tag, "nginx");
+ }
+
+ peer->conn.fd = (ngx_socket_t) -1;
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_syslog_parse_args(ngx_conf_t *cf, ngx_syslog_peer_t *peer)
+{
+ u_char *p, *comma, c;
+ size_t len;
+ ngx_str_t *value;
+ ngx_url_t u;
+ ngx_uint_t i;
+
+ value = cf->args->elts;
+
+ p = value[1].data + sizeof("syslog:") - 1;
+
+ for ( ;; ) {
+ comma = (u_char *) ngx_strchr(p, ',');
+
+ if (comma != NULL) {
+ len = comma - p;
+ *comma = '\0';
+
+ } else {
+ len = value[1].data + value[1].len - p;
+ }
+
+ if (ngx_strncmp(p, "server=", 7) == 0) {
+
+ if (peer->server.sockaddr != NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "duplicate syslog \"server\"");
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_memzero(&u, sizeof(ngx_url_t));
+
+ u.url.data = p + 7;
+ u.url.len = len - 7;
+ u.default_port = 514;
+
+ if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
+ if (u.err) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "%s in syslog server \"%V\"",
+ u.err, &u.url);
+ }
+
+ return NGX_CONF_ERROR;
+ }
+
+ peer->server = u.addrs[0];
+
+ } else if (ngx_strncmp(p, "facility=", 9) == 0) {
+
+ if (peer->facility != NGX_CONF_UNSET_UINT) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "duplicate syslog \"facility\"");
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; facilities[i] != NULL; i++) {
+
+ if (ngx_strcmp(p + 9, facilities[i]) == 0) {
+ peer->facility = i;
+ goto next;
+ }
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "unknown syslog facility \"%s\"", p + 9);
+ return NGX_CONF_ERROR;
+
+ } else if (ngx_strncmp(p, "severity=", 9) == 0) {
+
+ if (peer->severity != NGX_CONF_UNSET_UINT) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "duplicate syslog \"severity\"");
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; severities[i] != NULL; i++) {
+
+ if (ngx_strcmp(p + 9, severities[i]) == 0) {
+ peer->severity = i;
+ goto next;
+ }
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "unknown syslog severity \"%s\"", p + 9);
+ return NGX_CONF_ERROR;
+
+ } else if (ngx_strncmp(p, "tag=", 4) == 0) {
+
+ if (peer->tag.data != NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "duplicate syslog \"tag\"");
+ return NGX_CONF_ERROR;
+ }
+
+ /*
+ * RFC 3164: the TAG is a string of ABNF alphanumeric characters
+ * that MUST NOT exceed 32 characters.
+ */
+ if (len - 4 > 32) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "syslog tag length exceeds 32");
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 4; i < len; i++) {
+ c = ngx_tolower(p[i]);
+
+ if (c < '0' || (c > '9' && c < 'a') || c > 'z') {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "syslog \"tag\" only allows "
+ "alphanumeric characters");
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ peer->tag.data = p + 4;
+ peer->tag.len = len - 4;
+
+ } else {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "unknown syslog parameter \"%s\"", p);
+ return NGX_CONF_ERROR;
+ }
+
+ next:
+
+ if (comma == NULL) {
+ break;
+ }
+
+ p = comma + 1;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+u_char *
+ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf)
+{
+ ngx_uint_t pri;
+
+ pri = peer->facility * 8 + peer->severity;
+
+ return ngx_sprintf(buf, "<%ui>%V %V %V: ", pri, &ngx_cached_syslog_time,
+ &ngx_cycle->hostname, &peer->tag);
+}
+
+
+void
+ngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf,
+ size_t len)
+{
+ u_char *p, msg[NGX_SYSLOG_MAX_STR];
+ ngx_uint_t head_len;
+ ngx_syslog_peer_t *peer;
+
+ peer = log->wdata;
+
+ if (peer->processing) {
+ return;
+ }
+
+ peer->processing = 1;
+ peer->severity = level - 1;
+
+ p = ngx_syslog_add_header(peer, msg);
+ head_len = p - msg;
+
+ len -= NGX_LINEFEED_SIZE;
+
+ if (len > NGX_SYSLOG_MAX_STR - head_len) {
+ len = NGX_SYSLOG_MAX_STR - head_len;
+ }
+
+ p = ngx_snprintf(p, len, "%s", buf);
+
+ (void) ngx_syslog_send(peer, msg, p - msg);
+
+ peer->processing = 0;
+}
+
+
+ssize_t
+ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len)
+{
+ if (peer->conn.fd == (ngx_socket_t) -1) {
+ if (ngx_syslog_init_peer(peer) != NGX_OK) {
+ return NGX_ERROR;
+ }
+ }
+
+ if (ngx_send) {
+ return ngx_send(&peer->conn, buf, len);
+
+ } else {
+ /* event module has not yet set ngx_io */
+ return ngx_os_io.send(&peer->conn, buf, len);
+ }
+}
+
+
+static ngx_int_t
+ngx_syslog_init_peer(ngx_syslog_peer_t *peer)
+{
+ ngx_socket_t fd;
+ ngx_pool_cleanup_t *cln;
+
+ peer->conn.read = &ngx_syslog_dummy_event;
+ peer->conn.write = &ngx_syslog_dummy_event;
+ peer->conn.log = &ngx_syslog_dummy_log;
+
+ ngx_syslog_dummy_event.log = &ngx_syslog_dummy_log;
+
+ fd = ngx_socket(peer->server.sockaddr->sa_family, SOCK_DGRAM, 0);
+ if (fd == (ngx_socket_t) -1) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
+ ngx_socket_n " failed");
+ return NGX_ERROR;
+ }
+
+ if (ngx_nonblocking(fd) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
+ ngx_nonblocking_n " failed");
+ goto failed;
+ }
+
+ if (connect(fd, peer->server.sockaddr, peer->server.socklen) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
+ "connect() failed");
+ goto failed;
+ }
+
+ cln = ngx_pool_cleanup_add(peer->pool, 0);
+ if (cln == NULL) {
+ goto failed;
+ }
+
+ cln->data = peer;
+ cln->handler = ngx_syslog_cleanup;
+
+ peer->conn.fd = fd;
+ return NGX_OK;
+
+failed:
+
+ if (ngx_close_socket(fd) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+
+ return NGX_ERROR;
+}
+
+
+static void
+ngx_syslog_cleanup(void *data)
+{
+ ngx_syslog_peer_t *peer = data;
+
+ if (ngx_close_socket(peer->conn.fd) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_socket_errno,
+ ngx_close_socket_n " failed");
+ }
+}
diff --git a/usr.sbin/nginx/src/core/ngx_syslog.h b/usr.sbin/nginx/src/core/ngx_syslog.h
new file mode 100644
index 00000000000..92d47d5f5fd
--- /dev/null
+++ b/usr.sbin/nginx/src/core/ngx_syslog.h
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#ifndef _NGX_SYSLOG_H_INCLUDED_
+#define _NGX_SYSLOG_H_INCLUDED_
+
+
+typedef struct {
+ ngx_pool_t *pool;
+ ngx_uint_t facility;
+ ngx_uint_t severity;
+ ngx_str_t tag;
+
+ ngx_addr_t server;
+ ngx_connection_t conn;
+ ngx_uint_t processing; /* unsigned processing:1; */
+} ngx_syslog_peer_t;
+
+
+char *ngx_syslog_process_conf(ngx_conf_t *cf, ngx_syslog_peer_t *peer);
+u_char *ngx_syslog_add_header(ngx_syslog_peer_t *peer, u_char *buf);
+void ngx_syslog_writer(ngx_log_t *log, ngx_uint_t level, u_char *buf,
+ size_t len);
+ssize_t ngx_syslog_send(ngx_syslog_peer_t *peer, u_char *buf, size_t len);
+
+
+#endif /* _NGX_SYSLOG_H_INCLUDED_ */
diff --git a/usr.sbin/nginx/src/core/ngx_times.c b/usr.sbin/nginx/src/core/ngx_times.c
index 77490faf045..595c1224d0e 100644
--- a/usr.sbin/nginx/src/core/ngx_times.c
+++ b/usr.sbin/nginx/src/core/ngx_times.c
@@ -29,6 +29,7 @@ volatile ngx_str_t ngx_cached_err_log_time;
volatile ngx_str_t ngx_cached_http_time;
volatile ngx_str_t ngx_cached_http_log_time;
volatile ngx_str_t ngx_cached_http_log_iso8601;
+volatile ngx_str_t ngx_cached_syslog_time;
#if !(NGX_WIN32)
@@ -50,6 +51,8 @@ static u_char cached_http_log_time[NGX_TIME_SLOTS]
[sizeof("28/Sep/1970:12:00:00 +0600")];
static u_char cached_http_log_iso8601[NGX_TIME_SLOTS]
[sizeof("1970-09-28T12:00:00+06:00")];
+static u_char cached_syslog_time[NGX_TIME_SLOTS]
+ [sizeof("Sep 28 12:00:00")];
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
@@ -63,6 +66,7 @@ ngx_time_init(void)
ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1;
ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1;
ngx_cached_http_log_iso8601.len = sizeof("1970-09-28T12:00:00+06:00") - 1;
+ ngx_cached_syslog_time.len = sizeof("Sep 28 12:00:00") - 1;
ngx_cached_time = &cached_time[0];
@@ -73,7 +77,7 @@ ngx_time_init(void)
void
ngx_time_update(void)
{
- u_char *p0, *p1, *p2, *p3;
+ u_char *p0, *p1, *p2, *p3, *p4;
ngx_tm_t tm, gmt;
time_t sec;
ngx_uint_t msec;
@@ -166,6 +170,11 @@ ngx_time_update(void)
tp->gmtoff < 0 ? '-' : '+',
ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60));
+ p4 = &cached_syslog_time[slot][0];
+
+ (void) ngx_sprintf(p4, "%s %2d %02d:%02d:%02d",
+ months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday,
+ tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
ngx_memory_barrier();
@@ -174,6 +183,7 @@ ngx_time_update(void)
ngx_cached_err_log_time.data = p1;
ngx_cached_http_log_time.data = p2;
ngx_cached_http_log_iso8601.data = p3;
+ ngx_cached_syslog_time.data = p4;
ngx_unlock(&ngx_time_lock);
}
@@ -184,7 +194,7 @@ ngx_time_update(void)
void
ngx_time_sigsafe_update(void)
{
- u_char *p;
+ u_char *p, *p2;
ngx_tm_t tm;
time_t sec;
ngx_time_t *tp;
@@ -224,9 +234,16 @@ ngx_time_sigsafe_update(void)
tm.ngx_tm_mday, tm.ngx_tm_hour,
tm.ngx_tm_min, tm.ngx_tm_sec);
+ p2 = &cached_syslog_time[slot][0];
+
+ (void) ngx_sprintf(p2, "%s %2d %02d:%02d:%02d",
+ months[tm.ngx_tm_mon - 1], tm.ngx_tm_mday,
+ tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
+
ngx_memory_barrier();
ngx_cached_err_log_time.data = p;
+ ngx_cached_syslog_time.data = p2;
ngx_unlock(&ngx_time_lock);
}
diff --git a/usr.sbin/nginx/src/core/ngx_times.h b/usr.sbin/nginx/src/core/ngx_times.h
index c4b26a2ed0b..94aedcdc94c 100644
--- a/usr.sbin/nginx/src/core/ngx_times.h
+++ b/usr.sbin/nginx/src/core/ngx_times.h
@@ -40,6 +40,7 @@ extern volatile ngx_str_t ngx_cached_err_log_time;
extern volatile ngx_str_t ngx_cached_http_time;
extern volatile ngx_str_t ngx_cached_http_log_time;
extern volatile ngx_str_t ngx_cached_http_log_iso8601;
+extern volatile ngx_str_t ngx_cached_syslog_time;
/*
* milliseconds elapsed since epoch and truncated to ngx_msec_t,