resolver: improved space handling. improved error handling and added

IPv6 support.
pull/348/head
Datong Sun 7 years ago
parent dafba43e9f
commit 3135bb8450
No known key found for this signature in database
GPG Key ID: 1908AE626BFCE242

@ -1,5 +1,5 @@
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index cd55520c..6a3f98bb 100644
index cd55520c..d91c406c 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -5,6 +5,7 @@
@ -25,28 +25,31 @@ index cd55520c..6a3f98bb 100644
typedef struct {
u_char ident_hi;
@@ -131,6 +140,138 @@ static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
@@ -131,6 +140,180 @@ static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
#endif
+static ngx_int_t
+ngx_resolver_read_resolv_conf(ngx_conf_t *cf, ngx_resolver_t *r, u_char *path)
+ngx_resolver_read_resolv_conf(ngx_conf_t *cf, ngx_resolver_t *r, u_char *path,
+ size_t path_len)
+{
+ ngx_url_t u;
+ ngx_resolver_connection_t *rec;
+ ngx_fd_t fd;
+ ngx_file_t file;
+ u_char buf[NGX_RESOLVER_FILE_BUF_SIZE];
+ u_char ipv6_buf[NGX_INET6_ADDRSTRLEN];
+ ngx_uint_t address, j, total = 0;
+ ssize_t n, i;
+ enum {
+ sw_nameserver,
+ sw_spaces,
+ sw_address,
+ sw_skip
+ } state;
+
+ file.name.data = path;
+ file.name.len = ngx_strlen(path);
+ file.name.len = path_len;
+
+ if (ngx_conf_full_name(cf->cycle, &file.name, 1) != NGX_OK) {
+ return NGX_ERROR;
@ -71,6 +74,11 @@ index cd55520c..6a3f98bb 100644
+
+ n = ngx_read_file(&file, buf, NGX_RESOLVER_FILE_BUF_SIZE, 0);
+
+ if (n == NGX_ERROR) {
+ ngx_conf_log_error(NGX_LOG_ALERT, cf, ngx_errno,
+ ngx_read_file_n " \"%s\" failed", file.name.data);
+ }
+
+ if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
+ ngx_conf_log_error(NGX_LOG_ALERT, cf, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", file.name.data);
@ -97,24 +105,49 @@ index cd55520c..6a3f98bb 100644
+ && ngx_memcmp(buf + i, "nameserver",
+ sizeof("nameserver") - 1) == 0)
+ {
+ state = sw_address;
+ state = sw_spaces;
+ i += sizeof("nameserver") - 1;
+ address = i;
+
+ continue;
+ }
+
+ break;
+
+ case sw_spaces:
+ if (buf[i] != '\t' && buf[i] != ' ') {
+ address = i;
+ state = sw_address;
+ }
+
+ break;
+
+ case sw_address:
+
+ if (buf[i] == CR || buf[i] == LF || i == n - 1) {
+ ngx_memzero(&u, sizeof(ngx_url_t));
+
+ u.url.data = buf + address;
+ u.url.len = i - address;
+ u.url.len = i == n - 1 ? n - address : i - address;
+ u.default_port = 53;
+
+ /* IPv6? */
+ if (ngx_strlchr(u.url.data, u.url.data + u.url.len, ':') != NULL) {
+ if (u.url.len + 2 > sizeof(ipv6_buf)) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "IPv6 resolver address is too long: \"%V\"",
+ &u.url);
+
+ return NGX_ERROR;
+ }
+
+ ipv6_buf[0] = '[';
+ ngx_memcpy(ipv6_buf + 1, u.url.data, u.url.len);
+ ipv6_buf[u.url.len + 1] = ']';
+
+ u.url.data = ipv6_buf;
+ u.url.len = u.url.len + 2;
+ }
+
+ if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
+ if (u.err) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@ -141,6 +174,15 @@ index cd55520c..6a3f98bb 100644
+
+ total++;
+
+#if (NGX_DEBUG)
+ /*
+ * logs with level below NGX_LOG_NOTICE will not be printed
+ * in this early phase
+ */
+ ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0,
+ "parsed a resolver: \"%V\"", &u.url);
+#endif
+
+ state = sw_nameserver;
+ }
+
@ -164,7 +206,7 @@ index cd55520c..6a3f98bb 100644
ngx_resolver_t *
ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
{
@@ -246,6 +387,33 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
@@ -246,6 +429,35 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
}
#endif
@ -172,7 +214,8 @@ index cd55520c..6a3f98bb 100644
+
+ if (ngx_strcmp(&names[i].data[6], "on") == 0) {
+ if (ngx_resolver_read_resolv_conf(cf, r,
+ (u_char *) NGX_RESOLVER_FILE_NAME)
+ (u_char *) NGX_RESOLVER_FILE_NAME,
+ sizeof(NGX_RESOLVER_FILE_NAME) - 1)
+ != NGX_OK)
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
@ -182,7 +225,8 @@ index cd55520c..6a3f98bb 100644
+
+ } else if (ngx_strcmp(&names[i].data[6], "off") != 0) {
+ if (ngx_resolver_read_resolv_conf(cf, r,
+ &names[i].data[6])
+ &names[i].data[6],
+ names[i].len - 6)
+ != NGX_OK)
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,

