mirror of https://github.com/openresty/openresty
patch: added patch for parsing local resolvers defined in resolv.conf
and use them as resolv servers.pull/348/head
parent
23205d8114
commit
34adaa8ac8
@ -0,0 +1,192 @@
|
||||
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
|
||||
index cd55520c..06d1c461 100644
|
||||
--- a/src/core/ngx_resolver.c
|
||||
+++ b/src/core/ngx_resolver.c
|
||||
@@ -15,6 +15,9 @@
|
||||
#define NGX_RESOLVER_TCP_RSIZE (2 + 65535)
|
||||
#define NGX_RESOLVER_TCP_WSIZE 8192
|
||||
|
||||
+#define NGX_RESOLVER_FILE_BUF_SIZE 2048
|
||||
+#define NGX_RESOLVER_FILE_NAME "/etc/resolv.conf"
|
||||
+
|
||||
|
||||
typedef struct {
|
||||
u_char ident_hi;
|
||||
@@ -131,6 +134,143 @@ 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_url_t u;
|
||||
+ ngx_resolver_connection_t *rec;
|
||||
+ ngx_fd_t fd;
|
||||
+ ngx_file_t file;
|
||||
+ u_char buf[NGX_RESOLVER_FILE_BUF_SIZE];
|
||||
+ ngx_uint_t address, j;
|
||||
+ ssize_t n, i;
|
||||
+ enum {
|
||||
+ sw_nameserver,
|
||||
+ sw_address,
|
||||
+ sw_skip
|
||||
+ } state;
|
||||
+
|
||||
+ file.name.data = path;
|
||||
+ file.name.len = ngx_strlen(path);
|
||||
+
|
||||
+ if (ngx_conf_full_name(cf->cycle, &file.name, 1) != NGX_OK) {
|
||||
+ return NGX_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY,
|
||||
+ NGX_FILE_OPEN, 0);
|
||||
+
|
||||
+ if (fd == NGX_INVALID_FILE) {
|
||||
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
|
||||
+ ngx_open_file_n " \"%s\" failed", file.name.data);
|
||||
+
|
||||
+ return NGX_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ ngx_memzero(&file, sizeof(ngx_file_t));
|
||||
+
|
||||
+ file.fd = fd;
|
||||
+ file.name.data = path;
|
||||
+ file.name.len = ngx_strlen(path) - 1;
|
||||
+ file.log = cf->log;
|
||||
+
|
||||
+ state = sw_nameserver;
|
||||
+
|
||||
+ n = ngx_read_file(&file, buf, NGX_RESOLVER_FILE_BUF_SIZE, 0);
|
||||
+
|
||||
+ 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);
|
||||
+ }
|
||||
+
|
||||
+ if (n == NGX_ERROR) {
|
||||
+ return NGX_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (n == 0) {
|
||||
+ return NGX_OK;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < n; /* void */) {
|
||||
+ if (buf[i] == '#' || buf[i] == ';') {
|
||||
+ state = sw_skip;
|
||||
+ }
|
||||
+
|
||||
+ switch (state) {
|
||||
+
|
||||
+ case sw_nameserver:
|
||||
+
|
||||
+ if ((size_t) n - i >= sizeof("nameserver ") - 1
|
||||
+ && ngx_memcmp(buf + i, "nameserver ",
|
||||
+ sizeof("nameserver ") - 1) == 0)
|
||||
+ {
|
||||
+ state = sw_address;
|
||||
+ address = 0;
|
||||
+ i += sizeof("nameserver ") - 1;
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ case sw_address:
|
||||
+
|
||||
+ if (address == 0) {
|
||||
+ address = i;
|
||||
+ }
|
||||
+
|
||||
+ if (buf[i] == LF || i == n - 1) {
|
||||
+ ngx_memzero(&u, sizeof(ngx_url_t));
|
||||
+
|
||||
+ u.url.data = buf + address;
|
||||
+ u.url.len = i - address;
|
||||
+ u.default_port = 53;
|
||||
+
|
||||
+ if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
|
||||
+ if (u.err) {
|
||||
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
+ "%s in resolver \"%V\"",
|
||||
+ u.err, &u.url);
|
||||
+ }
|
||||
+
|
||||
+ return NGX_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ rec = ngx_array_push_n(&r->connections, u.naddrs);
|
||||
+ if (rec == NULL) {
|
||||
+ return NGX_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ ngx_memzero(rec, u.naddrs * sizeof(ngx_resolver_connection_t));
|
||||
+
|
||||
+ for (j = 0; j < u.naddrs; j++) {
|
||||
+ rec[j].sockaddr = u.addrs[j].sockaddr;
|
||||
+ rec[j].socklen = u.addrs[j].socklen;
|
||||
+ rec[j].server = u.addrs[j].name;
|
||||
+ rec[j].resolver = r;
|
||||
+ }
|
||||
+
|
||||
+ address = 0;
|
||||
+ state = sw_nameserver;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+
|
||||
+ case sw_skip:
|
||||
+ if (buf[i] == LF) {
|
||||
+ state = sw_nameserver;
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ return NGX_OK;
|
||||
+}
|
||||
+
|
||||
+
|
||||
ngx_resolver_t *
|
||||
ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
||||
{
|
||||
@@ -246,6 +386,33 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
|
||||
}
|
||||
#endif
|
||||
|
||||
+ if (ngx_strncmp(names[i].data, "local=", 6) == 0) {
|
||||
+
|
||||
+ if (ngx_strcmp(&names[i].data[6], "on") == 0) {
|
||||
+ if (ngx_resolver_read_resolv_conf(cf, r,
|
||||
+ NGX_RESOLVER_FILE_NAME)
|
||||
+ != NGX_OK)
|
||||
+ {
|
||||
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
+ "unable to parse local resolver");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ } else if (ngx_strcmp(&names[i].data[6], "off") != 0) {
|
||||
+ if (ngx_resolver_read_resolv_conf(cf, r,
|
||||
+ &names[i].data[6])
|
||||
+ != NGX_OK)
|
||||
+ {
|
||||
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
+ "unable to parse local resolver");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||
|
||||
u.url = names[i];
|
@ -0,0 +1,136 @@
|
||||
# vim:set ft= ts=4 sw=4 et fdm=marker:
|
||||
|
||||
use Test::Nginx::Socket::Lua;
|
||||
|
||||
#worker_connections(1014);
|
||||
#master_process_enabled(1);
|
||||
log_level('warn');
|
||||
|
||||
#repeat_each(120);
|
||||
repeat_each(2);
|
||||
|
||||
plan tests => repeat_each() * (blocks() * 2);
|
||||
|
||||
#no_diff();
|
||||
#no_long_string();
|
||||
|
||||
run_tests();
|
||||
|
||||
__DATA__
|
||||
|
||||
=== TEST 1: use system resolver
|
||||
--- config
|
||||
resolver local=on 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 ", server, ": ", err)
|
||||
return
|
||||
end
|
||||
ngx.say("successfully connected to openresty.org")
|
||||
sock:close()
|
||||
}
|
||||
}
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
successfully connected to openresty.org
|
||||
--- no_error
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 2: malformed file
|
||||
--- 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 ", server, ": ", err)
|
||||
return
|
||||
end
|
||||
ngx.say("successfully connected to openresty.org")
|
||||
sock:close()
|
||||
}
|
||||
}
|
||||
--- user_files eval
|
||||
">>> resolv.conf
|
||||
nameser 8.8.8.8"
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
failed to connect to nil: no resolver defined to resolve "openresty.org"
|
||||
--- no_error
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 3: disabled
|
||||
--- config
|
||||
resolver local=off 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 ", server, ": ", err)
|
||||
return
|
||||
end
|
||||
ngx.say("successfully connected to openresty.org")
|
||||
sock:close()
|
||||
}
|
||||
}
|
||||
--- user_files eval
|
||||
">>> resolv.conf
|
||||
nameser 8.8.8.8"
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
failed to connect to nil: no resolver defined to resolve "openresty.org"
|
||||
--- no_error
|
||||
[error]
|
||||
[crit]
|
||||
|
||||
|
||||
|
||||
=== TEST 4: multiple resolvers
|
||||
--- 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 ", server, ": ", 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"
|
||||
--- request
|
||||
GET /t
|
||||
--- response_body
|
||||
successfully connected to openresty.org
|
||||
--- no_error
|
||||
[error]
|
||||
[crit]
|
Loading…
Reference in New Issue