Compare commits
2
Commits
3043d78e78
...
96926ba5b9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96926ba5b9 | ||
|
|
ffaaf326a8 |
@@ -1170,6 +1170,16 @@ if [ $STREAM != NO ]; then
|
|||||||
. auto/module
|
. auto/module
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $STREAM_PASS = YES ]; then
|
||||||
|
ngx_module_name=ngx_stream_pass_module
|
||||||
|
ngx_module_deps=
|
||||||
|
ngx_module_srcs=src/stream/ngx_stream_pass_module.c
|
||||||
|
ngx_module_libs=
|
||||||
|
ngx_module_link=$STREAM_PASS
|
||||||
|
|
||||||
|
. auto/module
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $STREAM_SET = YES ]; then
|
if [ $STREAM_SET = YES ]; then
|
||||||
ngx_module_name=ngx_stream_set_module
|
ngx_module_name=ngx_stream_set_module
|
||||||
ngx_module_deps=
|
ngx_module_deps=
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ STREAM_GEOIP=NO
|
|||||||
STREAM_MAP=YES
|
STREAM_MAP=YES
|
||||||
STREAM_SPLIT_CLIENTS=YES
|
STREAM_SPLIT_CLIENTS=YES
|
||||||
STREAM_RETURN=YES
|
STREAM_RETURN=YES
|
||||||
|
STREAM_PASS=YES
|
||||||
STREAM_SET=YES
|
STREAM_SET=YES
|
||||||
STREAM_UPSTREAM_HASH=YES
|
STREAM_UPSTREAM_HASH=YES
|
||||||
STREAM_UPSTREAM_LEAST_CONN=YES
|
STREAM_UPSTREAM_LEAST_CONN=YES
|
||||||
@@ -339,6 +340,7 @@ use the \"--with-mail_ssl_module\" option instead"
|
|||||||
--without-stream_split_clients_module)
|
--without-stream_split_clients_module)
|
||||||
STREAM_SPLIT_CLIENTS=NO ;;
|
STREAM_SPLIT_CLIENTS=NO ;;
|
||||||
--without-stream_return_module) STREAM_RETURN=NO ;;
|
--without-stream_return_module) STREAM_RETURN=NO ;;
|
||||||
|
--without-stream_pass_module) STREAM_PASS=NO ;;
|
||||||
--without-stream_set_module) STREAM_SET=NO ;;
|
--without-stream_set_module) STREAM_SET=NO ;;
|
||||||
--without-stream_upstream_hash_module)
|
--without-stream_upstream_hash_module)
|
||||||
STREAM_UPSTREAM_HASH=NO ;;
|
STREAM_UPSTREAM_HASH=NO ;;
|
||||||
@@ -559,6 +561,7 @@ cat << END
|
|||||||
--without-stream_split_clients_module
|
--without-stream_split_clients_module
|
||||||
disable ngx_stream_split_clients_module
|
disable ngx_stream_split_clients_module
|
||||||
--without-stream_return_module disable ngx_stream_return_module
|
--without-stream_return_module disable ngx_stream_return_module
|
||||||
|
--without-stream_pass_module disable ngx_stream_pass_module
|
||||||
--without-stream_set_module disable ngx_stream_set_module
|
--without-stream_set_module disable ngx_stream_set_module
|
||||||
--without-stream_upstream_hash_module
|
--without-stream_upstream_hash_module
|
||||||
disable ngx_stream_upstream_hash_module
|
disable ngx_stream_upstream_hash_module
|
||||||
|
|||||||
+1
-1
Submodule lib/boringssl updated: a9a3ca4944...70b33d3904
Submodule lib/nginx-http-flv-module updated: 2adfaeec0a...97d51bf22f
+1
-1
Submodule lib/pcre updated: e8db6fa713...29764f94a9
+1
-1
Submodule lib/zlib-ng updated: 93b870fbef...af8169a724
+2
-2
@@ -9,8 +9,8 @@
|
|||||||
#define _NGINX_H_INCLUDED_
|
#define _NGINX_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
#define nginx_version 1025004
|
#define nginx_version 1025005
|
||||||
#define NGINX_VERSION "1.25.4"
|
#define NGINX_VERSION "1.25.5"
|
||||||
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
|
#define NGINX_VER "nginx/" NGINX_VERSION " by Hakase"
|
||||||
|
|
||||||
#ifndef NGINX_SERVER
|
#ifndef NGINX_SERVER
|
||||||
|
|||||||
@@ -631,7 +631,7 @@ ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"the using of the regex \"%V\" requires PCRE library",
|
"using regex \"%V\" requires PCRE library",
|
||||||
name);
|
name);
|
||||||
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
|
|||||||
@@ -2001,7 +2001,7 @@ ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern,
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||||
"the using of the regex \"%V\" in SSI requires PCRE library",
|
"using regex \"%V\" in SSI requires PCRE library",
|
||||||
pattern);
|
pattern);
|
||||||
return NGX_HTTP_SSI_ERROR;
|
return NGX_HTTP_SSI_ERROR;
|
||||||
|
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
continue;
|
continue;
|
||||||
#else
|
#else
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"bind ipv6only is not supported "
|
"ipv6only is not supported "
|
||||||
"on this platform");
|
"on this platform");
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
#endif
|
#endif
|
||||||
@@ -564,7 +564,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"the invalid \"%V\" parameter", &value[i]);
|
"invalid parameter \"%V\"", &value[i]);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+712
-192
@@ -16,16 +16,34 @@ static ngx_int_t ngx_stream_init_phases(ngx_conf_t *cf,
|
|||||||
ngx_stream_core_main_conf_t *cmcf);
|
ngx_stream_core_main_conf_t *cmcf);
|
||||||
static ngx_int_t ngx_stream_init_phase_handlers(ngx_conf_t *cf,
|
static ngx_int_t ngx_stream_init_phase_handlers(ngx_conf_t *cf,
|
||||||
ngx_stream_core_main_conf_t *cmcf);
|
ngx_stream_core_main_conf_t *cmcf);
|
||||||
static ngx_int_t ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
|
|
||||||
ngx_stream_listen_t *listen);
|
static ngx_int_t ngx_stream_add_addresses(ngx_conf_t *cf,
|
||||||
static char *ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
|
ngx_stream_core_srv_conf_t *cscf, ngx_stream_conf_port_t *port,
|
||||||
|
ngx_stream_listen_opt_t *lsopt);
|
||||||
|
static ngx_int_t ngx_stream_add_address(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_srv_conf_t *cscf, ngx_stream_conf_port_t *port,
|
||||||
|
ngx_stream_listen_opt_t *lsopt);
|
||||||
|
static ngx_int_t ngx_stream_add_server(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_srv_conf_t *cscf, ngx_stream_conf_addr_t *addr);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_stream_optimize_servers(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_main_conf_t *cmcf, ngx_array_t *ports);
|
||||||
|
static ngx_int_t ngx_stream_server_names(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_main_conf_t *cmcf, ngx_stream_conf_addr_t *addr);
|
||||||
|
static ngx_int_t ngx_stream_cmp_conf_addrs(const void *one, const void *two);
|
||||||
|
static int ngx_libc_cdecl ngx_stream_cmp_dns_wildcards(const void *one,
|
||||||
|
const void *two);
|
||||||
|
|
||||||
|
static ngx_int_t ngx_stream_init_listening(ngx_conf_t *cf,
|
||||||
|
ngx_stream_conf_port_t *port);
|
||||||
|
static ngx_listening_t *ngx_stream_add_listening(ngx_conf_t *cf,
|
||||||
|
ngx_stream_conf_addr_t *addr);
|
||||||
static ngx_int_t ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport,
|
static ngx_int_t ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport,
|
||||||
ngx_stream_conf_addr_t *addr);
|
ngx_stream_conf_addr_t *addr);
|
||||||
#if (NGX_HAVE_INET6)
|
#if (NGX_HAVE_INET6)
|
||||||
static ngx_int_t ngx_stream_add_addrs6(ngx_conf_t *cf,
|
static ngx_int_t ngx_stream_add_addrs6(ngx_conf_t *cf,
|
||||||
ngx_stream_port_t *stport, ngx_stream_conf_addr_t *addr);
|
ngx_stream_port_t *stport, ngx_stream_conf_addr_t *addr);
|
||||||
#endif
|
#endif
|
||||||
static ngx_int_t ngx_stream_cmp_conf_addrs(const void *one, const void *two);
|
|
||||||
|
|
||||||
|
|
||||||
ngx_uint_t ngx_stream_max_module;
|
ngx_uint_t ngx_stream_max_module;
|
||||||
@@ -74,10 +92,8 @@ static char *
|
|||||||
ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
char *rv;
|
char *rv;
|
||||||
ngx_uint_t i, m, mi, s;
|
ngx_uint_t mi, m, s;
|
||||||
ngx_conf_t pcf;
|
ngx_conf_t pcf;
|
||||||
ngx_array_t ports;
|
|
||||||
ngx_stream_listen_t *listen;
|
|
||||||
ngx_stream_module_t *module;
|
ngx_stream_module_t *module;
|
||||||
ngx_stream_conf_ctx_t *ctx;
|
ngx_stream_conf_ctx_t *ctx;
|
||||||
ngx_stream_core_srv_conf_t **cscfp;
|
ngx_stream_core_srv_conf_t **cscfp;
|
||||||
@@ -251,21 +267,13 @@ ngx_stream_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_stream_conf_port_t))
|
/* optimize the lists of ports, addresses and server names */
|
||||||
!= NGX_OK)
|
|
||||||
{
|
if (ngx_stream_optimize_servers(cf, cmcf, cmcf->ports) != NGX_OK) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
listen = cmcf->listen.elts;
|
return NGX_CONF_OK;
|
||||||
|
|
||||||
for (i = 0; i < cmcf->listen.nelts; i++) {
|
|
||||||
if (ngx_stream_add_ports(cf, &ports, &listen[i]) != NGX_OK) {
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ngx_stream_optimize_servers(cf, &ports);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -377,73 +385,295 @@ ngx_stream_init_phase_handlers(ngx_conf_t *cf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
ngx_int_t
|
||||||
ngx_stream_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
|
ngx_stream_add_listen(ngx_conf_t *cf, ngx_stream_core_srv_conf_t *cscf,
|
||||||
ngx_stream_listen_t *listen)
|
ngx_stream_listen_opt_t *lsopt)
|
||||||
{
|
{
|
||||||
in_port_t p;
|
in_port_t p;
|
||||||
ngx_uint_t i;
|
ngx_uint_t i;
|
||||||
struct sockaddr *sa;
|
struct sockaddr *sa;
|
||||||
ngx_stream_conf_port_t *port;
|
ngx_stream_conf_port_t *port;
|
||||||
ngx_stream_conf_addr_t *addr;
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
sa = listen->sockaddr;
|
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||||
|
|
||||||
|
if (cmcf->ports == NULL) {
|
||||||
|
cmcf->ports = ngx_array_create(cf->temp_pool, 2,
|
||||||
|
sizeof(ngx_stream_conf_port_t));
|
||||||
|
if (cmcf->ports == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sa = lsopt->sockaddr;
|
||||||
p = ngx_inet_get_port(sa);
|
p = ngx_inet_get_port(sa);
|
||||||
|
|
||||||
port = ports->elts;
|
port = cmcf->ports->elts;
|
||||||
for (i = 0; i < ports->nelts; i++) {
|
for (i = 0; i < cmcf->ports->nelts; i++) {
|
||||||
|
|
||||||
if (p == port[i].port
|
if (p != port[i].port
|
||||||
&& listen->type == port[i].type
|
|| lsopt->type != port[i].type
|
||||||
&& sa->sa_family == port[i].family)
|
|| sa->sa_family != port[i].family)
|
||||||
{
|
{
|
||||||
/* a port is already in the port list */
|
continue;
|
||||||
|
|
||||||
port = &port[i];
|
|
||||||
goto found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* a port is already in the port list */
|
||||||
|
|
||||||
|
return ngx_stream_add_addresses(cf, cscf, &port[i], lsopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add a port to the port list */
|
/* add a port to the port list */
|
||||||
|
|
||||||
port = ngx_array_push(ports);
|
port = ngx_array_push(cmcf->ports);
|
||||||
if (port == NULL) {
|
if (port == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
port->family = sa->sa_family;
|
port->family = sa->sa_family;
|
||||||
port->type = listen->type;
|
port->type = lsopt->type;
|
||||||
port->port = p;
|
port->port = p;
|
||||||
|
port->addrs.elts = NULL;
|
||||||
|
|
||||||
if (ngx_array_init(&port->addrs, cf->temp_pool, 2,
|
return ngx_stream_add_address(cf, cscf, port, lsopt);
|
||||||
sizeof(ngx_stream_conf_addr_t))
|
}
|
||||||
!= NGX_OK)
|
|
||||||
{
|
|
||||||
return NGX_ERROR;
|
static ngx_int_t
|
||||||
|
ngx_stream_add_addresses(ngx_conf_t *cf, ngx_stream_core_srv_conf_t *cscf,
|
||||||
|
ngx_stream_conf_port_t *port, ngx_stream_listen_opt_t *lsopt)
|
||||||
|
{
|
||||||
|
ngx_uint_t i, default_server, proxy_protocol,
|
||||||
|
protocols, protocols_prev;
|
||||||
|
ngx_stream_conf_addr_t *addr;
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
ngx_uint_t ssl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we cannot compare whole sockaddr struct's as kernel
|
||||||
|
* may fill some fields in inherited sockaddr struct's
|
||||||
|
*/
|
||||||
|
|
||||||
|
addr = port->addrs.elts;
|
||||||
|
|
||||||
|
for (i = 0; i < port->addrs.nelts; i++) {
|
||||||
|
|
||||||
|
if (ngx_cmp_sockaddr(lsopt->sockaddr, lsopt->socklen,
|
||||||
|
addr[i].opt.sockaddr,
|
||||||
|
addr[i].opt.socklen, 0)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the address is already in the address list */
|
||||||
|
|
||||||
|
if (ngx_stream_add_server(cf, cscf, &addr[i]) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* preserve default_server bit during listen options overwriting */
|
||||||
|
default_server = addr[i].opt.default_server;
|
||||||
|
|
||||||
|
proxy_protocol = lsopt->proxy_protocol || addr[i].opt.proxy_protocol;
|
||||||
|
protocols = lsopt->proxy_protocol;
|
||||||
|
protocols_prev = addr[i].opt.proxy_protocol;
|
||||||
|
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
ssl = lsopt->ssl || addr[i].opt.ssl;
|
||||||
|
protocols |= lsopt->ssl << 1;
|
||||||
|
protocols_prev |= addr[i].opt.ssl << 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (lsopt->set) {
|
||||||
|
|
||||||
|
if (addr[i].opt.set) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"duplicate listen options for %V",
|
||||||
|
&addr[i].opt.addr_text);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr[i].opt = *lsopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check the duplicate "default" server for this address:port */
|
||||||
|
|
||||||
|
if (lsopt->default_server) {
|
||||||
|
|
||||||
|
if (default_server) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"a duplicate default server for %V",
|
||||||
|
&addr[i].opt.addr_text);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
default_server = 1;
|
||||||
|
addr[i].default_server = cscf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for conflicting protocol options */
|
||||||
|
|
||||||
|
if ((protocols | protocols_prev) != protocols_prev) {
|
||||||
|
|
||||||
|
/* options added */
|
||||||
|
|
||||||
|
if ((addr[i].opt.set && !lsopt->set)
|
||||||
|
|| addr[i].protocols_changed
|
||||||
|
|| (protocols | protocols_prev) != protocols)
|
||||||
|
{
|
||||||
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
|
"protocol options redefined for %V",
|
||||||
|
&addr[i].opt.addr_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr[i].protocols = protocols_prev;
|
||||||
|
addr[i].protocols_set = 1;
|
||||||
|
addr[i].protocols_changed = 1;
|
||||||
|
|
||||||
|
} else if ((protocols_prev | protocols) != protocols) {
|
||||||
|
|
||||||
|
/* options removed */
|
||||||
|
|
||||||
|
if (lsopt->set
|
||||||
|
|| (addr[i].protocols_set && protocols != addr[i].protocols))
|
||||||
|
{
|
||||||
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
|
"protocol options redefined for %V",
|
||||||
|
&addr[i].opt.addr_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr[i].protocols = protocols;
|
||||||
|
addr[i].protocols_set = 1;
|
||||||
|
addr[i].protocols_changed = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* the same options */
|
||||||
|
|
||||||
|
if ((lsopt->set && addr[i].protocols_changed)
|
||||||
|
|| (addr[i].protocols_set && protocols != addr[i].protocols))
|
||||||
|
{
|
||||||
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
|
"protocol options redefined for %V",
|
||||||
|
&addr[i].opt.addr_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr[i].protocols = protocols;
|
||||||
|
addr[i].protocols_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr[i].opt.default_server = default_server;
|
||||||
|
addr[i].opt.proxy_protocol = proxy_protocol;
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
addr[i].opt.ssl = ssl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
found:
|
/* add the address to the addresses list that bound to this port */
|
||||||
|
|
||||||
|
return ngx_stream_add_address(cf, cscf, port, lsopt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add the server address, the server names and the server core module
|
||||||
|
* configurations to the port list
|
||||||
|
*/
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_add_address(ngx_conf_t *cf, ngx_stream_core_srv_conf_t *cscf,
|
||||||
|
ngx_stream_conf_port_t *port, ngx_stream_listen_opt_t *lsopt)
|
||||||
|
{
|
||||||
|
ngx_stream_conf_addr_t *addr;
|
||||||
|
|
||||||
|
if (port->addrs.elts == NULL) {
|
||||||
|
if (ngx_array_init(&port->addrs, cf->temp_pool, 4,
|
||||||
|
sizeof(ngx_stream_conf_addr_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addr = ngx_array_push(&port->addrs);
|
addr = ngx_array_push(&port->addrs);
|
||||||
if (addr == NULL) {
|
if (addr == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr->opt = *listen;
|
addr->opt = *lsopt;
|
||||||
|
addr->protocols = 0;
|
||||||
|
addr->protocols_set = 0;
|
||||||
|
addr->protocols_changed = 0;
|
||||||
|
addr->hash.buckets = NULL;
|
||||||
|
addr->hash.size = 0;
|
||||||
|
addr->wc_head = NULL;
|
||||||
|
addr->wc_tail = NULL;
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
addr->nregex = 0;
|
||||||
|
addr->regex = NULL;
|
||||||
|
#endif
|
||||||
|
addr->default_server = cscf;
|
||||||
|
addr->servers.elts = NULL;
|
||||||
|
|
||||||
|
return ngx_stream_add_server(cf, cscf, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* add the server core module configuration to the address:port */
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_add_server(ngx_conf_t *cf, ngx_stream_core_srv_conf_t *cscf,
|
||||||
|
ngx_stream_conf_addr_t *addr)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_stream_core_srv_conf_t **server;
|
||||||
|
|
||||||
|
if (addr->servers.elts == NULL) {
|
||||||
|
if (ngx_array_init(&addr->servers, cf->temp_pool, 4,
|
||||||
|
sizeof(ngx_stream_core_srv_conf_t *))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
server = addr->servers.elts;
|
||||||
|
for (i = 0; i < addr->servers.nelts; i++) {
|
||||||
|
if (server[i] == cscf) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"a duplicate listen %V",
|
||||||
|
&addr->opt.addr_text);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server = ngx_array_push(&addr->servers);
|
||||||
|
if (server == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*server = cscf;
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static ngx_int_t
|
||||||
ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
|
ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_stream_core_main_conf_t *cmcf,
|
||||||
|
ngx_array_t *ports)
|
||||||
{
|
{
|
||||||
ngx_uint_t i, p, last, bind_wildcard;
|
ngx_uint_t p, a;
|
||||||
ngx_listening_t *ls;
|
ngx_stream_conf_port_t *port;
|
||||||
ngx_stream_port_t *stport;
|
ngx_stream_conf_addr_t *addr;
|
||||||
ngx_stream_conf_port_t *port;
|
|
||||||
ngx_stream_conf_addr_t *addr;
|
if (ports == NULL) {
|
||||||
ngx_stream_core_srv_conf_t *cscf;
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
port = ports->elts;
|
port = ports->elts;
|
||||||
for (p = 0; p < ports->nelts; p++) {
|
for (p = 0; p < ports->nelts; p++) {
|
||||||
@@ -451,176 +681,192 @@ ngx_stream_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
|
|||||||
ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
|
ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
|
||||||
sizeof(ngx_stream_conf_addr_t), ngx_stream_cmp_conf_addrs);
|
sizeof(ngx_stream_conf_addr_t), ngx_stream_cmp_conf_addrs);
|
||||||
|
|
||||||
addr = port[p].addrs.elts;
|
|
||||||
last = port[p].addrs.nelts;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if there is the binding to the "*:port" then we need to bind()
|
* check whether all name-based servers have the same
|
||||||
* to the "*:port" only and ignore the other bindings
|
* configuration as a default server for given address:port
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (addr[last - 1].opt.wildcard) {
|
addr = port[p].addrs.elts;
|
||||||
addr[last - 1].opt.bind = 1;
|
for (a = 0; a < port[p].addrs.nelts; a++) {
|
||||||
bind_wildcard = 1;
|
|
||||||
|
|
||||||
} else {
|
if (addr[a].servers.nelts > 1
|
||||||
bind_wildcard = 0;
|
#if (NGX_PCRE)
|
||||||
|
|| addr[a].default_server->captures
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (ngx_stream_server_names(cf, cmcf, &addr[a]) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
if (ngx_stream_init_listening(cf, &port[p]) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (i < last) {
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (bind_wildcard && !addr[i].opt.bind) {
|
|
||||||
i++;
|
static ngx_int_t
|
||||||
|
ngx_stream_server_names(ngx_conf_t *cf, ngx_stream_core_main_conf_t *cmcf,
|
||||||
|
ngx_stream_conf_addr_t *addr)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_uint_t n, s;
|
||||||
|
ngx_hash_init_t hash;
|
||||||
|
ngx_hash_keys_arrays_t ha;
|
||||||
|
ngx_stream_server_name_t *name;
|
||||||
|
ngx_stream_core_srv_conf_t **cscfp;
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
ngx_uint_t regex, i;
|
||||||
|
|
||||||
|
regex = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ngx_memzero(&ha, sizeof(ngx_hash_keys_arrays_t));
|
||||||
|
|
||||||
|
ha.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
|
||||||
|
if (ha.temp_pool == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha.pool = cf->pool;
|
||||||
|
|
||||||
|
if (ngx_hash_keys_array_init(&ha, NGX_HASH_LARGE) != NGX_OK) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
cscfp = addr->servers.elts;
|
||||||
|
|
||||||
|
for (s = 0; s < addr->servers.nelts; s++) {
|
||||||
|
|
||||||
|
name = cscfp[s]->server_names.elts;
|
||||||
|
|
||||||
|
for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
|
||||||
|
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
if (name[n].regex) {
|
||||||
|
regex++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ls = ngx_create_listening(cf, addr[i].opt.sockaddr,
|
rc = ngx_hash_add_key(&ha, &name[n].name, name[n].server,
|
||||||
addr[i].opt.socklen);
|
NGX_HASH_WILDCARD_KEY);
|
||||||
if (ls == NULL) {
|
|
||||||
return NGX_CONF_ERROR;
|
if (rc == NGX_ERROR) {
|
||||||
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
ls->addr_ntop = 1;
|
if (rc == NGX_DECLINED) {
|
||||||
ls->handler = ngx_stream_init_connection;
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
ls->pool_size = 256;
|
"invalid server name or wildcard \"%V\" on %V",
|
||||||
ls->type = addr[i].opt.type;
|
&name[n].name, &addr->opt.addr_text);
|
||||||
|
goto failed;
|
||||||
cscf = addr->opt.ctx->srv_conf[ngx_stream_core_module.ctx_index];
|
|
||||||
|
|
||||||
ls->logp = cscf->error_log;
|
|
||||||
ls->log.data = &ls->addr_text;
|
|
||||||
ls->log.handler = ngx_accept_log_error;
|
|
||||||
|
|
||||||
ls->backlog = addr[i].opt.backlog;
|
|
||||||
ls->rcvbuf = addr[i].opt.rcvbuf;
|
|
||||||
ls->sndbuf = addr[i].opt.sndbuf;
|
|
||||||
|
|
||||||
ls->wildcard = addr[i].opt.wildcard;
|
|
||||||
|
|
||||||
ls->keepalive = addr[i].opt.so_keepalive;
|
|
||||||
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
|
|
||||||
ls->keepidle = addr[i].opt.tcp_keepidle;
|
|
||||||
ls->keepintvl = addr[i].opt.tcp_keepintvl;
|
|
||||||
ls->keepcnt = addr[i].opt.tcp_keepcnt;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (NGX_HAVE_INET6)
|
|
||||||
ls->ipv6only = addr[i].opt.ipv6only;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
|
||||||
ls->fastopen = addr[i].opt.fastopen;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (NGX_HAVE_REUSEPORT)
|
|
||||||
ls->reuseport = addr[i].opt.reuseport;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stport = ngx_palloc(cf->pool, sizeof(ngx_stream_port_t));
|
|
||||||
if (stport == NULL) {
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ls->servers = stport;
|
if (rc == NGX_BUSY) {
|
||||||
|
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
||||||
stport->naddrs = i + 1;
|
"conflicting server name \"%V\" on %V, ignored",
|
||||||
|
&name[n].name, &addr->opt.addr_text);
|
||||||
switch (ls->sockaddr->sa_family) {
|
|
||||||
#if (NGX_HAVE_INET6)
|
|
||||||
case AF_INET6:
|
|
||||||
if (ngx_stream_add_addrs6(cf, stport, addr) != NGX_OK) {
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default: /* AF_INET */
|
|
||||||
if (ngx_stream_add_addrs(cf, stport, addr) != NGX_OK) {
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addr++;
|
|
||||||
last--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
hash.key = ngx_hash_key_lc;
|
||||||
}
|
hash.max_size = cmcf->server_names_hash_max_size;
|
||||||
|
hash.bucket_size = cmcf->server_names_hash_bucket_size;
|
||||||
|
hash.name = "server_names_hash";
|
||||||
|
hash.pool = cf->pool;
|
||||||
|
|
||||||
|
if (ha.keys.nelts) {
|
||||||
|
hash.hash = &addr->hash;
|
||||||
|
hash.temp_pool = NULL;
|
||||||
|
|
||||||
static ngx_int_t
|
if (ngx_hash_init(&hash, ha.keys.elts, ha.keys.nelts) != NGX_OK) {
|
||||||
ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport,
|
goto failed;
|
||||||
ngx_stream_conf_addr_t *addr)
|
}
|
||||||
{
|
}
|
||||||
ngx_uint_t i;
|
|
||||||
struct sockaddr_in *sin;
|
|
||||||
ngx_stream_in_addr_t *addrs;
|
|
||||||
|
|
||||||
stport->addrs = ngx_pcalloc(cf->pool,
|
if (ha.dns_wc_head.nelts) {
|
||||||
stport->naddrs * sizeof(ngx_stream_in_addr_t));
|
|
||||||
if (stport->addrs == NULL) {
|
ngx_qsort(ha.dns_wc_head.elts, (size_t) ha.dns_wc_head.nelts,
|
||||||
|
sizeof(ngx_hash_key_t), ngx_stream_cmp_dns_wildcards);
|
||||||
|
|
||||||
|
hash.hash = NULL;
|
||||||
|
hash.temp_pool = ha.temp_pool;
|
||||||
|
|
||||||
|
if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
|
||||||
|
ha.dns_wc_head.nelts)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr->wc_head = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ha.dns_wc_tail.nelts) {
|
||||||
|
|
||||||
|
ngx_qsort(ha.dns_wc_tail.elts, (size_t) ha.dns_wc_tail.nelts,
|
||||||
|
sizeof(ngx_hash_key_t), ngx_stream_cmp_dns_wildcards);
|
||||||
|
|
||||||
|
hash.hash = NULL;
|
||||||
|
hash.temp_pool = ha.temp_pool;
|
||||||
|
|
||||||
|
if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
|
||||||
|
ha.dns_wc_tail.nelts)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr->wc_tail = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_destroy_pool(ha.temp_pool);
|
||||||
|
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
|
||||||
|
if (regex == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr->nregex = regex;
|
||||||
|
addr->regex = ngx_palloc(cf->pool,
|
||||||
|
regex * sizeof(ngx_stream_server_name_t));
|
||||||
|
if (addr->regex == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
addrs = stport->addrs;
|
i = 0;
|
||||||
|
|
||||||
for (i = 0; i < stport->naddrs; i++) {
|
for (s = 0; s < addr->servers.nelts; s++) {
|
||||||
|
|
||||||
sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
|
name = cscfp[s]->server_names.elts;
|
||||||
addrs[i].addr = sin->sin_addr.s_addr;
|
|
||||||
|
|
||||||
addrs[i].conf.ctx = addr[i].opt.ctx;
|
for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
|
||||||
#if (NGX_STREAM_SSL)
|
if (name[n].regex) {
|
||||||
addrs[i].conf.ssl = addr[i].opt.ssl;
|
addr->regex[i++] = name[n];
|
||||||
#endif
|
}
|
||||||
addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
|
}
|
||||||
addrs[i].conf.addr_text = addr[i].opt.addr_text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
ngx_destroy_pool(ha.temp_pool);
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if (NGX_HAVE_INET6)
|
|
||||||
|
|
||||||
static ngx_int_t
|
|
||||||
ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport,
|
|
||||||
ngx_stream_conf_addr_t *addr)
|
|
||||||
{
|
|
||||||
ngx_uint_t i;
|
|
||||||
struct sockaddr_in6 *sin6;
|
|
||||||
ngx_stream_in6_addr_t *addrs6;
|
|
||||||
|
|
||||||
stport->addrs = ngx_pcalloc(cf->pool,
|
|
||||||
stport->naddrs * sizeof(ngx_stream_in6_addr_t));
|
|
||||||
if (stport->addrs == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs6 = stport->addrs;
|
|
||||||
|
|
||||||
for (i = 0; i < stport->naddrs; i++) {
|
|
||||||
|
|
||||||
sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
|
|
||||||
addrs6[i].addr6 = sin6->sin6_addr;
|
|
||||||
|
|
||||||
addrs6[i].conf.ctx = addr[i].opt.ctx;
|
|
||||||
#if (NGX_STREAM_SSL)
|
|
||||||
addrs6[i].conf.ssl = addr[i].opt.ssl;
|
|
||||||
#endif
|
|
||||||
addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
|
|
||||||
addrs6[i].conf.addr_text = addr[i].opt.addr_text;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NGX_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_cmp_conf_addrs(const void *one, const void *two)
|
ngx_stream_cmp_conf_addrs(const void *one, const void *two)
|
||||||
{
|
{
|
||||||
@@ -630,12 +876,12 @@ ngx_stream_cmp_conf_addrs(const void *one, const void *two)
|
|||||||
second = (ngx_stream_conf_addr_t *) two;
|
second = (ngx_stream_conf_addr_t *) two;
|
||||||
|
|
||||||
if (first->opt.wildcard) {
|
if (first->opt.wildcard) {
|
||||||
/* a wildcard must be the last resort, shift it to the end */
|
/* a wildcard address must be the last resort, shift it to the end */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (second->opt.wildcard) {
|
if (second->opt.wildcard) {
|
||||||
/* a wildcard must be the last resort, shift it to the end */
|
/* a wildcard address must be the last resort, shift it to the end */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,3 +899,277 @@ ngx_stream_cmp_conf_addrs(const void *one, const void *two)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ngx_libc_cdecl
|
||||||
|
ngx_stream_cmp_dns_wildcards(const void *one, const void *two)
|
||||||
|
{
|
||||||
|
ngx_hash_key_t *first, *second;
|
||||||
|
|
||||||
|
first = (ngx_hash_key_t *) one;
|
||||||
|
second = (ngx_hash_key_t *) two;
|
||||||
|
|
||||||
|
return ngx_dns_strcmp(first->key.data, second->key.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_init_listening(ngx_conf_t *cf, ngx_stream_conf_port_t *port)
|
||||||
|
{
|
||||||
|
ngx_uint_t i, last, bind_wildcard;
|
||||||
|
ngx_listening_t *ls;
|
||||||
|
ngx_stream_port_t *stport;
|
||||||
|
ngx_stream_conf_addr_t *addr;
|
||||||
|
|
||||||
|
addr = port->addrs.elts;
|
||||||
|
last = port->addrs.nelts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is a binding to an "*:port" then we need to bind() to
|
||||||
|
* the "*:port" only and ignore other implicit bindings. The bindings
|
||||||
|
* have been already sorted: explicit bindings are on the start, then
|
||||||
|
* implicit bindings go, and wildcard binding is in the end.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (addr[last - 1].opt.wildcard) {
|
||||||
|
addr[last - 1].opt.bind = 1;
|
||||||
|
bind_wildcard = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
bind_wildcard = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
while (i < last) {
|
||||||
|
|
||||||
|
if (bind_wildcard && !addr[i].opt.bind) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls = ngx_stream_add_listening(cf, &addr[i]);
|
||||||
|
if (ls == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
stport = ngx_pcalloc(cf->pool, sizeof(ngx_stream_port_t));
|
||||||
|
if (stport == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls->servers = stport;
|
||||||
|
|
||||||
|
stport->naddrs = i + 1;
|
||||||
|
|
||||||
|
switch (ls->sockaddr->sa_family) {
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
case AF_INET6:
|
||||||
|
if (ngx_stream_add_addrs6(cf, stport, addr) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default: /* AF_INET */
|
||||||
|
if (ngx_stream_add_addrs(cf, stport, addr) != NGX_OK) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr++;
|
||||||
|
last--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_listening_t *
|
||||||
|
ngx_stream_add_listening(ngx_conf_t *cf, ngx_stream_conf_addr_t *addr)
|
||||||
|
{
|
||||||
|
ngx_listening_t *ls;
|
||||||
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
|
ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen);
|
||||||
|
if (ls == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls->addr_ntop = 1;
|
||||||
|
|
||||||
|
ls->handler = ngx_stream_init_connection;
|
||||||
|
|
||||||
|
ls->pool_size = 256;
|
||||||
|
|
||||||
|
cscf = addr->default_server;
|
||||||
|
|
||||||
|
ls->logp = cscf->error_log;
|
||||||
|
ls->log.data = &ls->addr_text;
|
||||||
|
ls->log.handler = ngx_accept_log_error;
|
||||||
|
|
||||||
|
ls->type = addr->opt.type;
|
||||||
|
ls->backlog = addr->opt.backlog;
|
||||||
|
ls->rcvbuf = addr->opt.rcvbuf;
|
||||||
|
ls->sndbuf = addr->opt.sndbuf;
|
||||||
|
|
||||||
|
ls->keepalive = addr->opt.so_keepalive;
|
||||||
|
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
|
||||||
|
ls->keepidle = addr->opt.tcp_keepidle;
|
||||||
|
ls->keepintvl = addr->opt.tcp_keepintvl;
|
||||||
|
ls->keepcnt = addr->opt.tcp_keepcnt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||||
|
ls->accept_filter = addr->opt.accept_filter;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
|
||||||
|
ls->deferred_accept = addr->opt.deferred_accept;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
ls->ipv6only = addr->opt.ipv6only;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_SETFIB)
|
||||||
|
ls->setfib = addr->opt.setfib;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||||
|
ls->fastopen = addr->opt.fastopen;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_REUSEPORT)
|
||||||
|
ls->reuseport = addr->opt.reuseport;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ls->wildcard = addr->opt.wildcard;
|
||||||
|
|
||||||
|
return ls;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_add_addrs(ngx_conf_t *cf, ngx_stream_port_t *stport,
|
||||||
|
ngx_stream_conf_addr_t *addr)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
struct sockaddr_in *sin;
|
||||||
|
ngx_stream_in_addr_t *addrs;
|
||||||
|
ngx_stream_virtual_names_t *vn;
|
||||||
|
|
||||||
|
stport->addrs = ngx_pcalloc(cf->pool,
|
||||||
|
stport->naddrs * sizeof(ngx_stream_in_addr_t));
|
||||||
|
if (stport->addrs == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs = stport->addrs;
|
||||||
|
|
||||||
|
for (i = 0; i < stport->naddrs; i++) {
|
||||||
|
|
||||||
|
sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
|
||||||
|
addrs[i].addr = sin->sin_addr.s_addr;
|
||||||
|
addrs[i].conf.default_server = addr[i].default_server;
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
addrs[i].conf.ssl = addr[i].opt.ssl;
|
||||||
|
#endif
|
||||||
|
addrs[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
|
||||||
|
|
||||||
|
if (addr[i].hash.buckets == NULL
|
||||||
|
&& (addr[i].wc_head == NULL
|
||||||
|
|| addr[i].wc_head->hash.buckets == NULL)
|
||||||
|
&& (addr[i].wc_tail == NULL
|
||||||
|
|| addr[i].wc_tail->hash.buckets == NULL)
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
&& addr[i].nregex == 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vn = ngx_palloc(cf->pool, sizeof(ngx_stream_virtual_names_t));
|
||||||
|
if (vn == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs[i].conf.virtual_names = vn;
|
||||||
|
|
||||||
|
vn->names.hash = addr[i].hash;
|
||||||
|
vn->names.wc_head = addr[i].wc_head;
|
||||||
|
vn->names.wc_tail = addr[i].wc_tail;
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
vn->nregex = addr[i].nregex;
|
||||||
|
vn->regex = addr[i].regex;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_add_addrs6(ngx_conf_t *cf, ngx_stream_port_t *stport,
|
||||||
|
ngx_stream_conf_addr_t *addr)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
struct sockaddr_in6 *sin6;
|
||||||
|
ngx_stream_in6_addr_t *addrs6;
|
||||||
|
ngx_stream_virtual_names_t *vn;
|
||||||
|
|
||||||
|
stport->addrs = ngx_pcalloc(cf->pool,
|
||||||
|
stport->naddrs * sizeof(ngx_stream_in6_addr_t));
|
||||||
|
if (stport->addrs == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs6 = stport->addrs;
|
||||||
|
|
||||||
|
for (i = 0; i < stport->naddrs; i++) {
|
||||||
|
|
||||||
|
sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
|
||||||
|
addrs6[i].addr6 = sin6->sin6_addr;
|
||||||
|
addrs6[i].conf.default_server = addr[i].default_server;
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
addrs6[i].conf.ssl = addr[i].opt.ssl;
|
||||||
|
#endif
|
||||||
|
addrs6[i].conf.proxy_protocol = addr[i].opt.proxy_protocol;
|
||||||
|
|
||||||
|
if (addr[i].hash.buckets == NULL
|
||||||
|
&& (addr[i].wc_head == NULL
|
||||||
|
|| addr[i].wc_head->hash.buckets == NULL)
|
||||||
|
&& (addr[i].wc_tail == NULL
|
||||||
|
|| addr[i].wc_tail->hash.buckets == NULL)
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
&& addr[i].nregex == 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vn = ngx_palloc(cf->pool, sizeof(ngx_stream_virtual_names_t));
|
||||||
|
if (vn == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs6[i].conf.virtual_names = vn;
|
||||||
|
|
||||||
|
vn->names.hash = addr[i].hash;
|
||||||
|
vn->names.wc_head = addr[i].wc_head;
|
||||||
|
vn->names.wc_tail = addr[i].wc_tail;
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
vn->nregex = addr[i].nregex;
|
||||||
|
vn->regex = addr[i].regex;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+126
-55
@@ -45,74 +45,39 @@ typedef struct {
|
|||||||
socklen_t socklen;
|
socklen_t socklen;
|
||||||
ngx_str_t addr_text;
|
ngx_str_t addr_text;
|
||||||
|
|
||||||
/* server ctx */
|
unsigned set:1;
|
||||||
ngx_stream_conf_ctx_t *ctx;
|
unsigned default_server:1;
|
||||||
|
|
||||||
unsigned bind:1;
|
unsigned bind:1;
|
||||||
unsigned wildcard:1;
|
unsigned wildcard:1;
|
||||||
unsigned ssl:1;
|
unsigned ssl:1;
|
||||||
#if (NGX_HAVE_INET6)
|
#if (NGX_HAVE_INET6)
|
||||||
unsigned ipv6only:1;
|
unsigned ipv6only:1;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned deferred_accept:1;
|
||||||
unsigned reuseport:1;
|
unsigned reuseport:1;
|
||||||
unsigned so_keepalive:2;
|
unsigned so_keepalive:2;
|
||||||
unsigned proxy_protocol:1;
|
unsigned proxy_protocol:1;
|
||||||
|
|
||||||
|
int backlog;
|
||||||
|
int rcvbuf;
|
||||||
|
int sndbuf;
|
||||||
|
int type;
|
||||||
|
#if (NGX_HAVE_SETFIB)
|
||||||
|
int setfib;
|
||||||
|
#endif
|
||||||
|
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||||
|
int fastopen;
|
||||||
|
#endif
|
||||||
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
|
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
|
||||||
int tcp_keepidle;
|
int tcp_keepidle;
|
||||||
int tcp_keepintvl;
|
int tcp_keepintvl;
|
||||||
int tcp_keepcnt;
|
int tcp_keepcnt;
|
||||||
#endif
|
#endif
|
||||||
int backlog;
|
|
||||||
int rcvbuf;
|
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||||
int sndbuf;
|
char *accept_filter;
|
||||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
|
||||||
int fastopen;
|
|
||||||
#endif
|
#endif
|
||||||
int type;
|
} ngx_stream_listen_opt_t;
|
||||||
} ngx_stream_listen_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ngx_stream_conf_ctx_t *ctx;
|
|
||||||
ngx_str_t addr_text;
|
|
||||||
unsigned ssl:1;
|
|
||||||
unsigned proxy_protocol:1;
|
|
||||||
} ngx_stream_addr_conf_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
in_addr_t addr;
|
|
||||||
ngx_stream_addr_conf_t conf;
|
|
||||||
} ngx_stream_in_addr_t;
|
|
||||||
|
|
||||||
|
|
||||||
#if (NGX_HAVE_INET6)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
struct in6_addr addr6;
|
|
||||||
ngx_stream_addr_conf_t conf;
|
|
||||||
} ngx_stream_in6_addr_t;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* ngx_stream_in_addr_t or ngx_stream_in6_addr_t */
|
|
||||||
void *addrs;
|
|
||||||
ngx_uint_t naddrs;
|
|
||||||
} ngx_stream_port_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int family;
|
|
||||||
int type;
|
|
||||||
in_port_t port;
|
|
||||||
ngx_array_t addrs; /* array of ngx_stream_conf_addr_t */
|
|
||||||
} ngx_stream_conf_port_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
ngx_stream_listen_t opt;
|
|
||||||
} ngx_stream_conf_addr_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -153,7 +118,6 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_array_t servers; /* ngx_stream_core_srv_conf_t */
|
ngx_array_t servers; /* ngx_stream_core_srv_conf_t */
|
||||||
ngx_array_t listen; /* ngx_stream_listen_t */
|
|
||||||
|
|
||||||
ngx_stream_phase_engine_t phase_engine;
|
ngx_stream_phase_engine_t phase_engine;
|
||||||
|
|
||||||
@@ -163,16 +127,24 @@ typedef struct {
|
|||||||
ngx_array_t prefix_variables; /* ngx_stream_variable_t */
|
ngx_array_t prefix_variables; /* ngx_stream_variable_t */
|
||||||
ngx_uint_t ncaptures;
|
ngx_uint_t ncaptures;
|
||||||
|
|
||||||
|
ngx_uint_t server_names_hash_max_size;
|
||||||
|
ngx_uint_t server_names_hash_bucket_size;
|
||||||
|
|
||||||
ngx_uint_t variables_hash_max_size;
|
ngx_uint_t variables_hash_max_size;
|
||||||
ngx_uint_t variables_hash_bucket_size;
|
ngx_uint_t variables_hash_bucket_size;
|
||||||
|
|
||||||
ngx_hash_keys_arrays_t *variables_keys;
|
ngx_hash_keys_arrays_t *variables_keys;
|
||||||
|
|
||||||
|
ngx_array_t *ports;
|
||||||
|
|
||||||
ngx_stream_phase_t phases[NGX_STREAM_LOG_PHASE + 1];
|
ngx_stream_phase_t phases[NGX_STREAM_LOG_PHASE + 1];
|
||||||
} ngx_stream_core_main_conf_t;
|
} ngx_stream_core_main_conf_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
/* array of the ngx_stream_server_name_t, "server_name" directive */
|
||||||
|
ngx_array_t server_names;
|
||||||
|
|
||||||
ngx_stream_content_handler_pt handler;
|
ngx_stream_content_handler_pt handler;
|
||||||
|
|
||||||
ngx_stream_conf_ctx_t *ctx;
|
ngx_stream_conf_ctx_t *ctx;
|
||||||
@@ -180,6 +152,8 @@ typedef struct {
|
|||||||
u_char *file_name;
|
u_char *file_name;
|
||||||
ngx_uint_t line;
|
ngx_uint_t line;
|
||||||
|
|
||||||
|
ngx_str_t server_name;
|
||||||
|
|
||||||
ngx_flag_t tcp_nodelay;
|
ngx_flag_t tcp_nodelay;
|
||||||
size_t preread_buffer_size;
|
size_t preread_buffer_size;
|
||||||
ngx_msec_t preread_timeout;
|
ngx_msec_t preread_timeout;
|
||||||
@@ -191,10 +165,98 @@ typedef struct {
|
|||||||
|
|
||||||
ngx_msec_t proxy_protocol_timeout;
|
ngx_msec_t proxy_protocol_timeout;
|
||||||
|
|
||||||
ngx_uint_t listen; /* unsigned listen:1; */
|
unsigned listen:1;
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
unsigned captures:1;
|
||||||
|
#endif
|
||||||
} ngx_stream_core_srv_conf_t;
|
} ngx_stream_core_srv_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* list of structures to find core_srv_conf quickly at run time */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
ngx_stream_regex_t *regex;
|
||||||
|
#endif
|
||||||
|
ngx_stream_core_srv_conf_t *server; /* virtual name server conf */
|
||||||
|
ngx_str_t name;
|
||||||
|
} ngx_stream_server_name_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_hash_combined_t names;
|
||||||
|
|
||||||
|
ngx_uint_t nregex;
|
||||||
|
ngx_stream_server_name_t *regex;
|
||||||
|
} ngx_stream_virtual_names_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* the default server configuration for this address:port */
|
||||||
|
ngx_stream_core_srv_conf_t *default_server;
|
||||||
|
|
||||||
|
ngx_stream_virtual_names_t *virtual_names;
|
||||||
|
|
||||||
|
unsigned ssl:1;
|
||||||
|
unsigned proxy_protocol:1;
|
||||||
|
} ngx_stream_addr_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
in_addr_t addr;
|
||||||
|
ngx_stream_addr_conf_t conf;
|
||||||
|
} ngx_stream_in_addr_t;
|
||||||
|
|
||||||
|
|
||||||
|
#if (NGX_HAVE_INET6)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct in6_addr addr6;
|
||||||
|
ngx_stream_addr_conf_t conf;
|
||||||
|
} ngx_stream_in6_addr_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* ngx_stream_in_addr_t or ngx_stream_in6_addr_t */
|
||||||
|
void *addrs;
|
||||||
|
ngx_uint_t naddrs;
|
||||||
|
} ngx_stream_port_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int family;
|
||||||
|
int type;
|
||||||
|
in_port_t port;
|
||||||
|
ngx_array_t addrs; /* array of ngx_stream_conf_addr_t */
|
||||||
|
} ngx_stream_conf_port_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_stream_listen_opt_t opt;
|
||||||
|
|
||||||
|
unsigned protocols:3;
|
||||||
|
unsigned protocols_set:1;
|
||||||
|
unsigned protocols_changed:1;
|
||||||
|
|
||||||
|
ngx_hash_t hash;
|
||||||
|
ngx_hash_wildcard_t *wc_head;
|
||||||
|
ngx_hash_wildcard_t *wc_tail;
|
||||||
|
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
ngx_uint_t nregex;
|
||||||
|
ngx_stream_server_name_t *regex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the default server configuration for this address:port */
|
||||||
|
ngx_stream_core_srv_conf_t *default_server;
|
||||||
|
ngx_array_t servers;
|
||||||
|
/* array of ngx_stream_core_srv_conf_t */
|
||||||
|
} ngx_stream_conf_addr_t;
|
||||||
|
|
||||||
|
|
||||||
struct ngx_stream_session_s {
|
struct ngx_stream_session_s {
|
||||||
uint32_t signature; /* "STRM" */
|
uint32_t signature; /* "STRM" */
|
||||||
|
|
||||||
@@ -210,6 +272,8 @@ struct ngx_stream_session_s {
|
|||||||
void **main_conf;
|
void **main_conf;
|
||||||
void **srv_conf;
|
void **srv_conf;
|
||||||
|
|
||||||
|
ngx_stream_virtual_names_t *virtual_names;
|
||||||
|
|
||||||
ngx_stream_upstream_t *upstream;
|
ngx_stream_upstream_t *upstream;
|
||||||
ngx_array_t *upstream_states;
|
ngx_array_t *upstream_states;
|
||||||
/* of ngx_stream_upstream_state_t */
|
/* of ngx_stream_upstream_state_t */
|
||||||
@@ -283,6 +347,9 @@ typedef struct {
|
|||||||
#define NGX_STREAM_WRITE_BUFFERED 0x10
|
#define NGX_STREAM_WRITE_BUFFERED 0x10
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t ngx_stream_add_listen(ngx_conf_t *cf,
|
||||||
|
ngx_stream_core_srv_conf_t *cscf, ngx_stream_listen_opt_t *lsopt);
|
||||||
|
|
||||||
void ngx_stream_core_run_phases(ngx_stream_session_t *s);
|
void ngx_stream_core_run_phases(ngx_stream_session_t *s);
|
||||||
ngx_int_t ngx_stream_core_generic_phase(ngx_stream_session_t *s,
|
ngx_int_t ngx_stream_core_generic_phase(ngx_stream_session_t *s,
|
||||||
ngx_stream_phase_handler_t *ph);
|
ngx_stream_phase_handler_t *ph);
|
||||||
@@ -291,6 +358,10 @@ ngx_int_t ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
|||||||
ngx_int_t ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
ngx_int_t ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
||||||
ngx_stream_phase_handler_t *ph);
|
ngx_stream_phase_handler_t *ph);
|
||||||
|
|
||||||
|
ngx_int_t ngx_stream_validate_host(ngx_str_t *host, ngx_pool_t *pool,
|
||||||
|
ngx_uint_t alloc);
|
||||||
|
ngx_int_t ngx_stream_find_virtual_server(ngx_stream_session_t *s,
|
||||||
|
ngx_str_t *host, ngx_stream_core_srv_conf_t **cscfp);
|
||||||
|
|
||||||
void ngx_stream_init_connection(ngx_connection_t *c);
|
void ngx_stream_init_connection(ngx_connection_t *c);
|
||||||
void ngx_stream_session_handler(ngx_event_t *rev);
|
void ngx_stream_session_handler(ngx_event_t *rev);
|
||||||
|
|||||||
+602
-163
@@ -10,6 +10,11 @@
|
|||||||
#include <ngx_stream.h>
|
#include <ngx_stream.h>
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_uint_t ngx_stream_preread_can_peek(ngx_connection_t *c);
|
||||||
|
static ngx_int_t ngx_stream_preread_peek(ngx_stream_session_t *s,
|
||||||
|
ngx_stream_phase_handler_t *ph);
|
||||||
|
static ngx_int_t ngx_stream_preread(ngx_stream_session_t *s,
|
||||||
|
ngx_stream_phase_handler_t *ph);
|
||||||
static ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf);
|
static ngx_int_t ngx_stream_core_preconfiguration(ngx_conf_t *cf);
|
||||||
static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf);
|
static void *ngx_stream_core_create_main_conf(ngx_conf_t *cf);
|
||||||
static char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf);
|
static char *ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf);
|
||||||
@@ -22,6 +27,8 @@ static char *ngx_stream_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||||||
void *conf);
|
void *conf);
|
||||||
static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
|
static char *ngx_stream_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
|
void *conf);
|
||||||
static char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
|
|
||||||
@@ -42,6 +49,20 @@ static ngx_command_t ngx_stream_core_commands[] = {
|
|||||||
offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size),
|
offsetof(ngx_stream_core_main_conf_t, variables_hash_bucket_size),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("server_names_hash_max_size"),
|
||||||
|
NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_num_slot,
|
||||||
|
NGX_STREAM_MAIN_CONF_OFFSET,
|
||||||
|
offsetof(ngx_stream_core_main_conf_t, server_names_hash_max_size),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("server_names_hash_bucket_size"),
|
||||||
|
NGX_STREAM_MAIN_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_num_slot,
|
||||||
|
NGX_STREAM_MAIN_CONF_OFFSET,
|
||||||
|
offsetof(ngx_stream_core_main_conf_t, server_names_hash_bucket_size),
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("server"),
|
{ ngx_string("server"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
|
NGX_STREAM_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
|
||||||
ngx_stream_core_server,
|
ngx_stream_core_server,
|
||||||
@@ -56,6 +77,13 @@ static ngx_command_t ngx_stream_core_commands[] = {
|
|||||||
0,
|
0,
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("server_name"),
|
||||||
|
NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
||||||
|
ngx_stream_core_server_name,
|
||||||
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("error_log"),
|
{ ngx_string("error_log"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
||||||
ngx_stream_core_error_log,
|
ngx_stream_core_error_log,
|
||||||
@@ -203,8 +231,6 @@ ngx_int_t
|
|||||||
ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
||||||
ngx_stream_phase_handler_t *ph)
|
ngx_stream_phase_handler_t *ph)
|
||||||
{
|
{
|
||||||
size_t size;
|
|
||||||
ssize_t n;
|
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
ngx_stream_core_srv_conf_t *cscf;
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
@@ -217,56 +243,33 @@ ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
|||||||
|
|
||||||
if (c->read->timedout) {
|
if (c->read->timedout) {
|
||||||
rc = NGX_STREAM_OK;
|
rc = NGX_STREAM_OK;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (c->read->timer_set) {
|
if (!c->read->timer_set) {
|
||||||
rc = NGX_AGAIN;
|
rc = ph->handler(s);
|
||||||
|
|
||||||
|
if (rc != NGX_AGAIN) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->buffer == NULL) {
|
||||||
|
c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
|
||||||
|
if (c->buffer == NULL) {
|
||||||
|
rc = NGX_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_stream_preread_can_peek(c)) {
|
||||||
|
rc = ngx_stream_preread_peek(s, ph);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rc = ph->handler(s);
|
rc = ngx_stream_preread(s, ph);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (rc == NGX_AGAIN) {
|
done:
|
||||||
|
|
||||||
if (c->buffer == NULL) {
|
|
||||||
c->buffer = ngx_create_temp_buf(c->pool, cscf->preread_buffer_size);
|
|
||||||
if (c->buffer == NULL) {
|
|
||||||
rc = NGX_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size = c->buffer->end - c->buffer->last;
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
|
|
||||||
rc = NGX_STREAM_BAD_REQUEST;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c->read->eof) {
|
|
||||||
rc = NGX_STREAM_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c->read->ready) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = c->recv(c, c->buffer->last, size);
|
|
||||||
|
|
||||||
if (n == NGX_ERROR || n == 0) {
|
|
||||||
rc = NGX_STREAM_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == NGX_AGAIN) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->buffer->last += n;
|
|
||||||
|
|
||||||
rc = ph->handler(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||||||
@@ -311,6 +314,129 @@ ngx_stream_core_preread_phase(ngx_stream_session_t *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_uint_t
|
||||||
|
ngx_stream_preread_can_peek(ngx_connection_t *c)
|
||||||
|
{
|
||||||
|
#if (NGX_STREAM_SSL)
|
||||||
|
if (c->ssl) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((ngx_event_flags & NGX_USE_CLEAR_EVENT) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (NGX_HAVE_KQUEUE)
|
||||||
|
if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_EPOLLRDHUP)
|
||||||
|
if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_preread_peek(ngx_stream_session_t *s, ngx_stream_phase_handler_t *ph)
|
||||||
|
{
|
||||||
|
ssize_t n;
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_err_t err;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
|
||||||
|
c = s->connection;
|
||||||
|
|
||||||
|
n = recv(c->fd, (char *) c->buffer->last,
|
||||||
|
c->buffer->end - c->buffer->last, MSG_PEEK);
|
||||||
|
|
||||||
|
err = ngx_socket_errno;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0, "stream recv(): %z", n);
|
||||||
|
|
||||||
|
if (n == -1) {
|
||||||
|
if (err == NGX_EAGAIN) {
|
||||||
|
c->read->ready = 0;
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_connection_error(c, err, "recv() failed");
|
||||||
|
return NGX_STREAM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
return NGX_STREAM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->buffer->last += n;
|
||||||
|
|
||||||
|
rc = ph->handler(s);
|
||||||
|
|
||||||
|
if (rc != NGX_AGAIN) {
|
||||||
|
c->buffer->last = c->buffer->pos;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->buffer->last == c->buffer->end) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
|
||||||
|
return NGX_STREAM_BAD_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->read->pending_eof) {
|
||||||
|
return NGX_STREAM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->buffer->last = c->buffer->pos;
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_preread(ngx_stream_session_t *s, ngx_stream_phase_handler_t *ph)
|
||||||
|
{
|
||||||
|
ssize_t n;
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
|
||||||
|
c = s->connection;
|
||||||
|
|
||||||
|
while (c->read->ready) {
|
||||||
|
|
||||||
|
n = c->recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
|
||||||
|
|
||||||
|
if (n == NGX_AGAIN) {
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == NGX_ERROR || n == 0) {
|
||||||
|
return NGX_STREAM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->buffer->last += n;
|
||||||
|
|
||||||
|
rc = ph->handler(s);
|
||||||
|
|
||||||
|
if (rc != NGX_AGAIN) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->buffer->last == c->buffer->end) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0, "preread buffer full");
|
||||||
|
return NGX_STREAM_BAD_REQUEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_AGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ngx_int_t
|
ngx_int_t
|
||||||
ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
||||||
ngx_stream_phase_handler_t *ph)
|
ngx_stream_phase_handler_t *ph)
|
||||||
@@ -338,6 +464,149 @@ ngx_stream_core_content_phase(ngx_stream_session_t *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_stream_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
|
||||||
|
{
|
||||||
|
u_char *h, ch;
|
||||||
|
size_t i, dot_pos, host_len;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
sw_usual = 0,
|
||||||
|
sw_literal,
|
||||||
|
sw_rest
|
||||||
|
} state;
|
||||||
|
|
||||||
|
dot_pos = host->len;
|
||||||
|
host_len = host->len;
|
||||||
|
|
||||||
|
h = host->data;
|
||||||
|
|
||||||
|
state = sw_usual;
|
||||||
|
|
||||||
|
for (i = 0; i < host->len; i++) {
|
||||||
|
ch = h[i];
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
|
||||||
|
case '.':
|
||||||
|
if (dot_pos == i - 1) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
dot_pos = i;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
if (state == sw_usual) {
|
||||||
|
host_len = i;
|
||||||
|
state = sw_rest;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
if (i == 0) {
|
||||||
|
state = sw_literal;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ']':
|
||||||
|
if (state == sw_literal) {
|
||||||
|
host_len = i + 1;
|
||||||
|
state = sw_rest;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
if (ngx_path_separator(ch)) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch <= 0x20 || ch == 0x7f) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch >= 'A' && ch <= 'Z') {
|
||||||
|
alloc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dot_pos == host_len - 1) {
|
||||||
|
host_len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (host_len == 0) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alloc) {
|
||||||
|
host->data = ngx_pnalloc(pool, host_len);
|
||||||
|
if (host->data == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_strlow(host->data, h, host_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
host->len = host_len;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngx_int_t
|
||||||
|
ngx_stream_find_virtual_server(ngx_stream_session_t *s,
|
||||||
|
ngx_str_t *host, ngx_stream_core_srv_conf_t **cscfp)
|
||||||
|
{
|
||||||
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
|
if (s->virtual_names == NULL) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
cscf = ngx_hash_find_combined(&s->virtual_names->names,
|
||||||
|
ngx_hash_key(host->data, host->len),
|
||||||
|
host->data, host->len);
|
||||||
|
|
||||||
|
if (cscf) {
|
||||||
|
*cscfp = cscf;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
|
||||||
|
if (host->len && s->virtual_names->nregex) {
|
||||||
|
ngx_int_t n;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_stream_server_name_t *sn;
|
||||||
|
|
||||||
|
sn = s->virtual_names->regex;
|
||||||
|
|
||||||
|
for (i = 0; i < s->virtual_names->nregex; i++) {
|
||||||
|
|
||||||
|
n = ngx_stream_regex_exec(s, sn[i].regex, host);
|
||||||
|
|
||||||
|
if (n == NGX_DECLINED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == NGX_OK) {
|
||||||
|
*cscfp = sn[i].server;
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* NGX_PCRE */
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_core_preconfiguration(ngx_conf_t *cf)
|
ngx_stream_core_preconfiguration(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
@@ -362,11 +631,8 @@ ngx_stream_core_create_main_conf(ngx_conf_t *cf)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_array_init(&cmcf->listen, cf->pool, 4, sizeof(ngx_stream_listen_t))
|
cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
|
||||||
!= NGX_OK)
|
cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
|
cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
|
||||||
cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
|
cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
|
||||||
@@ -380,6 +646,14 @@ ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
|
|||||||
{
|
{
|
||||||
ngx_stream_core_main_conf_t *cmcf = conf;
|
ngx_stream_core_main_conf_t *cmcf = conf;
|
||||||
|
|
||||||
|
ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512);
|
||||||
|
ngx_conf_init_uint_value(cmcf->server_names_hash_bucket_size,
|
||||||
|
ngx_cacheline_size);
|
||||||
|
|
||||||
|
cmcf->server_names_hash_bucket_size =
|
||||||
|
ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
|
||||||
|
|
||||||
|
|
||||||
ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
|
ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
|
||||||
ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
|
ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
|
||||||
|
|
||||||
@@ -411,6 +685,13 @@ ngx_stream_core_create_srv_conf(ngx_conf_t *cf)
|
|||||||
* cscf->error_log = NULL;
|
* cscf->error_log = NULL;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
|
||||||
|
sizeof(ngx_stream_server_name_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cscf->file_name = cf->conf_file->file.name.data;
|
cscf->file_name = cf->conf_file->file.name.data;
|
||||||
cscf->line = cf->conf_file->line;
|
cscf->line = cf->conf_file->line;
|
||||||
cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
|
cscf->resolver_timeout = NGX_CONF_UNSET_MSEC;
|
||||||
@@ -429,6 +710,9 @@ ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_stream_core_srv_conf_t *prev = parent;
|
ngx_stream_core_srv_conf_t *prev = parent;
|
||||||
ngx_stream_core_srv_conf_t *conf = child;
|
ngx_stream_core_srv_conf_t *conf = child;
|
||||||
|
|
||||||
|
ngx_str_t name;
|
||||||
|
ngx_stream_server_name_t *sn;
|
||||||
|
|
||||||
ngx_conf_merge_msec_value(conf->resolver_timeout,
|
ngx_conf_merge_msec_value(conf->resolver_timeout,
|
||||||
prev->resolver_timeout, 30000);
|
prev->resolver_timeout, 30000);
|
||||||
|
|
||||||
@@ -476,6 +760,37 @@ ngx_stream_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_conf_merge_msec_value(conf->preread_timeout,
|
ngx_conf_merge_msec_value(conf->preread_timeout,
|
||||||
prev->preread_timeout, 30000);
|
prev->preread_timeout, 30000);
|
||||||
|
|
||||||
|
if (conf->server_names.nelts == 0) {
|
||||||
|
/* the array has 4 empty preallocated elements, so push cannot fail */
|
||||||
|
sn = ngx_array_push(&conf->server_names);
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
sn->regex = NULL;
|
||||||
|
#endif
|
||||||
|
sn->server = conf;
|
||||||
|
ngx_str_set(&sn->name, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
sn = conf->server_names.elts;
|
||||||
|
name = sn[0].name;
|
||||||
|
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
if (sn->regex) {
|
||||||
|
name.len++;
|
||||||
|
name.data--;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (name.data[0] == '.') {
|
||||||
|
name.len--;
|
||||||
|
name.data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->server_name.len = name.len;
|
||||||
|
conf->server_name.data = ngx_pstrdup(cf->pool, &name);
|
||||||
|
if (conf->server_name.data == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,11 +890,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
{
|
{
|
||||||
ngx_stream_core_srv_conf_t *cscf = conf;
|
ngx_stream_core_srv_conf_t *cscf = conf;
|
||||||
|
|
||||||
ngx_str_t *value, size;
|
ngx_str_t *value, size;
|
||||||
ngx_url_t u;
|
ngx_url_t u;
|
||||||
ngx_uint_t i, n, backlog;
|
ngx_uint_t n, i, backlog;
|
||||||
ngx_stream_listen_t *ls, *als, *nls;
|
ngx_stream_listen_opt_t lsopt;
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
|
||||||
|
|
||||||
cscf->listen = 1;
|
cscf->listen = 1;
|
||||||
|
|
||||||
@@ -600,51 +914,67 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
ngx_memzero(&lsopt, sizeof(ngx_stream_listen_opt_t));
|
||||||
|
|
||||||
ls = ngx_array_push(&cmcf->listen);
|
lsopt.backlog = NGX_LISTEN_BACKLOG;
|
||||||
if (ls == NULL) {
|
lsopt.type = SOCK_STREAM;
|
||||||
return NGX_CONF_ERROR;
|
lsopt.rcvbuf = -1;
|
||||||
}
|
lsopt.sndbuf = -1;
|
||||||
|
#if (NGX_HAVE_SETFIB)
|
||||||
ngx_memzero(ls, sizeof(ngx_stream_listen_t));
|
lsopt.setfib = -1;
|
||||||
|
#endif
|
||||||
ls->backlog = NGX_LISTEN_BACKLOG;
|
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||||
ls->rcvbuf = -1;
|
lsopt.fastopen = -1;
|
||||||
ls->sndbuf = -1;
|
|
||||||
ls->type = SOCK_STREAM;
|
|
||||||
ls->ctx = cf->ctx;
|
|
||||||
|
|
||||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
|
||||||
ls->fastopen = -1;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (NGX_HAVE_INET6)
|
#if (NGX_HAVE_INET6)
|
||||||
ls->ipv6only = 1;
|
lsopt.ipv6only = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
backlog = 0;
|
backlog = 0;
|
||||||
|
|
||||||
for (i = 2; i < cf->args->nelts; i++) {
|
for (i = 2; i < cf->args->nelts; i++) {
|
||||||
|
|
||||||
|
if (ngx_strcmp(value[i].data, "default_server") == 0) {
|
||||||
|
lsopt.default_server = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
#if !(NGX_WIN32)
|
#if !(NGX_WIN32)
|
||||||
if (ngx_strcmp(value[i].data, "udp") == 0) {
|
if (ngx_strcmp(value[i].data, "udp") == 0) {
|
||||||
ls->type = SOCK_DGRAM;
|
lsopt.type = SOCK_DGRAM;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "bind") == 0) {
|
if (ngx_strcmp(value[i].data, "bind") == 0) {
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_HAVE_SETFIB)
|
||||||
|
if (ngx_strncmp(value[i].data, "setfib=", 7) == 0) {
|
||||||
|
lsopt.setfib = ngx_atoi(value[i].data + 7, value[i].len - 7);
|
||||||
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
|
||||||
|
if (lsopt.setfib == NGX_ERROR) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"invalid setfib \"%V\"", &value[i]);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||||
if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) {
|
if (ngx_strncmp(value[i].data, "fastopen=", 9) == 0) {
|
||||||
ls->fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9);
|
lsopt.fastopen = ngx_atoi(value[i].data + 9, value[i].len - 9);
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
|
||||||
if (ls->fastopen == NGX_ERROR) {
|
if (lsopt.fastopen == NGX_ERROR) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid fastopen \"%V\"", &value[i]);
|
"invalid fastopen \"%V\"", &value[i]);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
@@ -655,10 +985,11 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
|
if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) {
|
||||||
ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
|
lsopt.backlog = ngx_atoi(value[i].data + 8, value[i].len - 8);
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
|
||||||
if (ls->backlog == NGX_ERROR || ls->backlog == 0) {
|
if (lsopt.backlog == NGX_ERROR || lsopt.backlog == 0) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid backlog \"%V\"", &value[i]);
|
"invalid backlog \"%V\"", &value[i]);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
@@ -673,10 +1004,11 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
size.len = value[i].len - 7;
|
size.len = value[i].len - 7;
|
||||||
size.data = value[i].data + 7;
|
size.data = value[i].data + 7;
|
||||||
|
|
||||||
ls->rcvbuf = ngx_parse_size(&size);
|
lsopt.rcvbuf = ngx_parse_size(&size);
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
|
||||||
if (ls->rcvbuf == NGX_ERROR) {
|
if (lsopt.rcvbuf == NGX_ERROR) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid rcvbuf \"%V\"", &value[i]);
|
"invalid rcvbuf \"%V\"", &value[i]);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
@@ -689,10 +1021,11 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
size.len = value[i].len - 7;
|
size.len = value[i].len - 7;
|
||||||
size.data = value[i].data + 7;
|
size.data = value[i].data + 7;
|
||||||
|
|
||||||
ls->sndbuf = ngx_parse_size(&size);
|
lsopt.sndbuf = ngx_parse_size(&size);
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
|
||||||
if (ls->sndbuf == NGX_ERROR) {
|
if (lsopt.sndbuf == NGX_ERROR) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid sndbuf \"%V\"", &value[i]);
|
"invalid sndbuf \"%V\"", &value[i]);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
@@ -701,13 +1034,40 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ngx_strncmp(value[i].data, "accept_filter=", 14) == 0) {
|
||||||
|
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||||
|
lsopt.accept_filter = (char *) &value[i].data[14];
|
||||||
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
#else
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"accept filters \"%V\" are not supported "
|
||||||
|
"on this platform, ignored",
|
||||||
|
&value[i]);
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strcmp(value[i].data, "deferred") == 0) {
|
||||||
|
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
|
||||||
|
lsopt.deferred_accept = 1;
|
||||||
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
#else
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"the deferred accept is not supported "
|
||||||
|
"on this platform, ignored");
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
|
if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
|
||||||
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
|
#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
|
||||||
if (ngx_strcmp(&value[i].data[10], "n") == 0) {
|
if (ngx_strcmp(&value[i].data[10], "n") == 0) {
|
||||||
ls->ipv6only = 1;
|
lsopt.ipv6only = 1;
|
||||||
|
|
||||||
} else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
|
} else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
|
||||||
ls->ipv6only = 0;
|
lsopt.ipv6only = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
@@ -716,11 +1076,13 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
#else
|
#else
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"bind ipv6only is not supported "
|
"ipv6only is not supported "
|
||||||
"on this platform");
|
"on this platform");
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
#endif
|
#endif
|
||||||
@@ -728,8 +1090,9 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "reuseport") == 0) {
|
if (ngx_strcmp(value[i].data, "reuseport") == 0) {
|
||||||
#if (NGX_HAVE_REUSEPORT)
|
#if (NGX_HAVE_REUSEPORT)
|
||||||
ls->reuseport = 1;
|
lsopt.reuseport = 1;
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
#else
|
#else
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"reuseport is not supported "
|
"reuseport is not supported "
|
||||||
@@ -740,17 +1103,7 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "ssl") == 0) {
|
if (ngx_strcmp(value[i].data, "ssl") == 0) {
|
||||||
#if (NGX_STREAM_SSL)
|
#if (NGX_STREAM_SSL)
|
||||||
ngx_stream_ssl_conf_t *sslcf;
|
lsopt.ssl = 1;
|
||||||
|
|
||||||
sslcf = ngx_stream_conf_get_module_srv_conf(cf,
|
|
||||||
ngx_stream_ssl_module);
|
|
||||||
|
|
||||||
sslcf->listen = 1;
|
|
||||||
sslcf->file = cf->conf_file->file.name.data;
|
|
||||||
sslcf->line = cf->conf_file->line;
|
|
||||||
|
|
||||||
ls->ssl = 1;
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
#else
|
#else
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
@@ -763,10 +1116,10 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
|
if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) {
|
||||||
|
|
||||||
if (ngx_strcmp(&value[i].data[13], "on") == 0) {
|
if (ngx_strcmp(&value[i].data[13], "on") == 0) {
|
||||||
ls->so_keepalive = 1;
|
lsopt.so_keepalive = 1;
|
||||||
|
|
||||||
} else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
|
} else if (ngx_strcmp(&value[i].data[13], "off") == 0) {
|
||||||
ls->so_keepalive = 2;
|
lsopt.so_keepalive = 2;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@@ -785,8 +1138,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
if (p > s.data) {
|
if (p > s.data) {
|
||||||
s.len = p - s.data;
|
s.len = p - s.data;
|
||||||
|
|
||||||
ls->tcp_keepidle = ngx_parse_time(&s, 1);
|
lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
|
||||||
if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
|
if (lsopt.tcp_keepidle == (time_t) NGX_ERROR) {
|
||||||
goto invalid_so_keepalive;
|
goto invalid_so_keepalive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -801,8 +1154,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
if (p > s.data) {
|
if (p > s.data) {
|
||||||
s.len = p - s.data;
|
s.len = p - s.data;
|
||||||
|
|
||||||
ls->tcp_keepintvl = ngx_parse_time(&s, 1);
|
lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
|
||||||
if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
|
if (lsopt.tcp_keepintvl == (time_t) NGX_ERROR) {
|
||||||
goto invalid_so_keepalive;
|
goto invalid_so_keepalive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -812,19 +1165,19 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
if (s.data < end) {
|
if (s.data < end) {
|
||||||
s.len = end - s.data;
|
s.len = end - s.data;
|
||||||
|
|
||||||
ls->tcp_keepcnt = ngx_atoi(s.data, s.len);
|
lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len);
|
||||||
if (ls->tcp_keepcnt == NGX_ERROR) {
|
if (lsopt.tcp_keepcnt == NGX_ERROR) {
|
||||||
goto invalid_so_keepalive;
|
goto invalid_so_keepalive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0
|
if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0
|
||||||
&& ls->tcp_keepcnt == 0)
|
&& lsopt.tcp_keepcnt == 0)
|
||||||
{
|
{
|
||||||
goto invalid_so_keepalive;
|
goto invalid_so_keepalive;
|
||||||
}
|
}
|
||||||
|
|
||||||
ls->so_keepalive = 1;
|
lsopt.so_keepalive = 1;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -836,7 +1189,8 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ls->bind = 1;
|
lsopt.set = 1;
|
||||||
|
lsopt.bind = 1;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -851,39 +1205,51 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
|
if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
|
||||||
ls->proxy_protocol = 1;
|
lsopt.proxy_protocol = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"the invalid \"%V\" parameter", &value[i]);
|
"invalid parameter \"%V\"", &value[i]);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ls->type == SOCK_DGRAM) {
|
if (lsopt.type == SOCK_DGRAM) {
|
||||||
|
#if (NGX_HAVE_TCP_FASTOPEN)
|
||||||
|
if (lsopt.fastopen != -1) {
|
||||||
|
return "\"fastopen\" parameter is incompatible with \"udp\"";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (backlog) {
|
if (backlog) {
|
||||||
return "\"backlog\" parameter is incompatible with \"udp\"";
|
return "\"backlog\" parameter is incompatible with \"udp\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
|
||||||
|
if (lsopt.accept_filter) {
|
||||||
|
return "\"accept_filter\" parameter is incompatible with \"udp\"";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
|
||||||
|
if (lsopt.deferred_accept) {
|
||||||
|
return "\"deferred\" parameter is incompatible with \"udp\"";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (NGX_STREAM_SSL)
|
#if (NGX_STREAM_SSL)
|
||||||
if (ls->ssl) {
|
if (lsopt.ssl) {
|
||||||
return "\"ssl\" parameter is incompatible with \"udp\"";
|
return "\"ssl\" parameter is incompatible with \"udp\"";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ls->so_keepalive) {
|
if (lsopt.so_keepalive) {
|
||||||
return "\"so_keepalive\" parameter is incompatible with \"udp\"";
|
return "\"so_keepalive\" parameter is incompatible with \"udp\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ls->proxy_protocol) {
|
if (lsopt.proxy_protocol) {
|
||||||
return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
|
return "\"proxy_protocol\" parameter is incompatible with \"udp\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (NGX_HAVE_TCP_FASTOPEN)
|
|
||||||
if (ls->fastopen != -1) {
|
|
||||||
return "\"fastopen\" parameter is incompatible with \"udp\"";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = 0; n < u.naddrs; n++) {
|
for (n = 0; n < u.naddrs; n++) {
|
||||||
@@ -897,40 +1263,12 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n != 0) {
|
lsopt.sockaddr = u.addrs[n].sockaddr;
|
||||||
nls = ngx_array_push(&cmcf->listen);
|
lsopt.socklen = u.addrs[n].socklen;
|
||||||
if (nls == NULL) {
|
lsopt.addr_text = u.addrs[n].name;
|
||||||
return NGX_CONF_ERROR;
|
lsopt.wildcard = ngx_inet_wildcard(lsopt.sockaddr);
|
||||||
}
|
|
||||||
|
|
||||||
*nls = *ls;
|
if (ngx_stream_add_listen(cf, cscf, &lsopt) != NGX_OK) {
|
||||||
|
|
||||||
} else {
|
|
||||||
nls = ls;
|
|
||||||
}
|
|
||||||
|
|
||||||
nls->sockaddr = u.addrs[n].sockaddr;
|
|
||||||
nls->socklen = u.addrs[n].socklen;
|
|
||||||
nls->addr_text = u.addrs[n].name;
|
|
||||||
nls->wildcard = ngx_inet_wildcard(nls->sockaddr);
|
|
||||||
|
|
||||||
als = cmcf->listen.elts;
|
|
||||||
|
|
||||||
for (i = 0; i < cmcf->listen.nelts - 1; i++) {
|
|
||||||
if (nls->type != als[i].type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_cmp_sockaddr(als[i].sockaddr, als[i].socklen,
|
|
||||||
nls->sockaddr, nls->socklen, 1)
|
|
||||||
!= NGX_OK)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
||||||
"duplicate \"%V\" address and port pair",
|
|
||||||
&nls->addr_text);
|
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,6 +1280,107 @@ ngx_stream_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_stream_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
ngx_stream_core_srv_conf_t *cscf = conf;
|
||||||
|
|
||||||
|
u_char ch;
|
||||||
|
ngx_str_t *value;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_stream_server_name_t *sn;
|
||||||
|
|
||||||
|
value = cf->args->elts;
|
||||||
|
|
||||||
|
for (i = 1; i < cf->args->nelts; i++) {
|
||||||
|
|
||||||
|
ch = value[i].data[0];
|
||||||
|
|
||||||
|
if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
|
||||||
|
|| (ch == '.' && value[i].len < 2))
|
||||||
|
{
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"server name \"%V\" is invalid", &value[i]);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strchr(value[i].data, '/')) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||||
|
"server name \"%V\" has suspicious symbols",
|
||||||
|
&value[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sn = ngx_array_push(&cscf->server_names);
|
||||||
|
if (sn == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
sn->regex = NULL;
|
||||||
|
#endif
|
||||||
|
sn->server = cscf;
|
||||||
|
|
||||||
|
if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) {
|
||||||
|
sn->name = cf->cycle->hostname;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sn->name = value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value[i].data[0] != '~') {
|
||||||
|
ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (NGX_PCRE)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
ngx_regex_compile_t rc;
|
||||||
|
u_char errstr[NGX_MAX_CONF_ERRSTR];
|
||||||
|
|
||||||
|
if (value[i].len == 1) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"empty regex in server name \"%V\"", &value[i]);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
value[i].len--;
|
||||||
|
value[i].data++;
|
||||||
|
|
||||||
|
ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
|
||||||
|
|
||||||
|
rc.pattern = value[i];
|
||||||
|
rc.err.len = NGX_MAX_CONF_ERRSTR;
|
||||||
|
rc.err.data = errstr;
|
||||||
|
|
||||||
|
for (p = value[i].data; p < value[i].data + value[i].len; p++) {
|
||||||
|
if (*p >= 'A' && *p <= 'Z') {
|
||||||
|
rc.options = NGX_REGEX_CASELESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sn->regex = ngx_stream_regex_compile(cf, &rc);
|
||||||
|
if (sn->regex == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sn->name = value[i];
|
||||||
|
cscf->captures = (rc.captures > 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"using regex \"%V\" "
|
||||||
|
"requires PCRE library", &value[i]);
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_stream_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ ngx_stream_init_connection(ngx_connection_t *c)
|
|||||||
struct sockaddr_in *sin;
|
struct sockaddr_in *sin;
|
||||||
ngx_stream_in_addr_t *addr;
|
ngx_stream_in_addr_t *addr;
|
||||||
ngx_stream_session_t *s;
|
ngx_stream_session_t *s;
|
||||||
|
ngx_stream_conf_ctx_t *ctx;
|
||||||
ngx_stream_addr_conf_t *addr_conf;
|
ngx_stream_addr_conf_t *addr_conf;
|
||||||
#if (NGX_HAVE_INET6)
|
#if (NGX_HAVE_INET6)
|
||||||
struct sockaddr_in6 *sin6;
|
struct sockaddr_in6 *sin6;
|
||||||
@@ -121,9 +122,12 @@ ngx_stream_init_connection(ngx_connection_t *c)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx = addr_conf->default_server->ctx;
|
||||||
|
|
||||||
s->signature = NGX_STREAM_MODULE;
|
s->signature = NGX_STREAM_MODULE;
|
||||||
s->main_conf = addr_conf->ctx->main_conf;
|
s->main_conf = ctx->main_conf;
|
||||||
s->srv_conf = addr_conf->ctx->srv_conf;
|
s->srv_conf = ctx->srv_conf;
|
||||||
|
s->virtual_names = addr_conf->virtual_names;
|
||||||
|
|
||||||
#if (NGX_STREAM_SSL)
|
#if (NGX_STREAM_SSL)
|
||||||
s->ssl = addr_conf->ssl;
|
s->ssl = addr_conf->ssl;
|
||||||
@@ -144,7 +148,7 @@ ngx_stream_init_connection(ngx_connection_t *c)
|
|||||||
|
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA %sclient %*s connected to %V",
|
ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%uA %sclient %*s connected to %V",
|
||||||
c->number, c->type == SOCK_DGRAM ? "udp " : "",
|
c->number, c->type == SOCK_DGRAM ? "udp " : "",
|
||||||
len, text, &addr_conf->addr_text);
|
len, text, &c->listening->addr_text);
|
||||||
|
|
||||||
c->log->connection = c->number;
|
c->log->connection = c->number;
|
||||||
c->log->handler = ngx_stream_log_error;
|
c->log->handler = ngx_stream_log_error;
|
||||||
|
|||||||
@@ -0,0 +1,276 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Roman Arutyunyan
|
||||||
|
* Copyright (C) Nginx, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_core.h>
|
||||||
|
#include <ngx_stream.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_addr_t *addr;
|
||||||
|
ngx_stream_complex_value_t *addr_value;
|
||||||
|
} ngx_stream_pass_srv_conf_t;
|
||||||
|
|
||||||
|
|
||||||
|
static void ngx_stream_pass_handler(ngx_stream_session_t *s);
|
||||||
|
static ngx_int_t ngx_stream_pass_match(ngx_listening_t *ls, ngx_addr_t *addr);
|
||||||
|
static void *ngx_stream_pass_create_srv_conf(ngx_conf_t *cf);
|
||||||
|
static char *ngx_stream_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_command_t ngx_stream_pass_commands[] = {
|
||||||
|
|
||||||
|
{ ngx_string("pass"),
|
||||||
|
NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_stream_pass,
|
||||||
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
ngx_null_command
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_stream_module_t ngx_stream_pass_module_ctx = {
|
||||||
|
NULL, /* preconfiguration */
|
||||||
|
NULL, /* postconfiguration */
|
||||||
|
|
||||||
|
NULL, /* create main configuration */
|
||||||
|
NULL, /* init main configuration */
|
||||||
|
|
||||||
|
ngx_stream_pass_create_srv_conf, /* create server configuration */
|
||||||
|
NULL /* merge server configuration */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_module_t ngx_stream_pass_module = {
|
||||||
|
NGX_MODULE_V1,
|
||||||
|
&ngx_stream_pass_module_ctx, /* module context */
|
||||||
|
ngx_stream_pass_commands, /* module directives */
|
||||||
|
NGX_STREAM_MODULE, /* module type */
|
||||||
|
NULL, /* init master */
|
||||||
|
NULL, /* init module */
|
||||||
|
NULL, /* init process */
|
||||||
|
NULL, /* init thread */
|
||||||
|
NULL, /* exit thread */
|
||||||
|
NULL, /* exit process */
|
||||||
|
NULL, /* exit master */
|
||||||
|
NGX_MODULE_V1_PADDING
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ngx_stream_pass_handler(ngx_stream_session_t *s)
|
||||||
|
{
|
||||||
|
ngx_url_t u;
|
||||||
|
ngx_str_t url;
|
||||||
|
ngx_addr_t *addr;
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_listening_t *ls;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_stream_pass_srv_conf_t *pscf;
|
||||||
|
|
||||||
|
c = s->connection;
|
||||||
|
|
||||||
|
c->log->action = "passing connection to port";
|
||||||
|
|
||||||
|
if (c->buffer && c->buffer->pos != c->buffer->last) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"cannot pass connection with preread data");
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_pass_module);
|
||||||
|
|
||||||
|
addr = pscf->addr;
|
||||||
|
|
||||||
|
if (addr == NULL) {
|
||||||
|
if (ngx_stream_complex_value(s, pscf->addr_value, &url) != NGX_OK) {
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||||
|
|
||||||
|
u.url = url;
|
||||||
|
u.no_resolve = 1;
|
||||||
|
|
||||||
|
if (ngx_parse_url(c->pool, &u) != NGX_OK) {
|
||||||
|
if (u.err) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"%s in pass \"%V\"", u.err, &u.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u.naddrs == 0) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"no addresses in pass \"%V\"", &u.url);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u.no_port) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"no port in pass \"%V\"", &u.url);
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = &u.addrs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||||
|
"stream pass addr: \"%V\"", &addr->name);
|
||||||
|
|
||||||
|
ls = ngx_cycle->listening.elts;
|
||||||
|
|
||||||
|
for (i = 0; i < ngx_cycle->listening.nelts; i++) {
|
||||||
|
|
||||||
|
if (ngx_stream_pass_match(&ls[i], addr) != NGX_OK) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->listening = &ls[i];
|
||||||
|
|
||||||
|
c->data = NULL;
|
||||||
|
c->buffer = NULL;
|
||||||
|
|
||||||
|
*c->log = c->listening->log;
|
||||||
|
c->log->handler = NULL;
|
||||||
|
c->log->data = NULL;
|
||||||
|
|
||||||
|
c->local_sockaddr = addr->sockaddr;
|
||||||
|
c->local_socklen = addr->socklen;
|
||||||
|
|
||||||
|
c->listening->handler(c);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_ERR, c->log, 0,
|
||||||
|
"port not found for \"%V\"", &addr->name);
|
||||||
|
|
||||||
|
ngx_stream_finalize_session(s, NGX_STREAM_OK);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_pass_match(ngx_listening_t *ls, ngx_addr_t *addr)
|
||||||
|
{
|
||||||
|
if (!ls->wildcard) {
|
||||||
|
return ngx_cmp_sockaddr(ls->sockaddr, ls->socklen,
|
||||||
|
addr->sockaddr, addr->socklen, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ls->sockaddr->sa_family == addr->sockaddr->sa_family
|
||||||
|
&& ngx_inet_get_port(ls->sockaddr) == ngx_inet_get_port(addr->sockaddr))
|
||||||
|
{
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void *
|
||||||
|
ngx_stream_pass_create_srv_conf(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_stream_pass_srv_conf_t *conf;
|
||||||
|
|
||||||
|
conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_pass_srv_conf_t));
|
||||||
|
if (conf == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set by ngx_pcalloc():
|
||||||
|
*
|
||||||
|
* conf->addr = NULL;
|
||||||
|
* conf->addr_value = NULL;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_stream_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
ngx_stream_pass_srv_conf_t *pscf = conf;
|
||||||
|
|
||||||
|
ngx_url_t u;
|
||||||
|
ngx_str_t *value, *url;
|
||||||
|
ngx_stream_complex_value_t cv;
|
||||||
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
|
ngx_stream_compile_complex_value_t ccv;
|
||||||
|
|
||||||
|
if (pscf->addr || pscf->addr_value) {
|
||||||
|
return "is duplicate";
|
||||||
|
}
|
||||||
|
|
||||||
|
cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module);
|
||||||
|
|
||||||
|
cscf->handler = ngx_stream_pass_handler;
|
||||||
|
|
||||||
|
value = cf->args->elts;
|
||||||
|
|
||||||
|
url = &value[1];
|
||||||
|
|
||||||
|
ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));
|
||||||
|
|
||||||
|
ccv.cf = cf;
|
||||||
|
ccv.value = url;
|
||||||
|
ccv.complex_value = &cv;
|
||||||
|
|
||||||
|
if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cv.lengths) {
|
||||||
|
pscf->addr_value = ngx_palloc(cf->pool,
|
||||||
|
sizeof(ngx_stream_complex_value_t));
|
||||||
|
if (pscf->addr_value == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pscf->addr_value = cv;
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||||
|
|
||||||
|
u.url = *url;
|
||||||
|
u.no_resolve = 1;
|
||||||
|
|
||||||
|
if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
|
||||||
|
if (u.err) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"%s in \"%V\" of the \"pass\" directive",
|
||||||
|
u.err, &u.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u.naddrs == 0) {
|
||||||
|
return "has no addresses";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u.no_port) {
|
||||||
|
return "has no port";
|
||||||
|
}
|
||||||
|
|
||||||
|
pscf->addr = &u.addrs[0];
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
+286
-124
@@ -40,12 +40,12 @@ static ngx_int_t ngx_stream_ssl_variable(ngx_stream_session_t *s,
|
|||||||
ngx_stream_variable_value_t *v, uintptr_t data);
|
ngx_stream_variable_value_t *v, uintptr_t data);
|
||||||
|
|
||||||
static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf);
|
static ngx_int_t ngx_stream_ssl_add_variables(ngx_conf_t *cf);
|
||||||
static void *ngx_stream_ssl_create_conf(ngx_conf_t *cf);
|
static void *ngx_stream_ssl_create_srv_conf(ngx_conf_t *cf);
|
||||||
static char *ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent,
|
static char *ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent,
|
||||||
void *child);
|
void *child);
|
||||||
|
|
||||||
static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
|
static ngx_int_t ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
|
||||||
ngx_stream_ssl_conf_t *conf);
|
ngx_stream_ssl_srv_conf_t *conf);
|
||||||
|
|
||||||
static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
|
static char *ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||||
void *conf);
|
void *conf);
|
||||||
@@ -90,21 +90,21 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
|
|||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_msec_slot,
|
ngx_conf_set_msec_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, handshake_timeout),
|
offsetof(ngx_stream_ssl_srv_conf_t, handshake_timeout),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_certificate"),
|
{ ngx_string("ssl_certificate"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_array_slot,
|
ngx_conf_set_str_array_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, certificates),
|
offsetof(ngx_stream_ssl_srv_conf_t, certificates),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_certificate_key"),
|
{ ngx_string("ssl_certificate_key"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_array_slot,
|
ngx_conf_set_str_array_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, certificate_keys),
|
offsetof(ngx_stream_ssl_srv_conf_t, certificate_keys),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_password_file"),
|
{ ngx_string("ssl_password_file"),
|
||||||
@@ -118,63 +118,63 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
|
|||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, dhparam),
|
offsetof(ngx_stream_ssl_srv_conf_t, dhparam),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_ecdh_curve"),
|
{ ngx_string("ssl_ecdh_curve"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, ecdh_curve),
|
offsetof(ngx_stream_ssl_srv_conf_t, ecdh_curve),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_protocols"),
|
{ ngx_string("ssl_protocols"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
||||||
ngx_conf_set_bitmask_slot,
|
ngx_conf_set_bitmask_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, protocols),
|
offsetof(ngx_stream_ssl_srv_conf_t, protocols),
|
||||||
&ngx_stream_ssl_protocols },
|
&ngx_stream_ssl_protocols },
|
||||||
|
|
||||||
{ ngx_string("ssl_ciphers"),
|
{ ngx_string("ssl_ciphers"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, ciphers),
|
offsetof(ngx_stream_ssl_srv_conf_t, ciphers),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_verify_client"),
|
{ ngx_string("ssl_verify_client"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_enum_slot,
|
ngx_conf_set_enum_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, verify),
|
offsetof(ngx_stream_ssl_srv_conf_t, verify),
|
||||||
&ngx_stream_ssl_verify },
|
&ngx_stream_ssl_verify },
|
||||||
|
|
||||||
{ ngx_string("ssl_verify_depth"),
|
{ ngx_string("ssl_verify_depth"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_num_slot,
|
ngx_conf_set_num_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, verify_depth),
|
offsetof(ngx_stream_ssl_srv_conf_t, verify_depth),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_client_certificate"),
|
{ ngx_string("ssl_client_certificate"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, client_certificate),
|
offsetof(ngx_stream_ssl_srv_conf_t, client_certificate),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_trusted_certificate"),
|
{ ngx_string("ssl_trusted_certificate"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, trusted_certificate),
|
offsetof(ngx_stream_ssl_srv_conf_t, trusted_certificate),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_prefer_server_ciphers"),
|
{ ngx_string("ssl_prefer_server_ciphers"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
||||||
ngx_conf_set_flag_slot,
|
ngx_conf_set_flag_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, prefer_server_ciphers),
|
offsetof(ngx_stream_ssl_srv_conf_t, prefer_server_ciphers),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_session_cache"),
|
{ ngx_string("ssl_session_cache"),
|
||||||
@@ -188,37 +188,44 @@ static ngx_command_t ngx_stream_ssl_commands[] = {
|
|||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
||||||
ngx_conf_set_flag_slot,
|
ngx_conf_set_flag_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, session_tickets),
|
offsetof(ngx_stream_ssl_srv_conf_t, session_tickets),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_session_ticket_key"),
|
{ ngx_string("ssl_session_ticket_key"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_array_slot,
|
ngx_conf_set_str_array_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, session_ticket_keys),
|
offsetof(ngx_stream_ssl_srv_conf_t, session_ticket_keys),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_session_timeout"),
|
{ ngx_string("ssl_session_timeout"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_sec_slot,
|
ngx_conf_set_sec_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, session_timeout),
|
offsetof(ngx_stream_ssl_srv_conf_t, session_timeout),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_crl"),
|
{ ngx_string("ssl_crl"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_str_slot,
|
ngx_conf_set_str_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, crl),
|
offsetof(ngx_stream_ssl_srv_conf_t, crl),
|
||||||
NULL },
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_conf_command"),
|
{ ngx_string("ssl_conf_command"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE2,
|
||||||
ngx_conf_set_keyval_slot,
|
ngx_conf_set_keyval_slot,
|
||||||
NGX_STREAM_SRV_CONF_OFFSET,
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
offsetof(ngx_stream_ssl_conf_t, conf_commands),
|
offsetof(ngx_stream_ssl_srv_conf_t, conf_commands),
|
||||||
&ngx_stream_ssl_conf_command_post },
|
&ngx_stream_ssl_conf_command_post },
|
||||||
|
|
||||||
|
{ ngx_string("ssl_reject_handshake"),
|
||||||
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG,
|
||||||
|
ngx_conf_set_flag_slot,
|
||||||
|
NGX_STREAM_SRV_CONF_OFFSET,
|
||||||
|
offsetof(ngx_stream_ssl_srv_conf_t, reject_handshake),
|
||||||
|
NULL },
|
||||||
|
|
||||||
{ ngx_string("ssl_alpn"),
|
{ ngx_string("ssl_alpn"),
|
||||||
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,
|
||||||
ngx_stream_ssl_alpn,
|
ngx_stream_ssl_alpn,
|
||||||
@@ -237,8 +244,8 @@ static ngx_stream_module_t ngx_stream_ssl_module_ctx = {
|
|||||||
NULL, /* create main configuration */
|
NULL, /* create main configuration */
|
||||||
NULL, /* init main configuration */
|
NULL, /* init main configuration */
|
||||||
|
|
||||||
ngx_stream_ssl_create_conf, /* create server configuration */
|
ngx_stream_ssl_create_srv_conf, /* create server configuration */
|
||||||
ngx_stream_ssl_merge_conf /* merge server configuration */
|
ngx_stream_ssl_merge_srv_conf /* merge server configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -332,11 +339,11 @@ static ngx_str_t ngx_stream_ssl_sess_id_ctx = ngx_string("STREAM");
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_ssl_handler(ngx_stream_session_t *s)
|
ngx_stream_ssl_handler(ngx_stream_session_t *s)
|
||||||
{
|
{
|
||||||
long rc;
|
long rc;
|
||||||
X509 *cert;
|
X509 *cert;
|
||||||
ngx_int_t rv;
|
ngx_int_t rv;
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
ngx_stream_ssl_conf_t *sslcf;
|
ngx_stream_ssl_srv_conf_t *sscf;
|
||||||
|
|
||||||
if (!s->ssl) {
|
if (!s->ssl) {
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
@@ -344,23 +351,23 @@ ngx_stream_ssl_handler(ngx_stream_session_t *s)
|
|||||||
|
|
||||||
c = s->connection;
|
c = s->connection;
|
||||||
|
|
||||||
sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
||||||
|
|
||||||
if (c->ssl == NULL) {
|
if (c->ssl == NULL) {
|
||||||
c->log->action = "SSL handshaking";
|
c->log->action = "SSL handshaking";
|
||||||
|
|
||||||
rv = ngx_stream_ssl_init_connection(&sslcf->ssl, c);
|
rv = ngx_stream_ssl_init_connection(&sscf->ssl, c);
|
||||||
|
|
||||||
if (rv != NGX_OK) {
|
if (rv != NGX_OK) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sslcf->verify) {
|
if (sscf->verify) {
|
||||||
rc = SSL_get_verify_result(c->ssl->connection);
|
rc = SSL_get_verify_result(c->ssl->connection);
|
||||||
|
|
||||||
if (rc != X509_V_OK
|
if (rc != X509_V_OK
|
||||||
&& (sslcf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
|
&& (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
|
||||||
{
|
{
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
||||||
"client SSL certificate verify error: (%l:%s)",
|
"client SSL certificate verify error: (%l:%s)",
|
||||||
@@ -371,7 +378,7 @@ ngx_stream_ssl_handler(ngx_stream_session_t *s)
|
|||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sslcf->verify == 1) {
|
if (sscf->verify == 1) {
|
||||||
cert = SSL_get_peer_certificate(c->ssl->connection);
|
cert = SSL_get_peer_certificate(c->ssl->connection);
|
||||||
|
|
||||||
if (cert == NULL) {
|
if (cert == NULL) {
|
||||||
@@ -396,7 +403,7 @@ ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
|||||||
{
|
{
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_stream_session_t *s;
|
ngx_stream_session_t *s;
|
||||||
ngx_stream_ssl_conf_t *sslcf;
|
ngx_stream_ssl_srv_conf_t *sscf;
|
||||||
ngx_stream_core_srv_conf_t *cscf;
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
s = c->data;
|
s = c->data;
|
||||||
@@ -418,9 +425,9 @@ ngx_stream_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rc == NGX_AGAIN) {
|
if (rc == NGX_AGAIN) {
|
||||||
sslcf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
||||||
|
|
||||||
ngx_add_timer(c->read, sslcf->handshake_timeout);
|
ngx_add_timer(c->read, sscf->handshake_timeout);
|
||||||
|
|
||||||
c->ssl->handler = ngx_stream_ssl_handshake_handler;
|
c->ssl->handler = ngx_stream_ssl_handshake_handler;
|
||||||
|
|
||||||
@@ -458,7 +465,112 @@ ngx_stream_ssl_handshake_handler(ngx_connection_t *c)
|
|||||||
static int
|
static int
|
||||||
ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
ngx_stream_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
|
||||||
{
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_str_t host;
|
||||||
|
const char *servername;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_stream_session_t *s;
|
||||||
|
ngx_stream_ssl_srv_conf_t *sscf;
|
||||||
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
|
c = ngx_ssl_get_connection(ssl_conn);
|
||||||
|
|
||||||
|
if (c->ssl->handshaked) {
|
||||||
|
*ad = SSL_AD_NO_RENEGOTIATION;
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = c->data;
|
||||||
|
|
||||||
|
servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
|
||||||
|
|
||||||
|
if (servername == NULL) {
|
||||||
|
ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||||
|
"SSL server name: null");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||||
|
"SSL server name: \"%s\"", servername);
|
||||||
|
|
||||||
|
host.len = ngx_strlen(servername);
|
||||||
|
|
||||||
|
if (host.len == 0) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
host.data = (u_char *) servername;
|
||||||
|
|
||||||
|
rc = ngx_stream_validate_host(&host, c->pool, 1);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_stream_find_virtual_server(s, &host, &cscf);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->srv_conf = cscf->ctx->srv_conf;
|
||||||
|
|
||||||
|
ngx_set_connection_log(c, cscf->error_log);
|
||||||
|
|
||||||
|
sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
||||||
|
|
||||||
|
if (sscf->ssl.ctx) {
|
||||||
|
if (SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx) == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SSL_set_SSL_CTX() only changes certs as of 1.0.0d
|
||||||
|
* adjust other things we care about
|
||||||
|
*/
|
||||||
|
|
||||||
|
SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
|
||||||
|
SSL_CTX_get_verify_callback(sscf->ssl.ctx));
|
||||||
|
|
||||||
|
SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x009080dfL
|
||||||
|
/* only in 0.9.8m+ */
|
||||||
|
SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
|
||||||
|
~SSL_CTX_get_options(sscf->ssl.ctx));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
|
||||||
|
|
||||||
|
#ifdef SSL_OP_NO_RENEGOTIATION
|
||||||
|
SSL_set_options(ssl_conn, SSL_OP_NO_RENEGOTIATION);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
sscf = ngx_stream_get_module_srv_conf(s, ngx_stream_ssl_module);
|
||||||
|
|
||||||
|
if (sscf->reject_handshake) {
|
||||||
|
c->ssl->handshake_rejected = 1;
|
||||||
|
*ad = SSL_AD_UNRECOGNIZED_NAME;
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
*ad = SSL_AD_INTERNAL_ERROR;
|
||||||
|
return SSL_TLSEXT_ERR_ALERT_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -513,7 +625,7 @@ ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
|
|||||||
ngx_uint_t i, nelts;
|
ngx_uint_t i, nelts;
|
||||||
ngx_connection_t *c;
|
ngx_connection_t *c;
|
||||||
ngx_stream_session_t *s;
|
ngx_stream_session_t *s;
|
||||||
ngx_stream_ssl_conf_t *sslcf;
|
ngx_stream_ssl_srv_conf_t *sscf;
|
||||||
ngx_stream_complex_value_t *certs, *keys;
|
ngx_stream_complex_value_t *certs, *keys;
|
||||||
|
|
||||||
c = ngx_ssl_get_connection(ssl_conn);
|
c = ngx_ssl_get_connection(ssl_conn);
|
||||||
@@ -524,11 +636,11 @@ ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
|
|||||||
|
|
||||||
s = c->data;
|
s = c->data;
|
||||||
|
|
||||||
sslcf = arg;
|
sscf = arg;
|
||||||
|
|
||||||
nelts = sslcf->certificate_values->nelts;
|
nelts = sscf->certificate_values->nelts;
|
||||||
certs = sslcf->certificate_values->elts;
|
certs = sscf->certificate_values->elts;
|
||||||
keys = sslcf->certificate_key_values->elts;
|
keys = sscf->certificate_key_values->elts;
|
||||||
|
|
||||||
for (i = 0; i < nelts; i++) {
|
for (i = 0; i < nelts; i++) {
|
||||||
|
|
||||||
@@ -547,7 +659,7 @@ ngx_stream_ssl_certificate(ngx_ssl_conn_t *ssl_conn, void *arg)
|
|||||||
"ssl key: \"%s\"", key.data);
|
"ssl key: \"%s\"", key.data);
|
||||||
|
|
||||||
if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key,
|
if (ngx_ssl_connection_certificate(c, c->pool, &cert, &key,
|
||||||
sslcf->passwords)
|
sscf->passwords)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -643,53 +755,53 @@ ngx_stream_ssl_add_variables(ngx_conf_t *cf)
|
|||||||
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
ngx_stream_ssl_create_conf(ngx_conf_t *cf)
|
ngx_stream_ssl_create_srv_conf(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
ngx_stream_ssl_conf_t *scf;
|
ngx_stream_ssl_srv_conf_t *sscf;
|
||||||
|
|
||||||
scf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_ssl_conf_t));
|
sscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_ssl_srv_conf_t));
|
||||||
if (scf == NULL) {
|
if (sscf == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set by ngx_pcalloc():
|
* set by ngx_pcalloc():
|
||||||
*
|
*
|
||||||
* scf->listen = 0;
|
* sscf->protocols = 0;
|
||||||
* scf->protocols = 0;
|
* sscf->certificate_values = NULL;
|
||||||
* scf->certificate_values = NULL;
|
* sscf->dhparam = { 0, NULL };
|
||||||
* scf->dhparam = { 0, NULL };
|
* sscf->ecdh_curve = { 0, NULL };
|
||||||
* scf->ecdh_curve = { 0, NULL };
|
* sscf->client_certificate = { 0, NULL };
|
||||||
* scf->client_certificate = { 0, NULL };
|
* sscf->trusted_certificate = { 0, NULL };
|
||||||
* scf->trusted_certificate = { 0, NULL };
|
* sscf->crl = { 0, NULL };
|
||||||
* scf->crl = { 0, NULL };
|
* sscf->alpn = { 0, NULL };
|
||||||
* scf->alpn = { 0, NULL };
|
* sscf->ciphers = { 0, NULL };
|
||||||
* scf->ciphers = { 0, NULL };
|
* sscf->shm_zone = NULL;
|
||||||
* scf->shm_zone = NULL;
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
scf->handshake_timeout = NGX_CONF_UNSET_MSEC;
|
sscf->handshake_timeout = NGX_CONF_UNSET_MSEC;
|
||||||
scf->certificates = NGX_CONF_UNSET_PTR;
|
sscf->certificates = NGX_CONF_UNSET_PTR;
|
||||||
scf->certificate_keys = NGX_CONF_UNSET_PTR;
|
sscf->certificate_keys = NGX_CONF_UNSET_PTR;
|
||||||
scf->passwords = NGX_CONF_UNSET_PTR;
|
sscf->passwords = NGX_CONF_UNSET_PTR;
|
||||||
scf->conf_commands = NGX_CONF_UNSET_PTR;
|
sscf->conf_commands = NGX_CONF_UNSET_PTR;
|
||||||
scf->prefer_server_ciphers = NGX_CONF_UNSET;
|
sscf->prefer_server_ciphers = NGX_CONF_UNSET;
|
||||||
scf->verify = NGX_CONF_UNSET_UINT;
|
sscf->reject_handshake = NGX_CONF_UNSET;
|
||||||
scf->verify_depth = NGX_CONF_UNSET_UINT;
|
sscf->verify = NGX_CONF_UNSET_UINT;
|
||||||
scf->builtin_session_cache = NGX_CONF_UNSET;
|
sscf->verify_depth = NGX_CONF_UNSET_UINT;
|
||||||
scf->session_timeout = NGX_CONF_UNSET;
|
sscf->builtin_session_cache = NGX_CONF_UNSET;
|
||||||
scf->session_tickets = NGX_CONF_UNSET;
|
sscf->session_timeout = NGX_CONF_UNSET;
|
||||||
scf->session_ticket_keys = NGX_CONF_UNSET_PTR;
|
sscf->session_tickets = NGX_CONF_UNSET;
|
||||||
|
sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
|
||||||
|
|
||||||
return scf;
|
return sscf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
ngx_stream_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
{
|
{
|
||||||
ngx_stream_ssl_conf_t *prev = parent;
|
ngx_stream_ssl_srv_conf_t *prev = parent;
|
||||||
ngx_stream_ssl_conf_t *conf = child;
|
ngx_stream_ssl_srv_conf_t *conf = child;
|
||||||
|
|
||||||
ngx_pool_cleanup_t *cln;
|
ngx_pool_cleanup_t *cln;
|
||||||
|
|
||||||
@@ -702,6 +814,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
ngx_conf_merge_value(conf->prefer_server_ciphers,
|
||||||
prev->prefer_server_ciphers, 1);
|
prev->prefer_server_ciphers, 1);
|
||||||
|
|
||||||
|
ngx_conf_merge_value(conf->reject_handshake, prev->reject_handshake, 0);
|
||||||
|
|
||||||
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
|
||||||
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|
(NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1_2|NGX_SSL_TLSv1_3));
|
||||||
|
|
||||||
@@ -733,37 +847,23 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
conf->ssl.log = cf->log;
|
conf->ssl.log = cf->log;
|
||||||
|
|
||||||
if (!conf->listen) {
|
if (conf->certificates) {
|
||||||
|
|
||||||
|
if (conf->certificate_keys == NULL
|
||||||
|
|| conf->certificate_keys->nelts < conf->certificates->nelts)
|
||||||
|
{
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"no \"ssl_certificate_key\" is defined "
|
||||||
|
"for certificate \"%V\"",
|
||||||
|
((ngx_str_t *) conf->certificates->elts)
|
||||||
|
+ conf->certificates->nelts - 1);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (!conf->reject_handshake) {
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->certificates == NULL) {
|
|
||||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
|
||||||
"no \"ssl_certificate\" is defined for "
|
|
||||||
"the \"listen ... ssl\" directive in %s:%ui",
|
|
||||||
conf->file, conf->line);
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf->certificate_keys == NULL) {
|
|
||||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
|
||||||
"no \"ssl_certificate_key\" is defined for "
|
|
||||||
"the \"listen ... ssl\" directive in %s:%ui",
|
|
||||||
conf->file, conf->line);
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf->certificate_keys->nelts < conf->certificates->nelts) {
|
|
||||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
|
||||||
"no \"ssl_certificate_key\" is defined "
|
|
||||||
"for certificate \"%V\" and "
|
|
||||||
"the \"listen ... ssl\" directive in %s:%ui",
|
|
||||||
((ngx_str_t *) conf->certificates->elts)
|
|
||||||
+ conf->certificates->nelts - 1,
|
|
||||||
conf->file, conf->line);
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
|
if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
@@ -816,7 +916,7 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else {
|
} else if (conf->certificates) {
|
||||||
|
|
||||||
/* configure certificates */
|
/* configure certificates */
|
||||||
|
|
||||||
@@ -908,13 +1008,17 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
|||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
|
ngx_stream_ssl_compile_certificates(ngx_conf_t *cf,
|
||||||
ngx_stream_ssl_conf_t *conf)
|
ngx_stream_ssl_srv_conf_t *conf)
|
||||||
{
|
{
|
||||||
ngx_str_t *cert, *key;
|
ngx_str_t *cert, *key;
|
||||||
ngx_uint_t i, nelts;
|
ngx_uint_t i, nelts;
|
||||||
ngx_stream_complex_value_t *cv;
|
ngx_stream_complex_value_t *cv;
|
||||||
ngx_stream_compile_complex_value_t ccv;
|
ngx_stream_compile_complex_value_t ccv;
|
||||||
|
|
||||||
|
if (conf->certificates == NULL) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
cert = conf->certificates->elts;
|
cert = conf->certificates->elts;
|
||||||
key = conf->certificate_keys->elts;
|
key = conf->certificate_keys->elts;
|
||||||
nelts = conf->certificates->nelts;
|
nelts = conf->certificates->nelts;
|
||||||
@@ -993,19 +1097,19 @@ found:
|
|||||||
static char *
|
static char *
|
||||||
ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
ngx_stream_ssl_conf_t *scf = conf;
|
ngx_stream_ssl_srv_conf_t *sscf = conf;
|
||||||
|
|
||||||
ngx_str_t *value;
|
ngx_str_t *value;
|
||||||
|
|
||||||
if (scf->passwords != NGX_CONF_UNSET_PTR) {
|
if (sscf->passwords != NGX_CONF_UNSET_PTR) {
|
||||||
return "is duplicate";
|
return "is duplicate";
|
||||||
}
|
}
|
||||||
|
|
||||||
value = cf->args->elts;
|
value = cf->args->elts;
|
||||||
|
|
||||||
scf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
sscf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
|
||||||
|
|
||||||
if (scf->passwords == NULL) {
|
if (sscf->passwords == NULL) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1016,7 +1120,7 @@ ngx_stream_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
static char *
|
static char *
|
||||||
ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
ngx_stream_ssl_conf_t *scf = conf;
|
ngx_stream_ssl_srv_conf_t *sscf = conf;
|
||||||
|
|
||||||
size_t len;
|
size_t len;
|
||||||
ngx_str_t *value, name, size;
|
ngx_str_t *value, name, size;
|
||||||
@@ -1028,17 +1132,17 @@ ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
for (i = 1; i < cf->args->nelts; i++) {
|
for (i = 1; i < cf->args->nelts; i++) {
|
||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "off") == 0) {
|
if (ngx_strcmp(value[i].data, "off") == 0) {
|
||||||
scf->builtin_session_cache = NGX_SSL_NO_SCACHE;
|
sscf->builtin_session_cache = NGX_SSL_NO_SCACHE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "none") == 0) {
|
if (ngx_strcmp(value[i].data, "none") == 0) {
|
||||||
scf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
|
sscf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_strcmp(value[i].data, "builtin") == 0) {
|
if (ngx_strcmp(value[i].data, "builtin") == 0) {
|
||||||
scf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
|
sscf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,7 +1157,7 @@ ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
scf->builtin_session_cache = n;
|
sscf->builtin_session_cache = n;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1096,13 +1200,13 @@ ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
scf->shm_zone = ngx_shared_memory_add(cf, &name, n,
|
sscf->shm_zone = ngx_shared_memory_add(cf, &name, n,
|
||||||
&ngx_stream_ssl_module);
|
&ngx_stream_ssl_module);
|
||||||
if (scf->shm_zone == NULL) {
|
if (sscf->shm_zone == NULL) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
scf->shm_zone->init = ngx_ssl_session_cache_init;
|
sscf->shm_zone->init = ngx_ssl_session_cache_init;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1110,8 +1214,8 @@ ngx_stream_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scf->shm_zone && scf->builtin_session_cache == NGX_CONF_UNSET) {
|
if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
|
||||||
scf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
|
sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
@@ -1130,14 +1234,14 @@ ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
{
|
{
|
||||||
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
|
||||||
|
|
||||||
ngx_stream_ssl_conf_t *scf = conf;
|
ngx_stream_ssl_srv_conf_t *sscf = conf;
|
||||||
|
|
||||||
u_char *p;
|
u_char *p;
|
||||||
size_t len;
|
size_t len;
|
||||||
ngx_str_t *value;
|
ngx_str_t *value;
|
||||||
ngx_uint_t i;
|
ngx_uint_t i;
|
||||||
|
|
||||||
if (scf->alpn.len) {
|
if (sscf->alpn.len) {
|
||||||
return "is duplicate";
|
return "is duplicate";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1154,19 +1258,19 @@ ngx_stream_ssl_alpn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
|||||||
len += value[i].len + 1;
|
len += value[i].len + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
scf->alpn.data = ngx_pnalloc(cf->pool, len);
|
sscf->alpn.data = ngx_pnalloc(cf->pool, len);
|
||||||
if (scf->alpn.data == NULL) {
|
if (sscf->alpn.data == NULL) {
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = scf->alpn.data;
|
p = sscf->alpn.data;
|
||||||
|
|
||||||
for (i = 1; i < cf->args->nelts; i++) {
|
for (i = 1; i < cf->args->nelts; i++) {
|
||||||
*p++ = value[i].len;
|
*p++ = value[i].len;
|
||||||
p = ngx_cpymem(p, value[i].data, value[i].len);
|
p = ngx_cpymem(p, value[i].data, value[i].len);
|
||||||
}
|
}
|
||||||
|
|
||||||
scf->alpn.len = len;
|
sscf->alpn.len = len;
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
|
|
||||||
@@ -1193,8 +1297,13 @@ ngx_stream_ssl_conf_command_check(ngx_conf_t *cf, void *post, void *data)
|
|||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_ssl_init(ngx_conf_t *cf)
|
ngx_stream_ssl_init(ngx_conf_t *cf)
|
||||||
{
|
{
|
||||||
ngx_stream_handler_pt *h;
|
ngx_uint_t a, p, s;
|
||||||
ngx_stream_core_main_conf_t *cmcf;
|
ngx_stream_handler_pt *h;
|
||||||
|
ngx_stream_conf_addr_t *addr;
|
||||||
|
ngx_stream_conf_port_t *port;
|
||||||
|
ngx_stream_ssl_srv_conf_t *sscf;
|
||||||
|
ngx_stream_core_srv_conf_t **cscfp, *cscf;
|
||||||
|
ngx_stream_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module);
|
||||||
|
|
||||||
@@ -1205,5 +1314,58 @@ ngx_stream_ssl_init(ngx_conf_t *cf)
|
|||||||
|
|
||||||
*h = ngx_stream_ssl_handler;
|
*h = ngx_stream_ssl_handler;
|
||||||
|
|
||||||
|
if (cmcf->ports == NULL) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
port = cmcf->ports->elts;
|
||||||
|
for (p = 0; p < cmcf->ports->nelts; p++) {
|
||||||
|
|
||||||
|
addr = port[p].addrs.elts;
|
||||||
|
for (a = 0; a < port[p].addrs.nelts; a++) {
|
||||||
|
|
||||||
|
if (!addr[a].opt.ssl) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cscf = addr[a].default_server;
|
||||||
|
sscf = cscf->ctx->srv_conf[ngx_stream_ssl_module.ctx_index];
|
||||||
|
|
||||||
|
if (sscf->certificates) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sscf->reject_handshake) {
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"no \"ssl_certificate\" is defined for "
|
||||||
|
"the \"listen ... ssl\" directive in %s:%ui",
|
||||||
|
cscf->file_name, cscf->line);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if no certificates are defined in the default server,
|
||||||
|
* check all non-default server blocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
cscfp = addr[a].servers.elts;
|
||||||
|
for (s = 0; s < addr[a].servers.nelts; s++) {
|
||||||
|
|
||||||
|
cscf = cscfp[s];
|
||||||
|
sscf = cscf->ctx->srv_conf[ngx_stream_ssl_module.ctx_index];
|
||||||
|
|
||||||
|
if (sscf->certificates || sscf->reject_handshake) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"no \"ssl_certificate\" is defined for "
|
||||||
|
"the \"listen ... ssl\" directive in %s:%ui",
|
||||||
|
cscf->file_name, cscf->line);
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
@@ -18,10 +18,10 @@ typedef struct {
|
|||||||
ngx_msec_t handshake_timeout;
|
ngx_msec_t handshake_timeout;
|
||||||
|
|
||||||
ngx_flag_t prefer_server_ciphers;
|
ngx_flag_t prefer_server_ciphers;
|
||||||
|
ngx_flag_t reject_handshake;
|
||||||
|
|
||||||
ngx_ssl_t ssl;
|
ngx_ssl_t ssl;
|
||||||
|
|
||||||
ngx_uint_t listen;
|
|
||||||
ngx_uint_t protocols;
|
ngx_uint_t protocols;
|
||||||
|
|
||||||
ngx_uint_t verify;
|
ngx_uint_t verify;
|
||||||
@@ -53,10 +53,7 @@ typedef struct {
|
|||||||
|
|
||||||
ngx_flag_t session_tickets;
|
ngx_flag_t session_tickets;
|
||||||
ngx_array_t *session_ticket_keys;
|
ngx_array_t *session_ticket_keys;
|
||||||
|
} ngx_stream_ssl_srv_conf_t;
|
||||||
u_char *file;
|
|
||||||
ngx_uint_t line;
|
|
||||||
} ngx_stream_ssl_conf_t;
|
|
||||||
|
|
||||||
|
|
||||||
extern ngx_module_t ngx_stream_ssl_module;
|
extern ngx_module_t ngx_stream_ssl_module;
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ typedef struct {
|
|||||||
static ngx_int_t ngx_stream_ssl_preread_handler(ngx_stream_session_t *s);
|
static ngx_int_t ngx_stream_ssl_preread_handler(ngx_stream_session_t *s);
|
||||||
static ngx_int_t ngx_stream_ssl_preread_parse_record(
|
static ngx_int_t ngx_stream_ssl_preread_parse_record(
|
||||||
ngx_stream_ssl_preread_ctx_t *ctx, u_char *pos, u_char *last);
|
ngx_stream_ssl_preread_ctx_t *ctx, u_char *pos, u_char *last);
|
||||||
|
static ngx_int_t ngx_stream_ssl_preread_servername(ngx_stream_session_t *s,
|
||||||
|
ngx_str_t *servername);
|
||||||
static ngx_int_t ngx_stream_ssl_preread_protocol_variable(
|
static ngx_int_t ngx_stream_ssl_preread_protocol_variable(
|
||||||
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
|
ngx_stream_session_t *s, ngx_stream_variable_value_t *v, uintptr_t data);
|
||||||
static ngx_int_t ngx_stream_ssl_preread_server_name_variable(
|
static ngx_int_t ngx_stream_ssl_preread_server_name_variable(
|
||||||
@@ -187,6 +189,10 @@ ngx_stream_ssl_preread_handler(ngx_stream_session_t *s)
|
|||||||
return NGX_DECLINED;
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_OK) {
|
||||||
|
return ngx_stream_ssl_preread_servername(s, &ctx->host);
|
||||||
|
}
|
||||||
|
|
||||||
if (rc != NGX_AGAIN) {
|
if (rc != NGX_AGAIN) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -404,9 +410,6 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
case sw_sni_host:
|
case sw_sni_host:
|
||||||
ctx->host.len = (p[1] << 8) + p[2];
|
ctx->host.len = (p[1] << 8) + p[2];
|
||||||
|
|
||||||
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, ctx->log, 0,
|
|
||||||
"ssl preread: SNI hostname \"%V\"", &ctx->host);
|
|
||||||
|
|
||||||
state = sw_ext;
|
state = sw_ext;
|
||||||
dst = NULL;
|
dst = NULL;
|
||||||
size = ext;
|
size = ext;
|
||||||
@@ -496,6 +499,54 @@ ngx_stream_ssl_preread_parse_record(ngx_stream_ssl_preread_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_stream_ssl_preread_servername(ngx_stream_session_t *s,
|
||||||
|
ngx_str_t *servername)
|
||||||
|
{
|
||||||
|
ngx_int_t rc;
|
||||||
|
ngx_str_t host;
|
||||||
|
ngx_connection_t *c;
|
||||||
|
ngx_stream_core_srv_conf_t *cscf;
|
||||||
|
|
||||||
|
c = s->connection;
|
||||||
|
|
||||||
|
ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
|
||||||
|
"SSL preread server name: \"%V\"", servername);
|
||||||
|
|
||||||
|
if (servername->len == 0) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
host = *servername;
|
||||||
|
|
||||||
|
rc = ngx_stream_validate_host(&host, c->pool, 1);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_stream_find_virtual_server(s, &host, &cscf);
|
||||||
|
|
||||||
|
if (rc == NGX_ERROR) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->srv_conf = cscf->ctx->srv_conf;
|
||||||
|
|
||||||
|
ngx_set_connection_log(c, cscf->error_log);
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static ngx_int_t
|
static ngx_int_t
|
||||||
ngx_stream_ssl_preread_protocol_variable(ngx_stream_session_t *s,
|
ngx_stream_ssl_preread_protocol_variable(ngx_stream_session_t *s,
|
||||||
ngx_variable_value_t *v, uintptr_t data)
|
ngx_variable_value_t *v, uintptr_t data)
|
||||||
|
|||||||
Reference in New Issue
Block a user