@ -4,15 +4,14 @@ use Test::Nginx::Socket::Lua;
#worker_connections(1014);
#master_process_enabled(1);
log_level('warn');
log_level('debug');
#repeat_each(120);
repeat_each(2);
repeat_each(1);
plan tests => repeat_each() * (blocks() * 2);
plan tests => repeat_each() * (blocks() * 5);
#no_diff();
#no_long_string();
no_long_string();
run_tests();
@ -28,7 +27,7 @@ __DATA__
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to ", server, ": ", err)
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
@ -39,9 +38,11 @@ __DATA__
GET /t
--- response_body
successfully connected to openresty.org
--- no_error
--- no_error_log
[error]
[crit]
--- error_log
parsed a resolver: "
@ -55,7 +56,7 @@ successfully connected to openresty.org
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to ", server, ": ", err)
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
@ -68,10 +69,11 @@ nameser 8.8.8.8"
--- request
GET /t
--- response_body
failed to connect to nil: no resolver defined to resolve "openresty.org"
--- no_error
failed to connect to openresty.org: no resolver defined to resolve "openresty.org"
--- no_error_log
[error]
[crit]
parsed a resolver: "
@ -85,7 +87,7 @@ failed to connect to nil: no resolver defined to resolve "openresty.org"
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to ", server, ": ", err)
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
@ -98,10 +100,11 @@ nameser 8.8.8.8"
--- request
GET /t
--- response_body
failed to connect to nil: no resolver defined to resolve "openresty.org"
--- no_error
failed to connect to openresty.org: no resolver defined to resolve "openresty.org"
--- no_error_log
[error]
[crit]
parsed a resolver: "
@ -115,7 +118,7 @@ failed to connect to nil: no resolver defined to resolve "openresty.org"
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to ", server, ": ", err)
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
@ -131,9 +134,13 @@ nameserver 8.8.4.4"
GET /t
--- response_body
successfully connected to openresty.org
--- no_error
--- no_error_log
[error]
[crit]
--- grep_error_log eval: qr/parsed a resolver: ".+"/
--- grep_error_log_out
parsed a resolver: "8.8.8.8"
parsed a resolver: "8.8.4.4"
@ -147,7 +154,7 @@ successfully connected to openresty.org
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to ", server, ": ", err)
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
@ -161,9 +168,13 @@ domain example.com\r\nnameserver 8.8.8.8\r\nnameserver 8.8.4.4"
GET /t
--- response_body
successfully connected to openresty.org
--- no_error
--- no_error_log
[error]
[crit]
--- grep_error_log eval: qr/parsed a resolver: ".+"/
--- grep_error_log_out
parsed a resolver: "8.8.8.8"
parsed a resolver: "8.8.4.4"
@ -177,7 +188,7 @@ successfully connected to openresty.org
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to ", server, ": ", err)
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
@ -191,6 +202,144 @@ successfully connected to openresty.org
GET /t
--- response_body
successfully connected to openresty.org
--- no_error
--- no_error_log
[error]
[crit]
--- grep_error_log eval: qr/parsed a resolver: ".+"/
--- grep_error_log_out
parsed a resolver: "8.8.8.8"
parsed a resolver: "8.8.4.4"
=== TEST 7: spaces and tabs before and after nameserver
--- config
resolver local=../html/resolv.conf ipv6=off;
resolver_timeout 5s;
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
sock:close()
}
}
--- user_files eval
">>> resolv.conf
domain example.com
\t \t \tnameserver \t \t 8.8.8.8
\t \t \tnameserver\t \t8.8.4.4"
--- request
GET /t
--- response_body
successfully connected to openresty.org
--- no_error_log
[error]
[crit]
--- grep_error_log eval: qr/parsed a resolver: ".+"/
--- grep_error_log_out
parsed a resolver: "8.8.8.8"
parsed a resolver: "8.8.4.4"
=== TEST 8: MAXNS is respected (on standard Glibc it is 3)
--- config
resolver local=../html/resolv.conf ipv6=off;
resolver_timeout 5s;
location /t {
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:connect("openresty.org", 80)
if not ok then
ngx.say("failed to connect to openresty.org: ", err)
return
end
ngx.say("successfully connected to openresty.org")
sock:close()
}
}
--- user_files eval
">>> resolv.conf
domain example.com
nameserver 8.8.8.8
nameserver 8.8.4.4
nameserver 208.67.222.222
nameserver 208.67.220.220"
--- request
GET /t
--- response_body
successfully connected to openresty.org
--- no_error_log
[error]
[crit]
--- grep_error_log eval: qr/parsed a resolver: ".+"/
--- grep_error_log_out
parsed a resolver: "8.8.8.8"
parsed a resolver: "8.8.4.4"
parsed a resolver: "208.67.222.222"
=== TEST 9: IPv6 is supported
--- config
resolver local=../html/resolv.conf ipv6=off;
resolver_timeout 5s;
location = /t {
content_by_lua_block {
ngx.say("done")
}
}
--- user_files eval
">>> resolv.conf
domain example.com
nameserver 2001:4860:4860::8888
nameserver 2001:4860:4860::8844"
--- request
GET /t
--- response_body
done
--- no_error_log
[crit]
[error]
--- grep_error_log eval: qr/parsed a resolver: ".+"/
--- grep_error_log_out
parsed a resolver: "[2001:4860:4860::8888]"
parsed a resolver: "[2001:4860:4860::8844]"
=== TEST 10: IPv6 with malformed and long address
--- config
resolver local=../html/resolv.conf ipv6=off;
resolver_timeout 5s;
location = /t {
content_by_lua_block {
ngx.say("done")
}
}
--- user_files eval
">>> resolv.conf
domain example.com
nameserver 2001:4860:4860::8888:2001:4860:4860::8888:2001
nameserver 2001:4860:4860::8844"
--- request
GET /t
--- response_body
done
--- no_error_log
[crit]
[error]
--- must_die
--- error_log
IPv6 resolver address is too long: "2001:4860:4860::8888:2001:4860:4860::8888:2001"
unable to parse local resolver

Loading…
Cancel
Save