summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornginx <nginx@nginx.org>2013-12-17 14:04:51 +0000
committerJon Kolb <jon@b0g.us>2013-12-17 14:04:51 +0000
commit80816f36cfa4dc95e2441e527b1ff915b105309c (patch)
tree668bc5d0a49507d89bb24a8a3473c6c3fd49fd73
parent3198fb1d6a1edd51d3be9a909e2b306d3d03aa55 (diff)
downloadnginx-80816f36cfa4dc95e2441e527b1ff915b105309c.tar.gz
Changes with nginx 1.5.8 17 Dec 2013v1.5.8
*) Feature: IPv6 support in resolver. *) Feature: the "listen" directive supports the "fastopen" parameter. Thanks to Mathew Rodley. *) Feature: SSL support in the ngx_http_uwsgi_module. Thanks to Roberto De Ioris. *) Feature: vim syntax highlighting scripts were added to contrib. Thanks to Evan Miller. *) Bugfix: a timeout might occur while reading client request body in an SSL connection using chunked transfer encoding. *) Bugfix: the "master_process" directive did not work correctly in nginx/Windows. *) Bugfix: the "setfib" parameter of the "listen" directive might not work. *) Bugfix: in the ngx_http_spdy_module.
-rw-r--r--CHANGES25
-rw-r--r--CHANGES.ru24
-rw-r--r--auto/cc/clang1
-rwxr-xr-xauto/unix12
-rw-r--r--contrib/README6
-rw-r--r--contrib/vim/ftdetect/nginx.vim4
-rw-r--r--contrib/vim/indent/nginx.vim11
-rw-r--r--contrib/vim/syntax/nginx.vim703
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_connection.c49
-rw-r--r--src/core/ngx_connection.h5
-rw-r--r--src/core/ngx_cycle.c73
-rw-r--r--src/core/ngx_inet.c73
-rw-r--r--src/core/ngx_inet.h2
-rw-r--r--src/core/ngx_resolver.c1296
-rw-r--r--src/core/ngx_resolver.h36
-rw-r--r--src/event/ngx_event_accept.c1
-rw-r--r--src/event/ngx_event_openssl.c5
-rw-r--r--src/event/ngx_event_openssl_stapling.c57
-rw-r--r--src/event/ngx_event_pipe.c24
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c26
-rw-r--r--src/http/modules/ngx_http_proxy_module.c48
-rw-r--r--src/http/modules/ngx_http_scgi_module.c2
-rw-r--r--src/http/modules/ngx_http_uwsgi_module.c206
-rw-r--r--src/http/ngx_http.c4
-rw-r--r--src/http/ngx_http_core_module.c25
-rw-r--r--src/http/ngx_http_core_module.h3
-rw-r--r--src/http/ngx_http_spdy.c2
-rw-r--r--src/http/ngx_http_upstream.c18
-rw-r--r--src/http/ngx_http_upstream.h2
-rw-r--r--src/http/ngx_http_upstream_round_robin.c40
-rw-r--r--src/http/ngx_http_variables.c12
-rw-r--r--src/mail/ngx_mail_smtp_handler.c44
33 files changed, 2357 insertions, 486 deletions
diff --git a/CHANGES b/CHANGES
index 4a7e5225d..c47a5816c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,29 @@
+Changes with nginx 1.5.8 17 Dec 2013
+
+ *) Feature: IPv6 support in resolver.
+
+ *) Feature: the "listen" directive supports the "fastopen" parameter.
+ Thanks to Mathew Rodley.
+
+ *) Feature: SSL support in the ngx_http_uwsgi_module.
+ Thanks to Roberto De Ioris.
+
+ *) Feature: vim syntax highlighting scripts were added to contrib.
+ Thanks to Evan Miller.
+
+ *) Bugfix: a timeout might occur while reading client request body in an
+ SSL connection using chunked transfer encoding.
+
+ *) Bugfix: the "master_process" directive did not work correctly in
+ nginx/Windows.
+
+ *) Bugfix: the "setfib" parameter of the "listen" directive might not
+ work.
+
+ *) Bugfix: in the ngx_http_spdy_module.
+
+
Changes with nginx 1.5.7 19 Nov 2013
*) Security: a character following an unescaped space in a request line
diff --git a/CHANGES.ru b/CHANGES.ru
index 3d73b0d3e..f50fd2aeb 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,28 @@
+Изменения в nginx 1.5.8 17.12.2013
+
+ *) Добавление: теперь resolver поддерживает IPv6.
+
+ *) Добавление: директива listen поддерживает параметр fastopen.
+ Спасибо Mathew Rodley.
+
+ *) Добавление: поддержка SSL в модуле ngx_http_uwsgi_module.
+ Спасибо Roberto De Ioris.
+
+ *) Добавление: скрипты подсветки синтаксиса для vim добавлены в contrib.
+ Спасибо Evan Miller.
+
+ *) Исправление: при чтении тела запроса с использованием chunked
+ transfer encoding по SSL-соединению мог произойти таймаут.
+
+ *) Исправление: директива master_process работала неправильно в
+ nginx/Windows.
+
+ *) Исправление: параметр setfib директивы listen мог не работать.
+
+ *) Исправление: в модуле ngx_http_spdy_module.
+
+
Изменения в nginx 1.5.7 19.11.2013
*) Безопасность: символ, следующий за незакодированным пробелом в строке
diff --git a/auto/cc/clang b/auto/cc/clang
index 2611caa65..0cca3442e 100644
--- a/auto/cc/clang
+++ b/auto/cc/clang
@@ -82,6 +82,7 @@ fi
# warnings
CFLAGS="$CFLAGS $NGX_CLANG_OPT -Wall -Wextra -Wpointer-arith"
+CFLAGS="$CFLAGS -Wconditional-uninitialized"
#CFLAGS="$CFLAGS -Wmissing-prototypes"
# we have a lot of unused function arguments
diff --git a/auto/unix b/auto/unix
index 4dbdbe0c0..10fd3d293 100755
--- a/auto/unix
+++ b/auto/unix
@@ -344,6 +344,18 @@ ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_KEEPIDLE, NULL, 0);
. auto/feature
+ngx_feature="TCP_FASTOPEN"
+ngx_feature_name="NGX_HAVE_TCP_FASTOPEN"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="setsockopt(0, IPPROTO_TCP, TCP_FASTOPEN, NULL, 0)"
+. auto/feature
+
+
ngx_feature="TCP_INFO"
ngx_feature_name="NGX_HAVE_TCP_INFO"
ngx_feature_run=no
diff --git a/contrib/README b/contrib/README
index 094aa52cd..fec4b2008 100644
--- a/contrib/README
+++ b/contrib/README
@@ -13,3 +13,9 @@ unicode2nginx by Maxim Dounin
configuration file format.
Two generated full maps for windows-1251 and koi8-r.
+
+vim by Evan Miller
+
+ Syntax highlighting of nginx configuration for vim, to be
+ placed into ~/.vim/.
+
diff --git a/contrib/vim/ftdetect/nginx.vim b/contrib/vim/ftdetect/nginx.vim
new file mode 100644
index 000000000..3ae470d24
--- /dev/null
+++ b/contrib/vim/ftdetect/nginx.vim
@@ -0,0 +1,4 @@
+au BufRead,BufNewFile *.nginx set ft=nginx
+au BufRead,BufNewFile */etc/nginx/* set ft=nginx
+au BufRead,BufNewFile */usr/local/nginx/conf/* set ft=nginx
+au BufRead,BufNewFile nginx.conf set ft=nginx
diff --git a/contrib/vim/indent/nginx.vim b/contrib/vim/indent/nginx.vim
new file mode 100644
index 000000000..860136685
--- /dev/null
+++ b/contrib/vim/indent/nginx.vim
@@ -0,0 +1,11 @@
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+setlocal indentexpr=
+
+" cindent actually works for nginx' simple file structure
+setlocal cindent
+" Just make sure that the comments are not reset as defs would be.
+setlocal cinkeys-=0#
diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim
new file mode 100644
index 000000000..50d809bc4
--- /dev/null
+++ b/contrib/vim/syntax/nginx.vim
@@ -0,0 +1,703 @@
+" Vim syntax file
+" Language: nginx.conf
+
+if exists("b:current_syntax")
+ finish
+end
+
+setlocal iskeyword+=.
+setlocal iskeyword+=/
+setlocal iskeyword+=:
+
+syn match ngxVariable '\$\(\w\+\|{\w\+}\)'
+syn match ngxVariableBlock '\$\(\w\+\|{\w\+}\)' contained
+syn match ngxVariableString '\$\(\w\+\|{\w\+}\)' contained
+syn region ngxBlock start=+^+ end=+{+ skip=+\${+ contains=ngxComment,ngxDirectiveBlock,ngxVariableBlock,ngxString oneline
+syn region ngxString start=+\z(["']\)+ end=+\z1+ skip=+\\\\\|\\\z1+ contains=ngxVariableString
+syn match ngxComment ' *#.*$'
+
+syn keyword ngxBoolean on
+syn keyword ngxBoolean off
+
+syn keyword ngxDirectiveBlock http contained
+syn keyword ngxDirectiveBlock mail contained
+syn keyword ngxDirectiveBlock events contained
+syn keyword ngxDirectiveBlock server contained
+syn keyword ngxDirectiveBlock types contained
+syn keyword ngxDirectiveBlock location contained
+syn keyword ngxDirectiveBlock upstream contained
+syn keyword ngxDirectiveBlock charset_map contained
+syn keyword ngxDirectiveBlock limit_except contained
+syn keyword ngxDirectiveBlock if contained
+syn keyword ngxDirectiveBlock geo contained
+syn keyword ngxDirectiveBlock map contained
+
+syn keyword ngxDirectiveImportant include
+syn keyword ngxDirectiveImportant root
+syn keyword ngxDirectiveImportant server
+syn keyword ngxDirectiveImportant server_name
+syn keyword ngxDirectiveImportant listen
+syn keyword ngxDirectiveImportant internal
+syn keyword ngxDirectiveImportant proxy_pass
+syn keyword ngxDirectiveImportant memcached_pass
+syn keyword ngxDirectiveImportant fastcgi_pass
+syn keyword ngxDirectiveImportant try_files
+
+syn keyword ngxDirectiveControl break
+syn keyword ngxDirectiveControl return
+syn keyword ngxDirectiveControl rewrite
+syn keyword ngxDirectiveControl set
+
+syn keyword ngxDirectiveError error_page
+syn keyword ngxDirectiveError post_action
+
+syn keyword ngxDirectiveDeprecated connections
+syn keyword ngxDirectiveDeprecated imap
+syn keyword ngxDirectiveDeprecated open_file_cache_retest
+syn keyword ngxDirectiveDeprecated optimize_server_names
+syn keyword ngxDirectiveDeprecated satisfy_any
+
+syn keyword ngxDirective accept_mutex
+syn keyword ngxDirective accept_mutex_delay
+syn keyword ngxDirective access_log
+syn keyword ngxDirective add_after_body
+syn keyword ngxDirective add_before_body
+syn keyword ngxDirective add_header
+syn keyword ngxDirective addition_types
+syn keyword ngxDirective aio
+syn keyword ngxDirective alias
+syn keyword ngxDirective allow
+syn keyword ngxDirective ancient_browser
+syn keyword ngxDirective ancient_browser_value
+syn keyword ngxDirective auth_basic
+syn keyword ngxDirective auth_basic_user_file
+syn keyword ngxDirective auth_http
+syn keyword ngxDirective auth_http_header
+syn keyword ngxDirective auth_http_timeout
+syn keyword ngxDirective autoindex
+syn keyword ngxDirective autoindex_exact_size
+syn keyword ngxDirective autoindex_localtime
+syn keyword ngxDirective charset
+syn keyword ngxDirective charset_types
+syn keyword ngxDirective client_body_buffer_size
+syn keyword ngxDirective client_body_in_file_only
+syn keyword ngxDirective client_body_in_single_buffer
+syn keyword ngxDirective client_body_temp_path
+syn keyword ngxDirective client_body_timeout
+syn keyword ngxDirective client_header_buffer_size
+syn keyword ngxDirective client_header_timeout
+syn keyword ngxDirective client_max_body_size
+syn keyword ngxDirective connection_pool_size
+syn keyword ngxDirective create_full_put_path
+syn keyword ngxDirective daemon
+syn keyword ngxDirective dav_access
+syn keyword ngxDirective dav_methods
+syn keyword ngxDirective debug_connection
+syn keyword ngxDirective debug_points
+syn keyword ngxDirective default_type
+syn keyword ngxDirective degradation
+syn keyword ngxDirective degrade
+syn keyword ngxDirective deny
+syn keyword ngxDirective devpoll_changes
+syn keyword ngxDirective devpoll_events
+syn keyword ngxDirective directio
+syn keyword ngxDirective directio_alignment
+syn keyword ngxDirective empty_gif
+syn keyword ngxDirective env
+syn keyword ngxDirective epoll_events
+syn keyword ngxDirective error_log
+syn keyword ngxDirective eventport_events
+syn keyword ngxDirective expires
+syn keyword ngxDirective fastcgi_bind
+syn keyword ngxDirective fastcgi_buffer_size
+syn keyword ngxDirective fastcgi_buffers
+syn keyword ngxDirective fastcgi_busy_buffers_size
+syn keyword ngxDirective fastcgi_cache
+syn keyword ngxDirective fastcgi_cache_key
+syn keyword ngxDirective fastcgi_cache_methods
+syn keyword ngxDirective fastcgi_cache_min_uses
+syn keyword ngxDirective fastcgi_cache_path
+syn keyword ngxDirective fastcgi_cache_use_stale
+syn keyword ngxDirective fastcgi_cache_valid
+syn keyword ngxDirective fastcgi_catch_stderr
+syn keyword ngxDirective fastcgi_connect_timeout
+syn keyword ngxDirective fastcgi_hide_header
+syn keyword ngxDirective fastcgi_ignore_client_abort
+syn keyword ngxDirective fastcgi_ignore_headers
+syn keyword ngxDirective fastcgi_index
+syn keyword ngxDirective fastcgi_intercept_errors
+syn keyword ngxDirective fastcgi_max_temp_file_size
+syn keyword ngxDirective fastcgi_next_upstream
+syn keyword ngxDirective fastcgi_param
+syn keyword ngxDirective fastcgi_pass_header
+syn keyword ngxDirective fastcgi_pass_request_body
+syn keyword ngxDirective fastcgi_pass_request_headers
+syn keyword ngxDirective fastcgi_read_timeout
+syn keyword ngxDirective fastcgi_send_lowat
+syn keyword ngxDirective fastcgi_send_timeout
+syn keyword ngxDirective fastcgi_split_path_info
+syn keyword ngxDirective fastcgi_store
+syn keyword ngxDirective fastcgi_store_access
+syn keyword ngxDirective fastcgi_temp_file_write_size
+syn keyword ngxDirective fastcgi_temp_path
+syn keyword ngxDirective fastcgi_upstream_fail_timeout
+syn keyword ngxDirective fastcgi_upstream_max_fails
+syn keyword ngxDirective flv
+syn keyword ngxDirective geoip_city
+syn keyword ngxDirective geoip_country
+syn keyword ngxDirective google_perftools_profiles
+syn keyword ngxDirective gzip
+syn keyword ngxDirective gzip_buffers
+syn keyword ngxDirective gzip_comp_level
+syn keyword ngxDirective gzip_disable
+syn keyword ngxDirective gzip_hash
+syn keyword ngxDirective gzip_http_version
+syn keyword ngxDirective gzip_min_length
+syn keyword ngxDirective gzip_no_buffer
+syn keyword ngxDirective gzip_proxied
+syn keyword ngxDirective gzip_static
+syn keyword ngxDirective gzip_types
+syn keyword ngxDirective gzip_vary
+syn keyword ngxDirective gzip_window
+syn keyword ngxDirective if_modified_since
+syn keyword ngxDirective ignore_invalid_headers
+syn keyword ngxDirective image_filter
+syn keyword ngxDirective image_filter_buffer
+syn keyword ngxDirective image_filter_jpeg_quality
+syn keyword ngxDirective image_filter_transparency
+syn keyword ngxDirective imap_auth
+syn keyword ngxDirective imap_capabilities
+syn keyword ngxDirective imap_client_buffer
+syn keyword ngxDirective index
+syn keyword ngxDirective ip_hash
+syn keyword ngxDirective keepalive_requests
+syn keyword ngxDirective keepalive_timeout
+syn keyword ngxDirective kqueue_changes
+syn keyword ngxDirective kqueue_events
+syn keyword ngxDirective large_client_header_buffers
+syn keyword ngxDirective limit_conn
+syn keyword ngxDirective limit_conn_log_level
+syn keyword ngxDirective limit_rate
+syn keyword ngxDirective limit_rate_after
+syn keyword ngxDirective limit_req
+syn keyword ngxDirective limit_req_log_level
+syn keyword ngxDirective limit_req_zone
+syn keyword ngxDirective limit_zone
+syn keyword ngxDirective lingering_time
+syn keyword ngxDirective lingering_timeout
+syn keyword ngxDirective lock_file
+syn keyword ngxDirective log_format
+syn keyword ngxDirective log_not_found
+syn keyword ngxDirective log_subrequest
+syn keyword ngxDirective map_hash_bucket_size
+syn keyword ngxDirective map_hash_max_size
+syn keyword ngxDirective master_process
+syn keyword ngxDirective memcached_bind
+syn keyword ngxDirective memcached_buffer_size
+syn keyword ngxDirective memcached_connect_timeout
+syn keyword ngxDirective memcached_next_upstream
+syn keyword ngxDirective memcached_read_timeout
+syn keyword ngxDirective memcached_send_timeout
+syn keyword ngxDirective memcached_upstream_fail_timeout
+syn keyword ngxDirective memcached_upstream_max_fails
+syn keyword ngxDirective merge_slashes
+syn keyword ngxDirective min_delete_depth
+syn keyword ngxDirective modern_browser
+syn keyword ngxDirective modern_browser_value
+syn keyword ngxDirective msie_padding
+syn keyword ngxDirective msie_refresh
+syn keyword ngxDirective multi_accept
+syn keyword ngxDirective open_file_cache
+syn keyword ngxDirective open_file_cache_errors
+syn keyword ngxDirective open_file_cache_events
+syn keyword ngxDirective open_file_cache_min_uses
+syn keyword ngxDirective open_file_cache_valid
+syn keyword ngxDirective open_log_file_cache
+syn keyword ngxDirective output_buffers
+syn keyword ngxDirective override_charset
+syn keyword ngxDirective perl
+syn keyword ngxDirective perl_modules
+syn keyword ngxDirective perl_require
+syn keyword ngxDirective perl_set
+syn keyword ngxDirective pid
+syn keyword ngxDirective pop3_auth
+syn keyword ngxDirective pop3_capabilities
+syn keyword ngxDirective port_in_redirect
+syn keyword ngxDirective postpone_gzipping
+syn keyword ngxDirective postpone_output
+syn keyword ngxDirective protocol
+syn keyword ngxDirective proxy
+syn keyword ngxDirective proxy_bind
+syn keyword ngxDirective proxy_buffer
+syn keyword ngxDirective proxy_buffer_size
+syn keyword ngxDirective proxy_buffering
+syn keyword ngxDirective proxy_buffers
+syn keyword ngxDirective proxy_busy_buffers_size
+syn keyword ngxDirective proxy_cache
+syn keyword ngxDirective proxy_cache_key
+syn keyword ngxDirective proxy_cache_methods
+syn keyword ngxDirective proxy_cache_min_uses
+syn keyword ngxDirective proxy_cache_path
+syn keyword ngxDirective proxy_cache_use_stale
+syn keyword ngxDirective proxy_cache_valid
+syn keyword ngxDirective proxy_connect_timeout
+syn keyword ngxDirective proxy_headers_hash_bucket_size
+syn keyword ngxDirective proxy_headers_hash_max_size
+syn keyword ngxDirective proxy_hide_header
+syn keyword ngxDirective proxy_ignore_client_abort
+syn keyword ngxDirective proxy_ignore_headers
+syn keyword ngxDirective proxy_intercept_errors
+syn keyword ngxDirective proxy_max_temp_file_size
+syn keyword ngxDirective proxy_method
+syn keyword ngxDirective proxy_next_upstream
+syn keyword ngxDirective proxy_pass_error_message
+syn keyword ngxDirective proxy_pass_header
+syn keyword ngxDirective proxy_pass_request_body
+syn keyword ngxDirective proxy_pass_request_headers
+syn keyword ngxDirective proxy_read_timeout
+syn keyword ngxDirective proxy_redirect
+syn keyword ngxDirective proxy_send_lowat
+syn keyword ngxDirective proxy_send_timeout
+syn keyword ngxDirective proxy_set_body
+syn keyword ngxDirective proxy_set_header
+syn keyword ngxDirective proxy_ssl_session_reuse
+syn keyword ngxDirective proxy_store
+syn keyword ngxDirective proxy_store_access
+syn keyword ngxDirective proxy_temp_file_write_size
+syn keyword ngxDirective proxy_temp_path
+syn keyword ngxDirective proxy_timeout
+syn keyword ngxDirective proxy_upstream_fail_timeout
+syn keyword ngxDirective proxy_upstream_max_fails
+syn keyword ngxDirective random_index
+syn keyword ngxDirective read_ahead
+syn keyword ngxDirective real_ip_header
+syn keyword ngxDirective recursive_error_pages
+syn keyword ngxDirective request_pool_size
+syn keyword ngxDirective reset_timedout_connection
+syn keyword ngxDirective resolver
+syn keyword ngxDirective resolver_timeout
+syn keyword ngxDirective rewrite_log
+syn keyword ngxDirective rtsig_overflow_events
+syn keyword ngxDirective rtsig_overflow_test
+syn keyword ngxDirective rtsig_overflow_threshold
+syn keyword ngxDirective rtsig_signo
+syn keyword ngxDirective satisfy
+syn keyword ngxDirective secure_link_secret
+syn keyword ngxDirective send_lowat
+syn keyword ngxDirective send_timeout
+syn keyword ngxDirective sendfile
+syn keyword ngxDirective sendfile_max_chunk
+syn keyword ngxDirective server_name_in_redirect
+syn keyword ngxDirective server_names_hash_bucket_size
+syn keyword ngxDirective server_names_hash_max_size
+syn keyword ngxDirective server_tokens
+syn keyword ngxDirective set_real_ip_from
+syn keyword ngxDirective smtp_auth
+syn keyword ngxDirective smtp_capabilities
+syn keyword ngxDirective smtp_client_buffer
+syn keyword ngxDirective smtp_greeting_delay
+syn keyword ngxDirective so_keepalive
+syn keyword ngxDirective source_charset
+syn keyword ngxDirective ssi
+syn keyword ngxDirective ssi_ignore_recycled_buffers
+syn keyword ngxDirective ssi_min_file_chunk
+syn keyword ngxDirective ssi_silent_errors
+syn keyword ngxDirective ssi_types
+syn keyword ngxDirective ssi_value_length
+syn keyword ngxDirective ssl
+syn keyword ngxDirective ssl_certificate
+syn keyword ngxDirective ssl_certificate_key
+syn keyword ngxDirective ssl_ciphers
+syn keyword ngxDirective ssl_client_certificate
+syn keyword ngxDirective ssl_crl
+syn keyword ngxDirective ssl_dhparam
+syn keyword ngxDirective ssl_engine
+syn keyword ngxDirective ssl_prefer_server_ciphers
+syn keyword ngxDirective ssl_protocols
+syn keyword ngxDirective ssl_session_cache
+syn keyword ngxDirective ssl_session_timeout
+syn keyword ngxDirective ssl_verify_client
+syn keyword ngxDirective ssl_verify_depth
+syn keyword ngxDirective starttls
+syn keyword ngxDirective stub_status
+syn keyword ngxDirective sub_filter
+syn keyword ngxDirective sub_filter_once
+syn keyword ngxDirective sub_filter_types
+syn keyword ngxDirective tcp_nodelay
+syn keyword ngxDirective tcp_nopush
+syn keyword ngxDirective thread_stack_size
+syn keyword ngxDirective timeout
+syn keyword ngxDirective timer_resolution
+syn keyword ngxDirective types_hash_bucket_size
+syn keyword ngxDirective types_hash_max_size
+syn keyword ngxDirective underscores_in_headers
+syn keyword ngxDirective uninitialized_variable_warn
+syn keyword ngxDirective use
+syn keyword ngxDirective user
+syn keyword ngxDirective userid
+syn keyword ngxDirective userid_domain
+syn keyword ngxDirective userid_expires
+syn keyword ngxDirective userid_mark
+syn keyword ngxDirective userid_name
+syn keyword ngxDirective userid_p3p
+syn keyword ngxDirective userid_path
+syn keyword ngxDirective userid_service
+syn keyword ngxDirective valid_referers
+syn keyword ngxDirective variables_hash_bucket_size
+syn keyword ngxDirective variables_hash_max_size
+syn keyword ngxDirective worker_connections
+syn keyword ngxDirective worker_cpu_affinity
+syn keyword ngxDirective worker_priority
+syn keyword ngxDirective worker_processes
+syn keyword ngxDirective worker_rlimit_core
+syn keyword ngxDirective worker_rlimit_nofile
+syn keyword ngxDirective worker_rlimit_sigpending
+syn keyword ngxDirective worker_threads
+syn keyword ngxDirective working_directory
+syn keyword ngxDirective xclient
+syn keyword ngxDirective xml_entities
+syn keyword ngxDirective xslt_stylesheet
+syn keyword ngxDirective xslt_types
+
+" 3rd party module list:
+" http://wiki.nginx.org/Nginx3rdPartyModules
+
+" Accept Language Module <http://wiki.nginx.org/NginxAcceptLanguageModule>
+" Parses the Accept-Language header and gives the most suitable locale from a list of supported locales.
+syn keyword ngxDirectiveThirdParty set_from_accept_language
+
+" Access Key Module <http://wiki.nginx.org/NginxHttpAccessKeyModule>
+" Denies access unless the request URL contains an access key.
+syn keyword ngxDirectiveThirdParty accesskey
+syn keyword ngxDirectiveThirdParty accesskey_arg
+syn keyword ngxDirectiveThirdParty accesskey_hashmethod
+syn keyword ngxDirectiveThirdParty accesskey_signature
+
+" Auth PAM Module <http://web.iti.upv.es/~sto/nginx/>
+" HTTP Basic Authentication using PAM.
+syn keyword ngxDirectiveThirdParty auth_pam
+syn keyword ngxDirectiveThirdParty auth_pam_service_name
+
+" Cache Purge Module <http://labs.frickle.com/nginx_ngx_cache_purge/>
+" Module adding ability to purge content from FastCGI and proxy caches.
+syn keyword ngxDirectiveThirdParty fastcgi_cache_purge
+syn keyword ngxDirectiveThirdParty proxy_cache_purge
+
+" Chunkin Module <http://wiki.nginx.org/NginxHttpChunkinModule>
+" HTTP 1.1 chunked-encoding request body support for Nginx.
+syn keyword ngxDirectiveThirdParty chunkin
+syn keyword ngxDirectiveThirdParty chunkin_keepalive
+syn keyword ngxDirectiveThirdParty chunkin_max_chunks_per_buf
+syn keyword ngxDirectiveThirdParty chunkin_resume
+
+" Circle GIF Module <http://wiki.nginx.org/NginxHttpCircleGifModule>
+" Generates simple circle images with the colors and size specified in the URL.
+syn keyword ngxDirectiveThirdParty circle_gif
+syn keyword ngxDirectiveThirdParty circle_gif_max_radius
+syn keyword ngxDirectiveThirdParty circle_gif_min_radius
+syn keyword ngxDirectiveThirdParty circle_gif_step_radius
+
+" Drizzle Module <http://github.com/chaoslawful/drizzle-nginx-module>
+" Make nginx talk directly to mysql, drizzle, and sqlite3 by libdrizzle.
+syn keyword ngxDirectiveThirdParty drizzle_connect_timeout
+syn keyword ngxDirectiveThirdParty drizzle_dbname
+syn keyword ngxDirectiveThirdParty drizzle_keepalive
+syn keyword ngxDirectiveThirdParty drizzle_module_header
+syn keyword ngxDirectiveThirdParty drizzle_pass
+syn keyword ngxDirectiveThirdParty drizzle_query
+syn keyword ngxDirectiveThirdParty drizzle_recv_cols_timeout
+syn keyword ngxDirectiveThirdParty drizzle_recv_rows_timeout
+syn keyword ngxDirectiveThirdParty drizzle_send_query_timeout
+syn keyword ngxDirectiveThirdParty drizzle_server
+
+" Echo Module <http://wiki.nginx.org/NginxHttpEchoModule>
+" Brings 'echo', 'sleep', 'time', 'exec' and more shell-style goodies to Nginx config file.
+syn keyword ngxDirectiveThirdParty echo
+syn keyword ngxDirectiveThirdParty echo_after_body
+syn keyword ngxDirectiveThirdParty echo_before_body
+syn keyword ngxDirectiveThirdParty echo_blocking_sleep
+syn keyword ngxDirectiveThirdParty echo_duplicate
+syn keyword ngxDirectiveThirdParty echo_end
+syn keyword ngxDirectiveThirdParty echo_exec
+syn keyword ngxDirectiveThirdParty echo_flush
+syn keyword ngxDirectiveThirdParty echo_foreach_split
+syn keyword ngxDirectiveThirdParty echo_location
+syn keyword ngxDirectiveThirdParty echo_location_async
+syn keyword ngxDirectiveThirdParty echo_read_request_body
+syn keyword ngxDirectiveThirdParty echo_request_body
+syn keyword ngxDirectiveThirdParty echo_reset_timer
+syn keyword ngxDirectiveThirdParty echo_sleep
+syn keyword ngxDirectiveThirdParty echo_subrequest
+syn keyword ngxDirectiveThirdParty echo_subrequest_async
+
+" Events Module <http://docs.dutov.org/nginx_modules_events_en.html>
+" Privides options for start/stop events.
+syn keyword ngxDirectiveThirdParty on_start
+syn keyword ngxDirectiveThirdParty on_stop
+
+" EY Balancer Module <http://github.com/ry/nginx-ey-balancer>
+" Adds a request queue to Nginx that allows the limiting of concurrent requests passed to the upstream.
+syn keyword ngxDirectiveThirdParty max_connections
+syn keyword ngxDirectiveThirdParty max_connections_max_queue_length
+syn keyword ngxDirectiveThirdParty max_connections_queue_timeout
+
+" Fancy Indexes Module <https://connectical.com/projects/ngx-fancyindex/wiki>
+" Like the built-in autoindex module, but fancier.
+syn keyword ngxDirectiveThirdParty fancyindex
+syn keyword ngxDirectiveThirdParty fancyindex_exact_size
+syn keyword ngxDirectiveThirdParty fancyindex_footer
+syn keyword ngxDirectiveThirdParty fancyindex_header
+syn keyword ngxDirectiveThirdParty fancyindex_localtime
+syn keyword ngxDirectiveThirdParty fancyindex_readme
+syn keyword ngxDirectiveThirdParty fancyindex_readme_mode
+
+" GeoIP Module (DEPRECATED) <http://wiki.nginx.org/NginxHttp3rdPartyGeoIPModule>
+" Country code lookups via the MaxMind GeoIP API.
+syn keyword ngxDirectiveThirdParty geoip_country_file
+
+" Headers More Module <http://wiki.nginx.org/NginxHttpHeadersMoreModule>
+" Set and clear input and output headers...more than "add"!
+syn keyword ngxDirectiveThirdParty more_clear_headers
+syn keyword ngxDirectiveThirdParty more_clear_input_headers
+syn keyword ngxDirectiveThirdParty more_set_headers
+syn keyword ngxDirectiveThirdParty more_set_input_headers
+
+" HTTP Push Module <http://pushmodule.slact.net/>
+" Turn Nginx into an adept long-polling HTTP Push (Comet) server.
+syn keyword ngxDirectiveThirdParty push_buffer_size
+syn keyword ngxDirectiveThirdParty push_listener
+syn keyword ngxDirectiveThirdParty push_message_timeout
+syn keyword ngxDirectiveThirdParty push_queue_messages
+syn keyword ngxDirectiveThirdParty push_sender
+
+" HTTP Redis Module <http://people.FreeBSD.ORG/~osa/ngx_http_redis-0.3.1.tar.gz>>
+" Redis <http://code.google.com/p/redis/> support.>
+syn keyword ngxDirectiveThirdParty redis_bind
+syn keyword ngxDirectiveThirdParty redis_buffer_size
+syn keyword ngxDirectiveThirdParty redis_connect_timeout
+syn keyword ngxDirectiveThirdParty redis_next_upstream
+syn keyword ngxDirectiveThirdParty redis_pass
+syn keyword ngxDirectiveThirdParty redis_read_timeout
+syn keyword ngxDirectiveThirdParty redis_send_timeout
+
+" HTTP JavaScript Module <http://wiki.github.com/kung-fu-tzu/ngx_http_js_module>
+" Embedding SpiderMonkey. Nearly full port on Perl module.
+syn keyword ngxDirectiveThirdParty js
+syn keyword ngxDirectiveThirdParty js_filter
+syn keyword ngxDirectiveThirdParty js_filter_types
+syn keyword ngxDirectiveThirdParty js_load
+syn keyword ngxDirectiveThirdParty js_maxmem
+syn keyword ngxDirectiveThirdParty js_require
+syn keyword ngxDirectiveThirdParty js_set
+syn keyword ngxDirectiveThirdParty js_utf8
+
+" Log Request Speed <http://wiki.nginx.org/NginxHttpLogRequestSpeed>
+" Log the time it took to process each request.
+syn keyword ngxDirectiveThirdParty log_request_speed_filter
+syn keyword ngxDirectiveThirdParty log_request_speed_filter_timeout
+
+" Memc Module <http://wiki.nginx.org/NginxHttpMemcModule>
+" An extended version of the standard memcached module that supports set, add, delete, and many more memcached commands.
+syn keyword ngxDirectiveThirdParty memc_buffer_size
+syn keyword ngxDirectiveThirdParty memc_cmds_allowed
+syn keyword ngxDirectiveThirdParty memc_connect_timeout
+syn keyword ngxDirectiveThirdParty memc_flags_to_last_modified
+syn keyword ngxDirectiveThirdParty memc_next_upstream
+syn keyword ngxDirectiveThirdParty memc_pass
+syn keyword ngxDirectiveThirdParty memc_read_timeout
+syn keyword ngxDirectiveThirdParty memc_send_timeout
+syn keyword ngxDirectiveThirdParty memc_upstream_fail_timeout
+syn keyword ngxDirectiveThirdParty memc_upstream_max_fails
+
+" Mogilefs Module <http://www.grid.net.ru/nginx/mogilefs.en.html>
+" Implements a MogileFS client, provides a replace to the Perlbal reverse proxy of the original MogileFS.
+syn keyword ngxDirectiveThirdParty mogilefs_connect_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_domain
+syn keyword ngxDirectiveThirdParty mogilefs_methods
+syn keyword ngxDirectiveThirdParty mogilefs_noverify
+syn keyword ngxDirectiveThirdParty mogilefs_pass
+syn keyword ngxDirectiveThirdParty mogilefs_read_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_send_timeout
+syn keyword ngxDirectiveThirdParty mogilefs_tracker
+
+" MP4 Streaming Lite Module <http://wiki.nginx.org/NginxMP4StreamingLite>
+" Will seek to a certain time within H.264/MP4 files when provided with a 'start' parameter in the URL.
+syn keyword ngxDirectiveThirdParty mp4
+
+" Nginx Notice Module <http://xph.us/software/nginx-notice/>
+" Serve static file to POST requests.
+syn keyword ngxDirectiveThirdParty notice
+syn keyword ngxDirectiveThirdParty notice_type
+
+" Phusion Passenger <http://www.modrails.com/documentation.html>
+" Easy and robust deployment of Ruby on Rails application on Apache and Nginx webservers.
+syn keyword ngxDirectiveThirdParty passenger_base_uri
+syn keyword ngxDirectiveThirdParty passenger_default_user
+syn keyword ngxDirectiveThirdParty passenger_enabled
+syn keyword ngxDirectiveThirdParty passenger_log_level
+syn keyword ngxDirectiveThirdParty passenger_max_instances_per_app
+syn keyword ngxDirectiveThirdParty passenger_max_pool_size
+syn keyword ngxDirectiveThirdParty passenger_pool_idle_time
+syn keyword ngxDirectiveThirdParty passenger_root
+syn keyword ngxDirectiveThirdParty passenger_ruby
+syn keyword ngxDirectiveThirdParty passenger_use_global_queue
+syn keyword ngxDirectiveThirdParty passenger_user_switching
+syn keyword ngxDirectiveThirdParty rack_env
+syn keyword ngxDirectiveThirdParty rails_app_spawner_idle_time
+syn keyword ngxDirectiveThirdParty rails_env
+syn keyword ngxDirectiveThirdParty rails_framework_spawner_idle_time
+syn keyword ngxDirectiveThirdParty rails_spawn_method
+
+" RDS JSON Module <http://github.com/agentzh/rds-json-nginx-module>
+" Help ngx_drizzle and other DBD modules emit JSON data.
+syn keyword ngxDirectiveThirdParty rds_json
+syn keyword ngxDirectiveThirdParty rds_json_content_type
+syn keyword ngxDirectiveThirdParty rds_json_format
+syn keyword ngxDirectiveThirdParty rds_json_ret
+
+" RRD Graph Module <http://wiki.nginx.org/NginxNgx_rrd_graph>
+" This module provides an HTTP interface to RRDtool's graphing facilities.
+syn keyword ngxDirectiveThirdParty rrd_graph
+syn keyword ngxDirectiveThirdParty rrd_graph_root
+
+" Secure Download <http://wiki.nginx.org/NginxHttpSecureDownload>
+" Create expiring links.
+syn keyword ngxDirectiveThirdParty secure_download
+syn keyword ngxDirectiveThirdParty secure_download_fail_location
+syn keyword ngxDirectiveThirdParty secure_download_path_mode
+syn keyword ngxDirectiveThirdParty secure_download_secret
+
+" SlowFS Cache Module <http://labs.frickle.com/nginx_ngx_slowfs_cache/>
+" Module adding ability to cache static files.
+syn keyword ngxDirectiveThirdParty slowfs_big_file_size
+syn keyword ngxDirectiveThirdParty slowfs_cache
+syn keyword ngxDirectiveThirdParty slowfs_cache_key
+syn keyword ngxDirectiveThirdParty slowfs_cache_min_uses
+syn keyword ngxDirectiveThirdParty slowfs_cache_path
+syn keyword ngxDirectiveThirdParty slowfs_cache_purge
+syn keyword ngxDirectiveThirdParty slowfs_cache_valid
+syn keyword ngxDirectiveThirdParty slowfs_temp_path
+
+" Strip Module <http://wiki.nginx.org/NginxHttpStripModule>
+" Whitespace remover.
+syn keyword ngxDirectiveThirdParty strip
+
+" Substitutions Module <http://wiki.nginx.org/NginxHttpSubsModule>
+" A filter module which can do both regular expression and fixed string substitutions on response bodies.
+syn keyword ngxDirectiveThirdParty subs_filter
+syn keyword ngxDirectiveThirdParty subs_filter_types
+
+" Supervisord Module <http://labs.frickle.com/nginx_ngx_supervisord/>
+" Module providing nginx with API to communicate with supervisord and manage (start/stop) backends on-demand.
+syn keyword ngxDirectiveThirdParty supervisord
+syn keyword ngxDirectiveThirdParty supervisord_inherit_backend_status
+syn keyword ngxDirectiveThirdParty supervisord_name
+syn keyword ngxDirectiveThirdParty supervisord_start
+syn keyword ngxDirectiveThirdParty supervisord_stop
+
+" Upload Module <http://www.grid.net.ru/nginx/upload.en.html>
+" Parses multipart/form-data allowing arbitrary handling of uploaded files.
+syn keyword ngxDirectiveThirdParty upload_aggregate_form_field
+syn keyword ngxDirectiveThirdParty upload_buffer_size
+syn keyword ngxDirectiveThirdParty upload_cleanup
+syn keyword ngxDirectiveThirdParty upload_limit_rate
+syn keyword ngxDirectiveThirdParty upload_max_file_size
+syn keyword ngxDirectiveThirdParty upload_max_output_body_len
+syn keyword ngxDirectiveThirdParty upload_max_part_header_len
+syn keyword ngxDirectiveThirdParty upload_pass
+syn keyword ngxDirectiveThirdParty upload_pass_args
+syn keyword ngxDirectiveThirdParty upload_pass_form_field
+syn keyword ngxDirectiveThirdParty upload_set_form_field
+syn keyword ngxDirectiveThirdParty upload_store
+syn keyword ngxDirectiveThirdParty upload_store_access
+
+" Upload Progress Module <http://wiki.nginx.org/NginxHttpUploadProgressModule>
+" Tracks and reports upload progress.
+syn keyword ngxDirectiveThirdParty report_uploads
+syn keyword ngxDirectiveThirdParty track_uploads
+syn keyword ngxDirectiveThirdParty upload_progress
+syn keyword ngxDirectiveThirdParty upload_progress_content_type
+syn keyword ngxDirectiveThirdParty upload_progress_header
+syn keyword ngxDirectiveThirdParty upload_progress_json_output
+syn keyword ngxDirectiveThirdParty upload_progress_template
+
+" Upstream Fair Balancer <http://wiki.nginx.org/NginxHttpUpstreamFairModule>
+" Sends an incoming request to the least-busy backend server, rather than distributing requests round-robin.
+syn keyword ngxDirectiveThirdParty fair
+syn keyword ngxDirectiveThirdParty upstream_fair_shm_size
+
+" Upstream Consistent Hash <http://wiki.nginx.org/NginxHttpUpstreamConsistentHash>
+" Select backend based on Consistent hash ring.
+syn keyword ngxDirectiveThirdParty consistent_hash
+
+" Upstream Hash Module <http://wiki.nginx.org/NginxHttpUpstreamRequestHashModule>
+" Provides simple upstream load distribution by hashing a configurable variable.
+syn keyword ngxDirectiveThirdParty hash
+syn keyword ngxDirectiveThirdParty hash_again
+
+" XSS Module <http://github.com/agentzh/xss-nginx-module>
+" Native support for cross-site scripting (XSS) in an nginx.
+syn keyword ngxDirectiveThirdParty xss_callback_arg
+syn keyword ngxDirectiveThirdParty xss_get
+syn keyword ngxDirectiveThirdParty xss_input_types
+syn keyword ngxDirectiveThirdParty xss_output_type
+
+" uWSGI Module <http://wiki.nginx.org/HttpUwsgiModule>
+" Allows Nginx to interact with uWSGI processes and control what parameters are passed to the process.
+syn keyword ngxDirectiveThirdParty uwsgi_bind
+syn keyword ngxDirectiveThirdParty uwsgi_buffer_size
+syn keyword ngxDirectiveThirdParty uwsgi_buffering
+syn keyword ngxDirectiveThirdParty uwsgi_buffers
+syn keyword ngxDirectiveThirdParty uwsgi_busy_buffers_size
+syn keyword ngxDirectiveThirdParty uwsgi_cache
+syn keyword ngxDirectiveThirdParty uwsgi_cache_bypass
+syn keyword ngxDirectiveThirdParty uwsgi_cache_key
+syn keyword ngxDirectiveThirdParty uwsgi_cache_lock
+syn keyword ngxDirectiveThirdParty uwsgi_cache_lock_timeout
+syn keyword ngxDirectiveThirdParty uwsgi_cache_methods
+syn keyword ngxDirectiveThirdParty uwsgi_cache_min_uses
+syn keyword ngxDirectiveThirdParty uwsgi_cache_path
+syn keyword ngxDirectiveThirdParty uwsgi_cache_use_stale
+syn keyword ngxDirectiveThirdParty uwsgi_cache_valid
+syn keyword ngxDirectiveThirdParty uwsgi_connect_timeout
+syn keyword ngxDirectiveThirdParty uwsgi_hide_header
+syn keyword ngxDirectiveThirdParty uwsgi_ignore_client_abort
+syn keyword ngxDirectiveThirdParty uwsgi_ignore_headers
+syn keyword ngxDirectiveThirdParty uwsgi_intercept_errors
+syn keyword ngxDirectiveThirdParty uwsgi_max_temp_file_size
+syn keyword ngxDirectiveThirdParty uwsgi_modifier1
+syn keyword ngxDirectiveThirdParty uwsgi_modifier2
+syn keyword ngxDirectiveThirdParty uwsgi_next_upstream
+syn keyword ngxDirectiveThirdParty uwsgi_no_cache
+syn keyword ngxDirectiveThirdParty uwsgi_param
+syn keyword ngxDirectiveThirdParty uwsgi_pass
+syn keyword ngxDirectiveThirdParty uwsgi_pass_header
+syn keyword ngxDirectiveThirdParty uwsgi_pass_request_body
+syn keyword ngxDirectiveThirdParty uwsgi_pass_request_headers
+syn keyword ngxDirectiveThirdParty uwsgi_read_timeout
+syn keyword ngxDirectiveThirdParty uwsgi_send_timeout
+syn keyword ngxDirectiveThirdParty uwsgi_store
+syn keyword ngxDirectiveThirdParty uwsgi_store_access
+syn keyword ngxDirectiveThirdParty uwsgi_string
+syn keyword ngxDirectiveThirdParty uwsgi_temp_file_write_size
+syn keyword ngxDirectiveThirdParty uwsgi_temp_path
+
+" highlight
+
+hi link ngxComment Comment
+hi link ngxVariable Identifier
+hi link ngxVariableBlock Identifier
+hi link ngxVariableString PreProc
+hi link ngxBlock Normal
+hi link ngxString String
+
+hi link ngxBoolean Boolean
+hi link ngxDirectiveBlock Statement
+hi link ngxDirectiveImportant Type
+hi link ngxDirectiveControl Keyword
+hi link ngxDirectiveError Constant
+hi link ngxDirectiveDeprecated Error
+hi link ngxDirective Identifier
+hi link ngxDirectiveThirdParty Special
+
+let b:current_syntax = "nginx"
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 5c42c4737..220d55a29 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1005007
-#define NGINX_VERSION "1.5.7"
+#define nginx_version 1005008
+#define NGINX_VERSION "1.5.8"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index fbcd5f719..57e26912d 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -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;
}
@@ -209,6 +213,21 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle)
#endif
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+
+ if (getsockopt(ls[i].fastopen, IPPROTO_TCP, TCP_FASTOPEN,
+ (void *) &ls[i].fastopen, &olen)
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "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));
@@ -582,6 +601,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;
@@ -1046,12 +1078,15 @@ 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)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
- len = sizeof(struct sockaddr_in6);
for (addr = 0, i = 0; addr == 0 && i < 16; i++) {
addr |= sin6->sin6_addr.s6_addr[i];
@@ -1060,9 +1095,14 @@ 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;
- len = sizeof(struct sockaddr_in);
addr = sin->sin_addr.s_addr;
break;
}
@@ -1082,13 +1122,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, len, 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/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 3daf2eee4..c7b3b315c 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -80,6 +80,10 @@ struct ngx_listening_s {
int setfib;
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ int fastopen;
+#endif
+
};
@@ -139,6 +143,7 @@ struct ngx_connection_s {
#endif
struct sockaddr *local_sockaddr;
+ socklen_t local_socklen;
ngx_buf_t *buffer;
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c
index 96345192a..86ed9a6da 100644
--- a/src/core/ngx_cycle.c
+++ b/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);
@@ -494,7 +493,9 @@ 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[n].socklen, 1)
+ == NGX_OK)
{
nls[n].fd = ls[i].fd;
nls[n].previous = &ls[i];
@@ -849,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;
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index 0792d6e8c..26c5bc4b0 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -1196,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/src/core/ngx_inet.h b/src/core/ngx_inet.h
index d8f44c1e7..05557509d 100644
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -115,6 +115,8 @@ 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/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index d94477a9c..a446f98b6 100644
--- a/src/core/ngx_resolver.c
+++ b/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;
@@ -411,18 +457,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 +485,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 +510,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 +530,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 +581,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 +618,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 +644,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,8 +675,8 @@ 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->waiting = ctx;
@@ -630,16 +704,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 +766,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 +802,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 +812,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,16 +858,16 @@ 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;
@@ -744,7 +882,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 +907,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 +945,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 +977,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 +1074,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 +1110,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 +1132,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 +1239,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 +1288,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 +1314,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 +1356,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 +1381,7 @@ found:
short_response:
- err = "short dns response";
+ err = "short DNS response";
done:
@@ -1160,6 +1389,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 +1408,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 +1442,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 +1561,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,10 +1573,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 +1600,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,41 +1612,85 @@ 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) {
+ 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,
@@ -1328,72 +1699,152 @@ ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
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
+ }
+
+ rn->ttl = ttl;
+
+ n = 0;
+ i = ans;
- i += 1 + buf[i];
+ 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
+
+ i += len;
+ }
+ }
+
+ 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
- rn->u.addrs = addrs;
+ naddrs = rn->naddrs;
+#if (NGX_HAVE_INET6)
+ naddrs += rn->naddrs6;
+#endif
+
+ if (naddrs == 1 && rn->naddrs == 1) {
+ addrs = NULL;
- addrs = ngx_resolver_dup(r, rn->u.addrs,
- naddrs * sizeof(in_addr_t));
+ } 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 +1855,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;
+ }
+
+ next = ctx->next;
- ctx->handler(ctx);
+ 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,
@@ -1455,18 +1931,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 +1958,9 @@ invalid:
failed:
- /* unlock name mutex */
+next:
- ngx_resolver_free(r, name.data);
+ /* unlock name mutex */
return;
}
@@ -1492,47 +1972,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;
+ }
- rn = ngx_resolver_lookup_addr(r, addr);
+ 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;
+ }
+
+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 +2096,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 +2111,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 +2161,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 +2196,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 +2204,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 +2308,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 +2395,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 +2470,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 +2495,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 +2538,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 +2605,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 +2621,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);
+
+ 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", (ctx->addr >> n) & 0xff);
- *p = (u_char) (d - &p[1]);
- p = d;
+ 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 +2739,7 @@ done:
n = *src++;
} else {
- ngx_memcpy(dst, src, n);
+ ngx_strlow(dst, src, n);
dst += n;
src += n;
@@ -2061,10 +2788,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 +2869,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;
}
diff --git a/src/core/ngx_resolver.h b/src/core/ngx_resolver.h
index ae34ca56d..264c8c42b 100644
--- a/src/core/ngx_resolver.h
+++ b/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/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index b1145446a..e33dce81e 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -212,6 +212,7 @@ ngx_event_accept(ngx_event_t *ev)
c->socklen = socklen;
c->listening = ls;
c->local_sockaddr = ls->sockaddr;
+ c->local_socklen = ls->socklen;
c->unexpected_eof = 1;
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index e4bc1a2c7..ee6671350 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1025,6 +1025,7 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
size -= n;
if (size == 0) {
+ c->read->ready = 1;
return bytes;
}
@@ -1034,6 +1035,10 @@ ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size)
}
if (bytes) {
+ if (c->ssl->last != NGX_AGAIN) {
+ c->read->ready = 1;
+ }
+
return bytes;
}
diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c
index 77076141c..3a3cc7f9e 100644
--- a/src/event/ngx_event_openssl_stapling.c
+++ b/src/event/ngx_event_openssl_stapling.c
@@ -792,7 +792,6 @@ ngx_ssl_ocsp_request(ngx_ssl_ocsp_ctx_t *ctx)
}
resolve->name = ctx->host;
- resolve->type = NGX_RESOLVE_A;
resolve->handler = ngx_ssl_ocsp_resolve_handler;
resolve->data = ctx;
resolve->timeout = ctx->resolver_timeout;
@@ -816,11 +815,12 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
{
ngx_ssl_ocsp_ctx_t *ctx = resolve->data;
- u_char *p;
- size_t len;
- in_port_t port;
- ngx_uint_t i;
- struct sockaddr_in *sin;
+ u_char *p;
+ size_t len;
+ in_port_t port;
+ socklen_t socklen;
+ ngx_uint_t i;
+ struct sockaddr *sockaddr;
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
"ssl ocsp resolve handler");
@@ -835,15 +835,19 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
#if (NGX_DEBUG)
{
- in_addr_t addr;
+ u_char text[NGX_SOCKADDR_STRLEN];
+ ngx_str_t addr;
+
+ addr.data = text;
for (i = 0; i < resolve->naddrs; i++) {
- addr = ntohl(resolve->addrs[i]);
+ addr.len = ngx_sock_ntop(resolve->addrs[i].sockaddr,
+ resolve->addrs[i].socklen,
+ text, NGX_SOCKADDR_STRLEN, 0);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
+ "name was resolved to %V", &addr);
- ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
- "name was resolved to %ud.%ud.%ud.%ud",
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff);
}
}
#endif
@@ -859,27 +863,34 @@ ngx_ssl_ocsp_resolve_handler(ngx_resolver_ctx_t *resolve)
for (i = 0; i < resolve->naddrs; i++) {
- sin = ngx_pcalloc(ctx->pool, sizeof(struct sockaddr_in));
- if (sin == NULL) {
+ socklen = resolve->addrs[i].socklen;
+
+ sockaddr = ngx_palloc(ctx->pool, socklen);
+ if (sockaddr == NULL) {
goto failed;
}
- sin->sin_family = AF_INET;
- sin->sin_port = port;
- sin->sin_addr.s_addr = resolve->addrs[i];
+ ngx_memcpy(sockaddr, resolve->addrs[i].sockaddr, socklen);
- ctx->addrs[i].sockaddr = (struct sockaddr *) sin;
- ctx->addrs[i].socklen = sizeof(struct sockaddr_in);
+ switch (sockaddr->sa_family) {
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ ((struct sockaddr_in6 *) sockaddr)->sin6_port = port;
+ break;
+#endif
+ default: /* AF_INET */
+ ((struct sockaddr_in *) sockaddr)->sin_port = port;
+ }
- len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
+ ctx->addrs[i].sockaddr = sockaddr;
+ ctx->addrs[i].socklen = socklen;
- p = ngx_pnalloc(ctx->pool, len);
+ p = ngx_pnalloc(ctx->pool, NGX_SOCKADDR_STRLEN);
if (p == NULL) {
goto failed;
}
- len = ngx_sock_ntop((struct sockaddr *) sin, sizeof(struct sockaddr_in),
- p, len, 1);
+ len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
ctx->addrs[i].name.len = len;
ctx->addrs[i].name.data = p;
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index 6f685a9ed..eed807d61 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -857,19 +857,13 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK;
}
- if (p->free) {
- cl = p->free;
- b = cl->buf;
- p->free = cl->next;
- ngx_free_chain(p->pool, cl);
-
- } else {
- b = ngx_alloc_buf(p->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
+ cl = ngx_chain_get_free_buf(p->pool, &p->free);
+ if (cl == NULL) {
+ return NGX_ERROR;
}
+ b = cl->buf;
+
ngx_memcpy(b, buf, sizeof(ngx_buf_t));
b->shadow = buf;
b->tag = p->tag;
@@ -877,14 +871,6 @@ ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
b->recycled = 1;
buf->shadow = b;
- cl = ngx_alloc_chain_link(p->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
if (p->in) {
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 51672e227..5bcf6ef8c 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1827,19 +1827,13 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
break;
}
- if (p->free) {
- cl = p->free;
- b = cl->buf;
- p->free = cl->next;
- ngx_free_chain(p->pool, cl);
-
- } else {
- b = ngx_alloc_buf(p->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
+ cl = ngx_chain_get_free_buf(p->pool, &p->free);
+ if (cl == NULL) {
+ return NGX_ERROR;
}
+ b = cl->buf;
+
ngx_memzero(b, sizeof(ngx_buf_t));
b->pos = f->pos;
@@ -1852,14 +1846,6 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
*prev = b;
prev = &b->shadow;
- cl = ngx_alloc_chain_link(p->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
if (p->in) {
*p->last_in = cl;
} else {
@@ -2769,7 +2755,7 @@ ngx_http_fastcgi_merge_params(ngx_conf_t *cf,
s->key = h->key;
s->value = h->value;
- s->skip_empty = 0;
+ s->skip_empty = 1;
next:
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 404607511..93469984c 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1615,19 +1615,13 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
return NGX_OK;
}
- if (p->free) {
- cl = p->free;
- b = cl->buf;
- p->free = cl->next;
- ngx_free_chain(p->pool, cl);
-
- } else {
- b = ngx_alloc_buf(p->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
+ cl = ngx_chain_get_free_buf(p->pool, &p->free);
+ if (cl == NULL) {
+ return NGX_ERROR;
}
+ b = cl->buf;
+
ngx_memcpy(b, buf, sizeof(ngx_buf_t));
b->shadow = buf;
b->tag = p->tag;
@@ -1635,14 +1629,6 @@ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
b->recycled = 1;
buf->shadow = b;
- cl = ngx_alloc_chain_link(p->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
if (p->in) {
@@ -1707,19 +1693,13 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
/* a chunk has been parsed successfully */
- if (p->free) {
- cl = p->free;
- b = cl->buf;
- p->free = cl->next;
- ngx_free_chain(p->pool, cl);
-
- } else {
- b = ngx_alloc_buf(p->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
+ cl = ngx_chain_get_free_buf(p->pool, &p->free);
+ if (cl == NULL) {
+ return NGX_ERROR;
}
+ b = cl->buf;
+
ngx_memzero(b, sizeof(ngx_buf_t));
b->pos = buf->pos;
@@ -1732,14 +1712,6 @@ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
*prev = b;
prev = &b->shadow;
- cl = ngx_alloc_chain_link(p->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
if (p->in) {
*p->last_in = cl;
} else {
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
index 9163c6b3c..d396b27c8 100644
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -1506,7 +1506,7 @@ ngx_http_scgi_merge_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
s->key = h->key;
s->value = h->value;
- s->skip_empty = 0;
+ s->skip_empty = 1;
next:
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
index 9c5d76213..0ddea57df 100644
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -34,6 +34,12 @@ typedef struct {
ngx_uint_t modifier1;
ngx_uint_t modifier2;
+
+#if (NGX_HTTP_SSL)
+ ngx_uint_t ssl;
+ ngx_uint_t ssl_protocols;
+ ngx_str_t ssl_ciphers;
+#endif
} ngx_http_uwsgi_loc_conf_t;
@@ -66,6 +72,11 @@ static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#endif
+#if (NGX_HTTP_SSL)
+static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
+ ngx_http_uwsgi_loc_conf_t *uwcf);
+#endif
+
static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds = {
ngx_conf_check_num_bounds, 0, 255
@@ -86,6 +97,20 @@ static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
};
+#if (NGX_HTTP_SSL)
+
+static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = {
+ { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
+ { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
+ { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
+ { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
+ { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
+ { ngx_null_string, 0 }
+};
+
+#endif
+
+
ngx_module_t ngx_http_uwsgi_module;
@@ -361,6 +386,31 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
&ngx_http_upstream_ignore_headers_masks },
+#if (NGX_HTTP_SSL)
+
+ { ngx_string("uwsgi_ssl_session_reuse"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse),
+ NULL },
+
+ { ngx_string("uwsgi_ssl_protocols"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+ ngx_conf_set_bitmask_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols),
+ &ngx_http_uwsgi_ssl_protocols },
+
+ { ngx_string("uwsgi_ssl_ciphers"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_str_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers),
+ NULL },
+
+#endif
+
ngx_null_command
};
@@ -448,15 +498,29 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
- if (uwcf->uwsgi_lengths) {
+ u = r->upstream;
+
+ if (uwcf->uwsgi_lengths == NULL) {
+
+#if (NGX_HTTP_SSL)
+ u->ssl = (uwcf->upstream.ssl != NULL);
+
+ if (u->ssl) {
+ ngx_str_set(&u->schema, "suwsgi://");
+
+ } else {
+ ngx_str_set(&u->schema, "uwsgi://");
+ }
+#else
+ ngx_str_set(&u->schema, "uwsgi://");
+#endif
+
+ } else {
if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
- u = r->upstream;
-
- ngx_str_set(&u->schema, "uwsgi://");
u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module;
u->conf = &uwcf->upstream;
@@ -494,6 +558,7 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r)
static ngx_int_t
ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
{
+ size_t add;
ngx_url_t url;
ngx_http_upstream_t *u;
@@ -506,6 +571,41 @@ ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
return NGX_ERROR;
}
+ if (url.url.len > 8
+ && ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0)
+ {
+ add = 8;
+
+ } else if (url.url.len > 9
+ && ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0)
+ {
+
+#if (NGX_HTTP_SSL)
+ add = 9;
+ r->upstream->ssl = 1;
+#else
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "suwsgi protocol requires SSL support");
+ return NGX_ERROR;
+#endif
+
+ } else {
+ add = 0;
+ }
+
+ u = r->upstream;
+
+ if (add) {
+ u->schema.len = add;
+ u->schema.data = url.url.data;
+
+ url.url.data += add;
+ url.url.len -= add;
+
+ } else {
+ ngx_str_set(&u->schema, "uwsgi://");
+ }
+
url.no_resolve = 1;
if (ngx_parse_url(r->pool, &url) != NGX_OK) {
@@ -517,8 +617,6 @@ ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
return NGX_ERROR;
}
- u = r->upstream;
-
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
if (u->resolved == NULL) {
return NGX_ERROR;
@@ -1145,6 +1243,9 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
conf->upstream.intercept_errors = NGX_CONF_UNSET;
+#if (NGX_HTTP_SSL)
+ conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
+#endif
/* "uwsgi_cyclic_temp_file" is disabled */
conf->upstream.cyclic_temp_file = 0;
@@ -1392,6 +1493,27 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->upstream.intercept_errors,
prev->upstream.intercept_errors, 0);
+#if (NGX_HTTP_SSL)
+ ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
+ prev->upstream.ssl_session_reuse, 1);
+
+ ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
+ (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3
+ |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1
+ |NGX_SSL_TLSv1_2));
+
+ ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
+ "DEFAULT");
+
+ if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (conf->upstream.ssl == NULL) {
+ conf->upstream.ssl = prev->upstream.ssl;
+ }
+#endif
+
ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
hash.max_size = 512;
@@ -1548,7 +1670,7 @@ ngx_http_uwsgi_merge_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
s->key = h->key;
s->value = h->value;
- s->skip_empty = 0;
+ s->skip_empty = 1;
next:
@@ -1670,6 +1792,7 @@ ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_uwsgi_loc_conf_t *uwcf = conf;
+ size_t add;
ngx_url_t u;
ngx_str_t *value, *url;
ngx_uint_t n;
@@ -1705,12 +1828,35 @@ ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
+#if (NGX_HTTP_SSL)
+ uwcf->ssl = 1;
+#endif
+
return NGX_CONF_OK;
}
+ if (ngx_strncasecmp(url->data, (u_char *) "uwsgi://", 8) == 0) {
+ add = 8;
+
+ } else if (ngx_strncasecmp(url->data, (u_char *) "suwsgi://", 9) == 0) {
+
+#if (NGX_HTTP_SSL)
+ add = 9;
+ uwcf->ssl = 1;
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "suwsgi protocol requires SSL support");
+ return NGX_CONF_ERROR;
+#endif
+
+ } else {
+ add = 0;
+ }
+
ngx_memzero(&u, sizeof(ngx_url_t));
- u.url = value[1];
+ u.url.len = url->len - add;
+ u.url.data = url->data + add;
u.no_resolve = 1;
uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
@@ -1844,3 +1990,47 @@ ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
#endif
+
+
+#if (NGX_HTTP_SSL)
+
+static ngx_int_t
+ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
+{
+ ngx_pool_cleanup_t *cln;
+
+ uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
+ if (uwcf->upstream.ssl == NULL) {
+ return NGX_ERROR;
+ }
+
+ uwcf->upstream.ssl->log = cf->log;
+
+ if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ if (SSL_CTX_set_cipher_list(uwcf->upstream.ssl->ctx,
+ (const char *) uwcf->ssl_ciphers.data)
+ == 0)
+ {
+ ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
+ "SSL_CTX_set_cipher_list(\"%V\") failed",
+ &uwcf->ssl_ciphers);
+ return NGX_ERROR;
+ }
+
+ cln = ngx_pool_cleanup_add(cf->pool, 0);
+ if (cln == NULL) {
+ return NGX_ERROR;
+ }
+
+ cln->handler = ngx_ssl_cleanup_ctx;
+ cln->data = uwcf->upstream.ssl;
+
+ return NGX_OK;
+}
+
+#endif
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 91bb04f55..f030baa71 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1811,6 +1811,10 @@ ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
ls->setfib = addr->opt.setfib;
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ ls->fastopen = addr->opt.fastopen;
+#endif
+
return ls;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index d2e29136d..8abf864d5 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -3041,6 +3041,9 @@ ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
#if (NGX_HAVE_SETFIB)
lsopt.setfib = -1;
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ lsopt.fastopen = -1;
+#endif
lsopt.wildcard = 1;
(void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.socklen, lsopt.addr,
@@ -3989,6 +3992,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_HAVE_SETFIB)
lsopt.setfib = -1;
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ lsopt.fastopen = -1;
+#endif
lsopt.wildcard = u.wildcard;
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
lsopt.ipv6only = 1;
@@ -4015,6 +4021,8 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#if (NGX_HAVE_SETFIB)
if (ngx_strncmp(value[n].data, "setfib=", 7) == 0) {
lsopt.setfib = ngx_atoi(value[n].data + 7, value[n].len - 7);
+ lsopt.set = 1;
+ lsopt.bind = 1;
if (lsopt.setfib == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@@ -4025,6 +4033,23 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
#endif
+
+#if (NGX_HAVE_TCP_FASTOPEN)
+ if (ngx_strncmp(value[n].data, "fastopen=", 9) == 0) {
+ lsopt.fastopen = ngx_atoi(value[n].data + 9, value[n].len - 9);
+ lsopt.set = 1;
+ lsopt.bind = 1;
+
+ if (lsopt.fastopen == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid fastopen \"%V\"", &value[n]);
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+ }
+#endif
+
if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
lsopt.set = 1;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 5b38000d8..220c94ee4 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -89,6 +89,9 @@ typedef struct {
#if (NGX_HAVE_SETFIB)
int setfib;
#endif
+#if (NGX_HAVE_TCP_FASTOPEN)
+ int fastopen;
+#endif
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
int tcp_keepidle;
int tcp_keepintvl;
diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c
index 36e23be02..2346ad7a1 100644
--- a/src/http/ngx_http_spdy.c
+++ b/src/http/ngx_http_spdy.c
@@ -2855,7 +2855,9 @@ ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc,
if (stream->waiting) {
r->blocked -= stream->waiting;
stream->waiting = 0;
+
ev = fc->write;
+ ev->delayed = 0;
} else {
ev = fc->read;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 9570ccc7e..8bf0ba218 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -644,7 +644,6 @@ ngx_http_upstream_init_request(ngx_http_request_t *r)
}
ctx->name = *host;
- ctx->type = NGX_RESOLVE_A;
ctx->handler = ngx_http_upstream_resolve_handler;
ctx->data = r;
ctx->timeout = clcf->resolver_timeout;
@@ -918,16 +917,18 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
#if (NGX_DEBUG)
{
- in_addr_t addr;
+ u_char text[NGX_SOCKADDR_STRLEN];
+ ngx_str_t addr;
ngx_uint_t i;
+ addr.data = text;
+
for (i = 0; i < ctx->naddrs; i++) {
- addr = ntohl(ur->addrs[i]);
+ addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen,
+ text, NGX_SOCKADDR_STRLEN, 0);
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "name was resolved to %ud.%ud.%ud.%ud",
- (addr >> 24) & 0xff, (addr >> 16) & 0xff,
- (addr >> 8) & 0xff, addr & 0xff);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "name was resolved to %V", &addr);
}
}
#endif
@@ -4555,7 +4556,8 @@ ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
{
u_char *p;
- if (!r->upstream->conf->cache_revalidate
+ if (r->upstream == NULL
+ || !r->upstream->conf->cache_revalidate
|| r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED
|| r->cache->last_modified == -1)
{
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 469988eed..9f96c50f3 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -256,7 +256,7 @@ typedef struct {
ngx_uint_t no_port; /* unsigned no_port:1 */
ngx_uint_t naddrs;
- in_addr_t *addrs;
+ ngx_addr_t *addrs;
struct sockaddr *sockaddr;
socklen_t socklen;
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c
index 02dbf0a16..85ff5581b 100644
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -79,12 +79,12 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf,
peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
peers->peer[n].socklen = server[i].addrs[j].socklen;
peers->peer[n].name = server[i].addrs[j].name;
- peers->peer[n].max_fails = server[i].max_fails;
- peers->peer[n].fail_timeout = server[i].fail_timeout;
- peers->peer[n].down = server[i].down;
peers->peer[n].weight = server[i].weight;
peers->peer[n].effective_weight = server[i].weight;
peers->peer[n].current_weight = 0;
+ peers->peer[n].max_fails = server[i].max_fails;
+ peers->peer[n].fail_timeout = server[i].fail_timeout;
+ peers->peer[n].down = server[i].down;
n++;
}
}
@@ -266,8 +266,9 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
{
u_char *p;
size_t len;
+ socklen_t socklen;
ngx_uint_t i, n;
- struct sockaddr_in *sin;
+ struct sockaddr *sockaddr;
ngx_http_upstream_rr_peers_t *peers;
ngx_http_upstream_rr_peer_data_t *rrp;
@@ -306,27 +307,34 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r,
for (i = 0; i < ur->naddrs; i++) {
- len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1;
+ socklen = ur->addrs[i].socklen;
- p = ngx_pnalloc(r->pool, len);
- if (p == NULL) {
+ sockaddr = ngx_palloc(r->pool, socklen);
+ if (sockaddr == NULL) {
return NGX_ERROR;
}
- len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, NGX_INET_ADDRSTRLEN);
- len = ngx_sprintf(&p[len], ":%d", ur->port) - p;
+ ngx_memcpy(sockaddr, ur->addrs[i].sockaddr, socklen);
- sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in));
- if (sin == NULL) {
+ switch (sockaddr->sa_family) {
+#if (NGX_HAVE_INET6)
+ case AF_INET6:
+ ((struct sockaddr_in6 *) sockaddr)->sin6_port = htons(ur->port);
+ break;
+#endif
+ default: /* AF_INET */
+ ((struct sockaddr_in *) sockaddr)->sin_port = htons(ur->port);
+ }
+
+ p = ngx_pnalloc(r->pool, NGX_SOCKADDR_STRLEN);
+ if (p == NULL) {
return NGX_ERROR;
}
- sin->sin_family = AF_INET;
- sin->sin_port = htons(ur->port);
- sin->sin_addr.s_addr = ur->addrs[i];
+ len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1);
- peers->peer[i].sockaddr = (struct sockaddr *) sin;
- peers->peer[i].socklen = sizeof(struct sockaddr_in);
+ peers->peer[i].sockaddr = sockaddr;
+ peers->peer[i].socklen = socklen;
peers->peer[i].name.len = len;
peers->peer[i].name.data = p;
peers->peer[i].weight = 1;
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index e49d2023b..8b86d5a9a 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -1185,6 +1185,12 @@ ngx_http_variable_remote_port(ngx_http_request_t *r,
break;
#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+ port = 0;
+ break;
+#endif
+
default: /* AF_INET */
sin = (struct sockaddr_in *) r->connection->sockaddr;
port = ntohs(sin->sin_port);
@@ -1263,6 +1269,12 @@ ngx_http_variable_server_port(ngx_http_request_t *r,
break;
#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+ case AF_UNIX:
+ port = 0;
+ break;
+#endif
+
default: /* AF_INET */
sin = (struct sockaddr_in *) r->connection->local_sockaddr;
port = ntohs(sin->sin_port);
diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c
index 0238b6282..52fe47523 100644
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -55,7 +55,6 @@ static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
void
ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
{
- struct sockaddr_in *sin;
ngx_resolver_ctx_t *ctx;
ngx_mail_core_srv_conf_t *cscf;
@@ -67,11 +66,13 @@ ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
return;
}
- if (c->sockaddr->sa_family != AF_INET) {
+#if (NGX_HAVE_UNIX_DOMAIN)
+ if (c->sockaddr->sa_family == AF_UNIX) {
s->host = smtp_tempunavail;
ngx_mail_smtp_greeting(s, c);
return;
}
+#endif
c->log->action = "in resolving client address";
@@ -81,11 +82,8 @@ ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
return;
}
- /* AF_INET only */
-
- sin = (struct sockaddr_in *) c->sockaddr;
-
- ctx->addr = sin->sin_addr.s_addr;
+ ctx->addr.sockaddr = c->sockaddr;
+ ctx->addr.socklen = c->socklen;
ctx->handler = ngx_mail_smtp_resolve_addr_handler;
ctx->data = s;
ctx->timeout = cscf->resolver_timeout;
@@ -167,7 +165,6 @@ ngx_mail_smtp_resolve_name(ngx_event_t *rev)
}
ctx->name = s->host;
- ctx->type = NGX_RESOLVE_A;
ctx->handler = ngx_mail_smtp_resolve_name_handler;
ctx->data = s;
ctx->timeout = cscf->resolver_timeout;
@@ -181,10 +178,8 @@ ngx_mail_smtp_resolve_name(ngx_event_t *rev)
static void
ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
{
- in_addr_t addr;
ngx_uint_t i;
ngx_connection_t *c;
- struct sockaddr_in *sin;
ngx_mail_session_t *s;
s = ctx->data;
@@ -205,22 +200,29 @@ ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
} else {
- /* AF_INET only */
+#if (NGX_DEBUG)
+ {
+ u_char text[NGX_SOCKADDR_STRLEN];
+ ngx_str_t addr;
- sin = (struct sockaddr_in *) c->sockaddr;
+ addr.data = text;
for (i = 0; i < ctx->naddrs; i++) {
+ addr.len = ngx_sock_ntop(ctx->addrs[i].sockaddr,
+ ctx->addrs[i].socklen,
+ text, NGX_SOCKADDR_STRLEN, 0);
- addr = ctx->addrs[i];
-
- ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
- "name was resolved to %ud.%ud.%ud.%ud",
- (ntohl(addr) >> 24) & 0xff,
- (ntohl(addr) >> 16) & 0xff,
- (ntohl(addr) >> 8) & 0xff,
- ntohl(addr) & 0xff);
+ ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
+ "name was resolved to %V", &addr);
+ }
+ }
+#endif
- if (addr == sin->sin_addr.s_addr) {
+ for (i = 0; i < ctx->naddrs; i++) {
+ if (ngx_cmp_sockaddr(ctx->addrs[i].sockaddr, ctx->addrs[i].socklen,
+ c->sockaddr, c->socklen, 0)
+ == NGX_OK)
+ {
goto found;
}
}