mirror of https://github.com/openresty/openresty
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
5.5 KiB
C
201 lines
5.5 KiB
C
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
|
|
index cd55520c..6a3f98bb 100644
|
|
--- a/src/core/ngx_resolver.c
|
|
+++ b/src/core/ngx_resolver.c
|
|
@@ -5,6 +5,7 @@
|
|
*/
|
|
|
|
|
|
+#include <resolv.h>
|
|
#include <ngx_config.h>
|
|
#include <ngx_core.h>
|
|
#include <ngx_event.h>
|
|
@@ -15,6 +16,14 @@
|
|
#define NGX_RESOLVER_TCP_RSIZE (2 + 65535)
|
|
#define NGX_RESOLVER_TCP_WSIZE 8192
|
|
|
|
+/*
|
|
+ * note that 2KB should be more than enough for majority of the
|
|
+ * resolv.conf files out there. it also acts as a safety guard to prevent
|
|
+ * abuse.
|
|
+ */
|
|
+#define NGX_RESOLVER_FILE_BUF_SIZE 2048
|
|
+#define NGX_RESOLVER_FILE_NAME "/etc/resolv.conf"
|
|
+
|
|
|
|
typedef struct {
|
|
u_char ident_hi;
|
|
@@ -131,6 +140,138 @@ 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, total = 0;
|
|
+ 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.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 && total < MAXNS; /* 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;
|
|
+ i += sizeof("nameserver ") - 1;
|
|
+ address = i;
|
|
+
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ 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.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;
|
|
+ }
|
|
+
|
|
+ total++;
|
|
+
|
|
+ state = sw_nameserver;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+
|
|
+ case sw_skip:
|
|
+ if (buf[i] == CR || 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 +387,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,
|
|
+ (u_char *) 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];
|