mirror of
				https://github.com/openresty/openresty.git
				synced 2024-10-13 00:29:41 +00:00 
			
		
		
		
	bugfix: nginx patch: moved the include of resolv.h to after ngx_config.h to avoid compilation failures on FreeBSD. bugfix: patch: updated safe_resolver_ipv6_option.patch with new offsets to avoid confusing patch while applying. Signed-off-by: Yichun Zhang (agentzh) <agentzh@gmail.com>
		
			
				
	
	
		
			264 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			264 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
 | 
						|
index cd55520c..dade1846 100644
 | 
						|
--- a/src/core/ngx_resolver.c
 | 
						|
+++ b/src/core/ngx_resolver.c
 | 
						|
@@ -9,12 +9,26 @@
 | 
						|
 #include <ngx_core.h>
 | 
						|
 #include <ngx_event.h>
 | 
						|
 
 | 
						|
+#if !(NGX_WIN32)
 | 
						|
+#include <resolv.h>
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 
 | 
						|
 #define NGX_RESOLVER_UDP_SIZE   4096
 | 
						|
 
 | 
						|
 #define NGX_RESOLVER_TCP_RSIZE  (2 + 65535)
 | 
						|
 #define NGX_RESOLVER_TCP_WSIZE  8192
 | 
						|
 
 | 
						|
+#if !(NGX_WIN32)
 | 
						|
+/*
 | 
						|
+ * 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"
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 
 | 
						|
 typedef struct {
 | 
						|
     u_char  ident_hi;
 | 
						|
@@ -131,6 +145,191 @@ static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 
 | 
						|
+#if !(NGX_WIN32)
 | 
						|
+static ngx_int_t
 | 
						|
+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 = 0, j, total = 0;
 | 
						|
+    ssize_t                          n, i;
 | 
						|
+    enum {
 | 
						|
+        sw_nameserver,
 | 
						|
+        sw_spaces,
 | 
						|
+        sw_address,
 | 
						|
+        sw_skip
 | 
						|
+    } state;
 | 
						|
+
 | 
						|
+    file.name.data = path;
 | 
						|
+    file.name.len = path_len;
 | 
						|
+
 | 
						|
+    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 (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);
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    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_spaces;
 | 
						|
+                i += sizeof("nameserver") - 1;
 | 
						|
+
 | 
						|
+                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;
 | 
						|
+
 | 
						|
+                if (i == n - 1 && buf[i] != CR && buf[i] != LF) {
 | 
						|
+                    u.url.len = n - address;
 | 
						|
+
 | 
						|
+                } else {
 | 
						|
+                    u.url.len = 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,
 | 
						|
+                                           "%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++;
 | 
						|
+
 | 
						|
+#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;
 | 
						|
+            }
 | 
						|
+
 | 
						|
+            break;
 | 
						|
+
 | 
						|
+        case sw_skip:
 | 
						|
+            if (buf[i] == CR || buf[i] == LF) {
 | 
						|
+                state = sw_nameserver;
 | 
						|
+            }
 | 
						|
+
 | 
						|
+            break;
 | 
						|
+        }
 | 
						|
+
 | 
						|
+        i++;
 | 
						|
+    }
 | 
						|
+
 | 
						|
+    return NGX_OK;
 | 
						|
+}
 | 
						|
+#endif
 | 
						|
+
 | 
						|
+
 | 
						|
 ngx_resolver_t *
 | 
						|
 ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
 | 
						|
 {
 | 
						|
@@ -246,6 +445,39 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
 | 
						|
         }
 | 
						|
 #endif
 | 
						|
 
 | 
						|
+#if !(NGX_WIN32)
 | 
						|
+        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,
 | 
						|
+                                                  sizeof(NGX_RESOLVER_FILE_NAME)
 | 
						|
+                                                  - 1)
 | 
						|
+                    != 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],
 | 
						|
+                                                  names[i].len - 6)
 | 
						|
+                    != NGX_OK)
 | 
						|
+                {
 | 
						|
+                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
 | 
						|
+                                       "unable to parse local resolver");
 | 
						|
+                    return NULL;
 | 
						|
+                }
 | 
						|
+
 | 
						|
+            }
 | 
						|
+
 | 
						|
+            continue;
 | 
						|
+        }
 | 
						|
+#endif
 | 
						|
+
 | 
						|
         ngx_memzero(&u, sizeof(ngx_url_t));
 | 
						|
 
 | 
						|
         u.url = names[i];
 |