Mercurial > hg > nginx
annotate src/core/ngx_resolver.c @ 5475:07dd5bd222ac
Changed resolver API to use ngx_addr_t.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Fri, 06 Dec 2013 14:30:27 +0400 |
parents | b43b02bb54db |
children | 950c9ed3e66f |
rev | line source |
---|---|
583 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4412 | 4 * Copyright (C) Nginx, Inc. |
583 | 5 */ |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_event.h> | |
11 | |
12 | |
1649 | 13 #define NGX_RESOLVER_UDP_SIZE 4096 |
14 | |
15 | |
583 | 16 typedef struct { |
1649 | 17 u_char ident_hi; |
18 u_char ident_lo; | |
19 u_char flags_hi; | |
20 u_char flags_lo; | |
21 u_char nqs_hi; | |
22 u_char nqs_lo; | |
23 u_char nan_hi; | |
24 u_char nan_lo; | |
25 u_char nns_hi; | |
26 u_char nns_lo; | |
27 u_char nar_hi; | |
28 u_char nar_lo; | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
29 } ngx_resolver_hdr_t; |
1649 | 30 |
31 | |
32 typedef struct { | |
33 u_char type_hi; | |
34 u_char type_lo; | |
35 u_char class_hi; | |
36 u_char class_lo; | |
37 } ngx_resolver_qs_t; | |
38 | |
39 | |
40 typedef struct { | |
41 u_char type_hi; | |
42 u_char type_lo; | |
43 u_char class_hi; | |
44 u_char class_lo; | |
45 u_char ttl[4]; | |
46 u_char len_hi; | |
47 u_char len_lo; | |
48 } ngx_resolver_an_t; | |
49 | |
50 | |
51 ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc); | |
52 | |
53 | |
1906 | 54 static void ngx_resolver_cleanup(void *data); |
55 static void ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree); | |
1649 | 56 static ngx_int_t ngx_resolve_name_locked(ngx_resolver_t *r, |
57 ngx_resolver_ctx_t *ctx); | |
58 static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, | |
59 ngx_queue_t *queue); | |
60 static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r, | |
61 ngx_resolver_node_t *rn); | |
62 static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_node_t *rn, | |
63 ngx_resolver_ctx_t *ctx); | |
64 static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, | |
65 ngx_resolver_ctx_t *ctx); | |
66 static void ngx_resolver_resend_handler(ngx_event_t *ev); | |
67 static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, | |
68 ngx_queue_t *queue); | |
69 static void ngx_resolver_read_response(ngx_event_t *rev); | |
70 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, | |
71 size_t n); | |
72 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n, | |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
73 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans); |
1649 | 74 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
75 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan); |
1649 | 76 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r, |
77 ngx_str_t *name, uint32_t hash); | |
78 static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r, | |
79 in_addr_t addr); | |
80 static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
81 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); | |
82 static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, | |
83 u_char *buf, u_char *src, u_char *last); | |
84 static void ngx_resolver_timeout_handler(ngx_event_t *ev); | |
85 static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn); | |
86 static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size); | |
1903 | 87 static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size); |
1649 | 88 static void ngx_resolver_free(ngx_resolver_t *r, void *p); |
89 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p); | |
90 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size); | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
91 static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src, |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
92 ngx_uint_t n, ngx_uint_t rotate); |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
93 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len); |
1649 | 94 |
95 | |
96 ngx_resolver_t * | |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
97 ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n) |
1649 | 98 { |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
99 ngx_str_t s; |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
100 ngx_url_t u; |
4684
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
101 ngx_uint_t i, j; |
1649 | 102 ngx_resolver_t *r; |
1906 | 103 ngx_pool_cleanup_t *cln; |
1649 | 104 ngx_udp_connection_t *uc; |
105 | |
1913
c0f873458e2b
use cf->cycle->new_log because at merge stage cf->pool->log is old log
Igor Sysoev <igor@sysoev.ru>
parents:
1906
diff
changeset
|
106 cln = ngx_pool_cleanup_add(cf->pool, 0); |
1906 | 107 if (cln == NULL) { |
108 return NULL; | |
109 } | |
110 | |
111 cln->handler = ngx_resolver_cleanup; | |
112 | |
1913
c0f873458e2b
use cf->cycle->new_log because at merge stage cf->pool->log is old log
Igor Sysoev <igor@sysoev.ru>
parents:
1906
diff
changeset
|
113 r = ngx_calloc(sizeof(ngx_resolver_t), cf->log); |
1649 | 114 if (r == NULL) { |
115 return NULL; | |
116 } | |
117 | |
1906 | 118 cln->data = r; |
119 | |
1913
c0f873458e2b
use cf->cycle->new_log because at merge stage cf->pool->log is old log
Igor Sysoev <igor@sysoev.ru>
parents:
1906
diff
changeset
|
120 r->event = ngx_calloc(sizeof(ngx_event_t), cf->log); |
1649 | 121 if (r->event == NULL) { |
122 return NULL; | |
123 } | |
124 | |
1687 | 125 ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel, |
126 ngx_resolver_rbtree_insert_value); | |
127 | |
128 ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel, | |
129 ngx_rbtree_insert_value); | |
1649 | 130 |
1685 | 131 ngx_queue_init(&r->name_resend_queue); |
132 ngx_queue_init(&r->addr_resend_queue); | |
133 | |
134 ngx_queue_init(&r->name_expire_queue); | |
135 ngx_queue_init(&r->addr_expire_queue); | |
1649 | 136 |
137 r->event->handler = ngx_resolver_resend_handler; | |
138 r->event->data = r; | |
2785
d478379e51ac
*) refactor error_log processing: listen socket log might inherit built-in
Igor Sysoev <igor@sysoev.ru>
parents:
2490
diff
changeset
|
139 r->event->log = &cf->cycle->new_log; |
1649 | 140 r->ident = -1; |
141 | |
142 r->resend_timeout = 5; | |
143 r->expire = 30; | |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
144 r->valid = 0; |
1649 | 145 |
2785
d478379e51ac
*) refactor error_log processing: listen socket log might inherit built-in
Igor Sysoev <igor@sysoev.ru>
parents:
2490
diff
changeset
|
146 r->log = &cf->cycle->new_log; |
3763
beca53d6ab3c
decrease resolver errors level to error
Igor Sysoev <igor@sysoev.ru>
parents:
3642
diff
changeset
|
147 r->log_level = NGX_LOG_ERR; |
1649 | 148 |
4784
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
149 if (n) { |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
150 if (ngx_array_init(&r->udp_connections, cf->pool, n, |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
151 sizeof(ngx_udp_connection_t)) |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
152 != NGX_OK) |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
153 { |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
154 return NULL; |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
155 } |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
156 } |
dd63abf20ba7
Resolver: fixed possible memory leak in ngx_resolver_create().
Maxim Dounin <mdounin@mdounin.ru>
parents:
4684
diff
changeset
|
157 |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
158 for (i = 0; i < n; i++) { |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
159 if (ngx_strncmp(names[i].data, "valid=", 6) == 0) { |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
160 s.len = names[i].len - 6; |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
161 s.data = names[i].data + 6; |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
162 |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
163 r->valid = ngx_parse_time(&s, 1); |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
164 |
4474 | 165 if (r->valid == (time_t) NGX_ERROR) { |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
166 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
167 "invalid parameter: %V", &names[i]); |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
168 return NULL; |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
169 } |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
170 |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
171 continue; |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
172 } |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
173 |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
174 ngx_memzero(&u, sizeof(ngx_url_t)); |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
175 |
4671
af9342747669
Support for IPv6 literals and an optional port in resolver.
Ruslan Ermilov <ru@nginx.com>
parents:
4653
diff
changeset
|
176 u.url = names[i]; |
af9342747669
Support for IPv6 literals and an optional port in resolver.
Ruslan Ermilov <ru@nginx.com>
parents:
4653
diff
changeset
|
177 u.default_port = 53; |
af9342747669
Support for IPv6 literals and an optional port in resolver.
Ruslan Ermilov <ru@nginx.com>
parents:
4653
diff
changeset
|
178 |
af9342747669
Support for IPv6 literals and an optional port in resolver.
Ruslan Ermilov <ru@nginx.com>
parents:
4653
diff
changeset
|
179 if (ngx_parse_url(cf->pool, &u) != NGX_OK) { |
4643
bc5f881323b8
Fixed potential null pointer dereference in ngx_resolver_create().
Ruslan Ermilov <ru@nginx.com>
parents:
4619
diff
changeset
|
180 if (u.err) { |
bc5f881323b8
Fixed potential null pointer dereference in ngx_resolver_create().
Ruslan Ermilov <ru@nginx.com>
parents:
4619
diff
changeset
|
181 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
bc5f881323b8
Fixed potential null pointer dereference in ngx_resolver_create().
Ruslan Ermilov <ru@nginx.com>
parents:
4619
diff
changeset
|
182 "%s in resolver \"%V\"", |
4671
af9342747669
Support for IPv6 literals and an optional port in resolver.
Ruslan Ermilov <ru@nginx.com>
parents:
4653
diff
changeset
|
183 u.err, &u.url); |
4643
bc5f881323b8
Fixed potential null pointer dereference in ngx_resolver_create().
Ruslan Ermilov <ru@nginx.com>
parents:
4619
diff
changeset
|
184 } |
bc5f881323b8
Fixed potential null pointer dereference in ngx_resolver_create().
Ruslan Ermilov <ru@nginx.com>
parents:
4619
diff
changeset
|
185 |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
186 return NULL; |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
187 } |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
188 |
4684
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
189 uc = ngx_array_push_n(&r->udp_connections, u.naddrs); |
1683
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
190 if (uc == NULL) { |
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
191 return NULL; |
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
192 } |
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
193 |
4684
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
194 ngx_memzero(uc, u.naddrs * sizeof(ngx_udp_connection_t)); |
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
195 |
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
196 for (j = 0; j < u.naddrs; j++) { |
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
197 uc[j].sockaddr = u.addrs[j].sockaddr; |
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
198 uc[j].socklen = u.addrs[j].socklen; |
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
199 uc[j].server = u.addrs[j].name; |
f5c2c9d656f9
When "resolver" is configured with a domain name, only the first
Ruslan Ermilov <ru@nginx.com>
parents:
4683
diff
changeset
|
200 } |
1683
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
201 } |
1649 | 202 |
203 return r; | |
204 } | |
205 | |
206 | |
1906 | 207 static void |
208 ngx_resolver_cleanup(void *data) | |
209 { | |
210 ngx_resolver_t *r = data; | |
211 | |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
212 ngx_uint_t i; |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
213 ngx_udp_connection_t *uc; |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
214 |
1906 | 215 if (r) { |
216 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, | |
217 "cleanup resolver"); | |
218 | |
219 ngx_resolver_cleanup_tree(r, &r->name_rbtree); | |
220 | |
221 ngx_resolver_cleanup_tree(r, &r->addr_rbtree); | |
222 | |
223 if (r->event) { | |
224 ngx_free(r->event); | |
225 } | |
226 | |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
227 |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
228 uc = r->udp_connections.elts; |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
229 |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
230 for (i = 0; i < r->udp_connections.nelts; i++) { |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
231 if (uc[i].connection) { |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
232 ngx_close_connection(uc[i].connection); |
1906 | 233 } |
234 } | |
235 | |
236 ngx_free(r); | |
237 } | |
238 } | |
239 | |
240 | |
241 static void | |
242 ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree) | |
243 { | |
244 ngx_resolver_ctx_t *ctx, *next; | |
245 ngx_resolver_node_t *rn; | |
246 | |
247 while (tree->root != tree->sentinel) { | |
248 | |
249 rn = (ngx_resolver_node_t *) ngx_rbtree_min(tree->root, tree->sentinel); | |
250 | |
251 ngx_queue_remove(&rn->queue); | |
252 | |
253 for (ctx = rn->waiting; ctx; ctx = next) { | |
2006
b52cb9bf2064
style fix: remove tabs and trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1969
diff
changeset
|
254 next = ctx->next; |
1906 | 255 |
256 if (ctx->event) { | |
257 ngx_resolver_free(r, ctx->event); | |
258 } | |
259 | |
260 ngx_resolver_free(r, ctx); | |
261 } | |
262 | |
263 ngx_rbtree_delete(tree, &rn->node); | |
264 | |
265 ngx_resolver_free_node(r, rn); | |
266 } | |
267 } | |
268 | |
269 | |
1649 | 270 ngx_resolver_ctx_t * |
271 ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp) | |
272 { | |
273 in_addr_t addr; | |
274 ngx_resolver_ctx_t *ctx; | |
275 | |
276 if (temp) { | |
277 addr = ngx_inet_addr(temp->name.data, temp->name.len); | |
278 | |
279 if (addr != INADDR_NONE) { | |
280 temp->resolver = r; | |
281 temp->state = NGX_OK; | |
282 temp->naddrs = 1; | |
283 temp->addrs = &temp->addr; | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
284 temp->addr.sockaddr = (struct sockaddr *) &temp->sin; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
285 temp->addr.socklen = sizeof(struct sockaddr_in); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
286 ngx_memzero(&temp->sin, sizeof(struct sockaddr_in)); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
287 temp->sin.sin_family = AF_INET; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
288 temp->sin.sin_addr.s_addr = addr; |
1649 | 289 temp->quick = 1; |
290 | |
291 return temp; | |
292 } | |
293 } | |
294 | |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
295 if (r->udp_connections.nelts == 0) { |
1683
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
296 return NGX_NO_RESOLVER; |
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
297 } |
1e0b028055ec
allow to use IP addresses without defined resolver
Igor Sysoev <igor@sysoev.ru>
parents:
1679
diff
changeset
|
298 |
1649 | 299 ctx = ngx_resolver_calloc(r, sizeof(ngx_resolver_ctx_t)); |
300 | |
301 if (ctx) { | |
302 ctx->resolver = r; | |
303 } | |
304 | |
305 return ctx; | |
306 } | |
307 | |
308 | |
309 ngx_int_t | |
310 ngx_resolve_name(ngx_resolver_ctx_t *ctx) | |
311 { | |
312 ngx_int_t rc; | |
313 ngx_resolver_t *r; | |
314 | |
315 r = ctx->resolver; | |
316 | |
317 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, | |
318 "resolve: \"%V\"", &ctx->name); | |
319 | |
320 if (ctx->quick) { | |
321 ctx->handler(ctx); | |
322 return NGX_OK; | |
323 } | |
324 | |
325 /* lock name mutex */ | |
326 | |
327 rc = ngx_resolve_name_locked(r, ctx); | |
328 | |
329 if (rc == NGX_OK) { | |
330 return NGX_OK; | |
331 } | |
332 | |
333 /* unlock name mutex */ | |
334 | |
335 if (rc == NGX_AGAIN) { | |
336 return NGX_OK; | |
337 } | |
338 | |
1904
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
339 /* NGX_ERROR */ |
1649 | 340 |
341 if (ctx->event) { | |
1904
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
342 ngx_resolver_free(r, ctx->event); |
1649 | 343 } |
344 | |
1904
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
345 ngx_resolver_free(r, ctx); |
1649 | 346 |
347 return NGX_ERROR; | |
348 } | |
349 | |
350 | |
351 void | |
352 ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) | |
353 { | |
354 uint32_t hash; | |
355 ngx_resolver_t *r; | |
356 ngx_resolver_ctx_t *w, **p; | |
357 ngx_resolver_node_t *rn; | |
358 | |
359 r = ctx->resolver; | |
360 | |
361 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, | |
362 "resolve name done: %i", ctx->state); | |
363 | |
364 if (ctx->quick) { | |
365 return; | |
366 } | |
367 | |
368 if (ctx->event && ctx->event->timer_set) { | |
369 ngx_del_timer(ctx->event); | |
370 } | |
371 | |
372 /* lock name mutex */ | |
373 | |
374 if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { | |
375 | |
376 hash = ngx_crc32_short(ctx->name.data, ctx->name.len); | |
377 | |
378 rn = ngx_resolver_lookup_name(r, &ctx->name, hash); | |
379 | |
380 if (rn) { | |
381 p = &rn->waiting; | |
382 w = rn->waiting; | |
383 | |
384 while (w) { | |
385 if (w == ctx) { | |
386 *p = w->next; | |
387 | |
388 goto done; | |
389 } | |
390 | |
391 p = &w->next; | |
392 w = w->next; | |
393 } | |
394 } | |
395 | |
396 ngx_log_error(NGX_LOG_ALERT, r->log, 0, | |
397 "could not cancel %V resolving", &ctx->name); | |
398 } | |
399 | |
400 done: | |
401 | |
402 ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue); | |
403 | |
404 /* unlock name mutex */ | |
405 | |
1904
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
406 /* lock alloc mutex */ |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
407 |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
408 if (ctx->event) { |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
409 ngx_resolver_free_locked(r, ctx->event); |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
410 } |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
411 |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
412 ngx_resolver_free_locked(r, ctx); |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
413 |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
414 /* unlock alloc mutex */ |
1649 | 415 } |
416 | |
417 | |
418 /* NGX_RESOLVE_A only */ | |
419 | |
420 static ngx_int_t | |
421 ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) | |
422 { | |
423 uint32_t hash; | |
1961
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
424 ngx_int_t rc; |
1649 | 425 ngx_uint_t naddrs; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
426 ngx_addr_t *addrs; |
1649 | 427 ngx_resolver_ctx_t *next; |
428 ngx_resolver_node_t *rn; | |
429 | |
430 hash = ngx_crc32_short(ctx->name.data, ctx->name.len); | |
431 | |
432 rn = ngx_resolver_lookup_name(r, &ctx->name, hash); | |
433 | |
434 if (rn) { | |
435 | |
436 if (rn->valid >= ngx_time()) { | |
437 | |
438 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached"); | |
439 | |
440 ngx_queue_remove(&rn->queue); | |
441 | |
442 rn->expire = ngx_time() + r->expire; | |
443 | |
444 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); | |
445 | |
446 naddrs = rn->naddrs; | |
447 | |
448 if (naddrs) { | |
449 | |
450 /* NGX_RESOLVE_A answer */ | |
451 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
452 if (naddrs == 1) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
453 addrs = NULL; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
454 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
455 } else { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
456 addrs = ngx_resolver_export(r, rn->u.addrs, naddrs, 1); |
1649 | 457 if (addrs == NULL) { |
458 return NGX_ERROR; | |
459 } | |
460 } | |
461 | |
462 ctx->next = rn->waiting; | |
463 rn->waiting = NULL; | |
464 | |
465 /* unlock name mutex */ | |
466 | |
467 do { | |
468 ctx->state = NGX_OK; | |
469 ctx->naddrs = naddrs; | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
470 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
471 if (addrs == NULL) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
472 ctx->addrs = &ctx->addr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
473 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
474 ctx->addr.socklen = sizeof(struct sockaddr_in); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
475 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in)); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
476 ctx->sin.sin_family = AF_INET; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
477 ctx->sin.sin_addr.s_addr = rn->u.addr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
478 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
479 } else { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
480 ctx->addrs = addrs; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
481 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
482 |
1649 | 483 next = ctx->next; |
484 | |
485 ctx->handler(ctx); | |
486 | |
487 ctx = next; | |
488 } while (ctx); | |
489 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
490 if (addrs != NULL) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
491 ngx_resolver_free(r, addrs->sockaddr); |
1649 | 492 ngx_resolver_free(r, addrs); |
493 } | |
494 | |
495 return NGX_OK; | |
496 } | |
497 | |
498 /* NGX_RESOLVE_CNAME */ | |
499 | |
1969 | 500 if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) { |
501 | |
502 ctx->name.len = rn->cnlen; | |
503 ctx->name.data = rn->u.cname; | |
504 | |
505 return ngx_resolve_name_locked(r, ctx); | |
506 } | |
507 | |
508 ctx->next = rn->waiting; | |
509 rn->waiting = NULL; | |
510 | |
511 /* unlock name mutex */ | |
512 | |
513 do { | |
514 ctx->state = NGX_RESOLVE_NXDOMAIN; | |
515 next = ctx->next; | |
516 | |
517 ctx->handler(ctx); | |
518 | |
519 ctx = next; | |
520 } while (ctx); | |
521 | |
522 return NGX_OK; | |
1649 | 523 } |
524 | |
525 if (rn->waiting) { | |
526 | |
527 ctx->next = rn->waiting; | |
528 rn->waiting = ctx; | |
3297 | 529 ctx->state = NGX_AGAIN; |
1649 | 530 |
531 return NGX_AGAIN; | |
532 } | |
533 | |
534 ngx_queue_remove(&rn->queue); | |
535 | |
536 /* lock alloc mutex */ | |
537 | |
4619
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
538 if (rn->query) { |
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
539 ngx_resolver_free_locked(r, rn->query); |
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
540 rn->query = NULL; |
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
541 } |
1649 | 542 |
543 if (rn->cnlen) { | |
544 ngx_resolver_free_locked(r, rn->u.cname); | |
545 } | |
546 | |
547 if (rn->naddrs > 1) { | |
548 ngx_resolver_free_locked(r, rn->u.addrs); | |
549 } | |
550 | |
551 /* unlock alloc mutex */ | |
552 | |
553 } else { | |
554 | |
555 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); | |
556 if (rn == NULL) { | |
557 return NGX_ERROR; | |
558 } | |
559 | |
560 rn->name = ngx_resolver_dup(r, ctx->name.data, ctx->name.len); | |
561 if (rn->name == NULL) { | |
562 ngx_resolver_free(r, rn); | |
563 return NGX_ERROR; | |
564 } | |
565 | |
566 rn->node.key = hash; | |
567 rn->nlen = (u_short) ctx->name.len; | |
1960
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
568 rn->query = NULL; |
1649 | 569 |
570 ngx_rbtree_insert(&r->name_rbtree, &rn->node); | |
571 } | |
572 | |
1961
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
573 rc = ngx_resolver_create_name_query(rn, ctx); |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
574 |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
575 if (rc == NGX_ERROR) { |
1649 | 576 goto failed; |
577 } | |
578 | |
1961
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
579 if (rc == NGX_DECLINED) { |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
580 ngx_rbtree_delete(&r->name_rbtree, &rn->node); |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
581 |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
582 ngx_resolver_free(r, rn->query); |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
583 ngx_resolver_free(r, rn->name); |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
584 ngx_resolver_free(r, rn); |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
585 |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
586 ctx->state = NGX_RESOLVE_NXDOMAIN; |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
587 ctx->handler(ctx); |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
588 |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
589 return NGX_OK; |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
590 } |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
591 |
1649 | 592 if (ngx_resolver_send_query(r, rn) != NGX_OK) { |
593 goto failed; | |
594 } | |
595 | |
596 if (ctx->event == NULL) { | |
597 ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); | |
598 if (ctx->event == NULL) { | |
599 goto failed; | |
600 } | |
601 | |
602 ctx->event->handler = ngx_resolver_timeout_handler; | |
603 ctx->event->data = ctx; | |
604 ctx->event->log = r->log; | |
605 ctx->ident = -1; | |
606 | |
607 ngx_add_timer(ctx->event, ctx->timeout); | |
608 } | |
609 | |
610 if (ngx_queue_empty(&r->name_resend_queue)) { | |
611 ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); | |
612 } | |
613 | |
614 rn->expire = ngx_time() + r->resend_timeout; | |
615 | |
616 ngx_queue_insert_head(&r->name_resend_queue, &rn->queue); | |
617 | |
618 rn->cnlen = 0; | |
619 rn->naddrs = 0; | |
620 rn->valid = 0; | |
621 rn->waiting = ctx; | |
622 | |
623 ctx->state = NGX_AGAIN; | |
624 | |
625 return NGX_AGAIN; | |
626 | |
627 failed: | |
628 | |
629 ngx_rbtree_delete(&r->name_rbtree, &rn->node); | |
630 | |
1960
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
631 if (rn->query) { |
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
632 ngx_resolver_free(r, rn->query); |
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
633 } |
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
634 |
1649 | 635 ngx_resolver_free(r, rn->name); |
636 | |
637 ngx_resolver_free(r, rn); | |
638 | |
639 return NGX_ERROR; | |
640 } | |
583 | 641 |
642 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
643 /* AF_INET only */ |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
644 |
583 | 645 ngx_int_t |
1649 | 646 ngx_resolve_addr(ngx_resolver_ctx_t *ctx) |
647 { | |
2484
cf3cd450049c
store name pointer in variable allocated on stack
Igor Sysoev <igor@sysoev.ru>
parents:
2483
diff
changeset
|
648 u_char *name; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
649 in_addr_t addr; |
1649 | 650 ngx_resolver_t *r; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
651 struct sockaddr_in *sin; |
1649 | 652 ngx_resolver_node_t *rn; |
653 | |
654 r = ctx->resolver; | |
655 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
656 if (ctx->addr.sockaddr->sa_family != AF_INET) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
657 return NGX_ERROR; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
658 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
659 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
660 sin = (struct sockaddr_in *) ctx->addr.sockaddr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
661 addr = ntohl(sin->sin_addr.s_addr); |
1649 | 662 |
663 /* lock addr mutex */ | |
664 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
665 rn = ngx_resolver_lookup_addr(r, addr); |
1649 | 666 |
667 if (rn) { | |
668 | |
669 if (rn->valid >= ngx_time()) { | |
670 | |
671 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached"); | |
672 | |
673 ngx_queue_remove(&rn->queue); | |
674 | |
675 rn->expire = ngx_time() + r->expire; | |
676 | |
677 ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue); | |
678 | |
2484
cf3cd450049c
store name pointer in variable allocated on stack
Igor Sysoev <igor@sysoev.ru>
parents:
2483
diff
changeset
|
679 name = ngx_resolver_dup(r, rn->name, rn->nlen); |
cf3cd450049c
store name pointer in variable allocated on stack
Igor Sysoev <igor@sysoev.ru>
parents:
2483
diff
changeset
|
680 if (name == NULL) { |
1649 | 681 goto failed; |
682 } | |
683 | |
2484
cf3cd450049c
store name pointer in variable allocated on stack
Igor Sysoev <igor@sysoev.ru>
parents:
2483
diff
changeset
|
684 ctx->name.len = rn->nlen; |
cf3cd450049c
store name pointer in variable allocated on stack
Igor Sysoev <igor@sysoev.ru>
parents:
2483
diff
changeset
|
685 ctx->name.data = name; |
cf3cd450049c
store name pointer in variable allocated on stack
Igor Sysoev <igor@sysoev.ru>
parents:
2483
diff
changeset
|
686 |
1649 | 687 /* unlock addr mutex */ |
688 | |
689 ctx->state = NGX_OK; | |
690 | |
691 ctx->handler(ctx); | |
692 | |
2484
cf3cd450049c
store name pointer in variable allocated on stack
Igor Sysoev <igor@sysoev.ru>
parents:
2483
diff
changeset
|
693 ngx_resolver_free(r, name); |
1649 | 694 |
695 return NGX_OK; | |
696 } | |
697 | |
698 if (rn->waiting) { | |
699 | |
700 ctx->next = rn->waiting; | |
701 rn->waiting = ctx; | |
3297 | 702 ctx->state = NGX_AGAIN; |
1649 | 703 |
2487
9b4dce95c744
fix return code, this fixes segfault when two or more
Igor Sysoev <igor@sysoev.ru>
parents:
2486
diff
changeset
|
704 /* unlock addr mutex */ |
9b4dce95c744
fix return code, this fixes segfault when two or more
Igor Sysoev <igor@sysoev.ru>
parents:
2486
diff
changeset
|
705 |
9b4dce95c744
fix return code, this fixes segfault when two or more
Igor Sysoev <igor@sysoev.ru>
parents:
2486
diff
changeset
|
706 return NGX_OK; |
1649 | 707 } |
708 | |
709 ngx_queue_remove(&rn->queue); | |
710 | |
711 ngx_resolver_free(r, rn->query); | |
1960
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
712 rn->query = NULL; |
1649 | 713 |
714 } else { | |
715 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); | |
716 if (rn == NULL) { | |
717 goto failed; | |
718 } | |
719 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
720 rn->node.key = addr; |
1960
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
721 rn->query = NULL; |
1649 | 722 |
723 ngx_rbtree_insert(&r->addr_rbtree, &rn->node); | |
724 } | |
725 | |
726 if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) { | |
727 goto failed; | |
728 } | |
729 | |
730 if (ngx_resolver_send_query(r, rn) != NGX_OK) { | |
731 goto failed; | |
732 } | |
733 | |
734 ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); | |
735 if (ctx->event == NULL) { | |
736 goto failed; | |
737 } | |
738 | |
739 ctx->event->handler = ngx_resolver_timeout_handler; | |
740 ctx->event->data = ctx; | |
741 ctx->event->log = r->log; | |
742 ctx->ident = -1; | |
743 | |
744 ngx_add_timer(ctx->event, ctx->timeout); | |
745 | |
746 if (ngx_queue_empty(&r->addr_resend_queue)) { | |
747 ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); | |
748 } | |
749 | |
750 rn->expire = ngx_time() + r->resend_timeout; | |
751 | |
752 ngx_queue_insert_head(&r->addr_resend_queue, &rn->queue); | |
753 | |
754 rn->cnlen = 0; | |
755 rn->naddrs = 0; | |
756 rn->name = NULL; | |
757 rn->nlen = 0; | |
758 rn->valid = 0; | |
759 rn->waiting = ctx; | |
760 | |
761 /* unlock addr mutex */ | |
762 | |
763 ctx->state = NGX_AGAIN; | |
764 | |
765 return NGX_OK; | |
766 | |
767 failed: | |
768 | |
769 if (rn) { | |
770 ngx_rbtree_delete(&r->addr_rbtree, &rn->node); | |
771 | |
1960
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
772 if (rn->query) { |
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
773 ngx_resolver_free(r, rn->query); |
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
774 } |
1609b3c3d604
fix memory leak on resolver query send failure
Igor Sysoev <igor@sysoev.ru>
parents:
1914
diff
changeset
|
775 |
1649 | 776 ngx_resolver_free(r, rn); |
777 } | |
778 | |
779 /* unlock addr mutex */ | |
780 | |
781 if (ctx->event) { | |
1904
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
782 ngx_resolver_free(r, ctx->event); |
1649 | 783 } |
784 | |
1904
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
785 ngx_resolver_free(r, ctx); |
1649 | 786 |
787 return NGX_ERROR; | |
788 } | |
789 | |
790 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
791 /* AF_INET only */ |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
792 |
1649 | 793 void |
794 ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx) | |
795 { | |
796 in_addr_t addr; | |
797 ngx_resolver_t *r; | |
798 ngx_resolver_ctx_t *w, **p; | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
799 struct sockaddr_in *sin; |
1649 | 800 ngx_resolver_node_t *rn; |
801 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
802 if (ctx->addr.sockaddr->sa_family != AF_INET) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
803 return; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
804 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
805 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
806 sin = (struct sockaddr_in *) ctx->addr.sockaddr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
807 addr = ntohl(sin->sin_addr.s_addr); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
808 |
1649 | 809 r = ctx->resolver; |
810 | |
811 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, | |
812 "resolve addr done: %i", ctx->state); | |
813 | |
814 if (ctx->event && ctx->event->timer_set) { | |
815 ngx_del_timer(ctx->event); | |
816 } | |
817 | |
818 /* lock addr mutex */ | |
819 | |
820 if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { | |
821 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
822 rn = ngx_resolver_lookup_addr(r, addr); |
1649 | 823 |
824 if (rn) { | |
825 p = &rn->waiting; | |
826 w = rn->waiting; | |
827 | |
828 while (w) { | |
829 if (w == ctx) { | |
830 *p = w->next; | |
831 | |
832 goto done; | |
833 } | |
834 | |
835 p = &w->next; | |
836 w = w->next; | |
837 } | |
838 } | |
839 | |
840 ngx_log_error(NGX_LOG_ALERT, r->log, 0, | |
841 "could not cancel %ud.%ud.%ud.%ud resolving", | |
842 (addr >> 24) & 0xff, (addr >> 16) & 0xff, | |
843 (addr >> 8) & 0xff, addr & 0xff); | |
844 } | |
845 | |
846 done: | |
847 | |
848 ngx_resolver_expire(r, &r->addr_rbtree, &r->addr_expire_queue); | |
849 | |
850 /* unlock addr mutex */ | |
851 | |
1904
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
852 /* lock alloc mutex */ |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
853 |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
854 if (ctx->event) { |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
855 ngx_resolver_free_locked(r, ctx->event); |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
856 } |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
857 |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
858 ngx_resolver_free_locked(r, ctx); |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
859 |
538f06aa8118
fix memory leaks, use unlocked ngx_resolver_free() for seldom failed cases
Igor Sysoev <igor@sysoev.ru>
parents:
1903
diff
changeset
|
860 /* unlock alloc mutex */ |
1649 | 861 } |
862 | |
863 | |
864 static void | |
865 ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue) | |
866 { | |
867 time_t now; | |
868 ngx_uint_t i; | |
869 ngx_queue_t *q; | |
870 ngx_resolver_node_t *rn; | |
871 | |
872 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver expire"); | |
873 | |
874 now = ngx_time(); | |
875 | |
876 for (i = 0; i < 2; i++) { | |
877 if (ngx_queue_empty(queue)) { | |
878 return; | |
879 } | |
880 | |
881 q = ngx_queue_last(queue); | |
882 | |
883 rn = ngx_queue_data(q, ngx_resolver_node_t, queue); | |
884 | |
885 if (now <= rn->expire) { | |
886 return; | |
887 } | |
888 | |
1774 | 889 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, |
890 "resolver expire \"%*s\"", (size_t) rn->nlen, rn->name); | |
1649 | 891 |
892 ngx_queue_remove(q); | |
893 | |
894 ngx_rbtree_delete(tree, &rn->node); | |
895 | |
896 ngx_resolver_free_node(r, rn); | |
897 } | |
898 } | |
899 | |
900 | |
901 static ngx_int_t | |
902 ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn) | |
903 { | |
904 ssize_t n; | |
905 ngx_udp_connection_t *uc; | |
906 | |
4225
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
907 uc = r->udp_connections.elts; |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
908 |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
909 uc = &uc[r->last_connection++]; |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
910 if (r->last_connection == r->udp_connections.nelts) { |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
911 r->last_connection = 0; |
016352c19049
Support of several servers in the "resolver" directive.
Igor Sysoev <igor@sysoev.ru>
parents:
3902
diff
changeset
|
912 } |
1649 | 913 |
914 if (uc->connection == NULL) { | |
4496
be6c250b827b
Fixed null pointer dereference in resolver (ticket #91).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4474
diff
changeset
|
915 |
be6c250b827b
Fixed null pointer dereference in resolver (ticket #91).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4474
diff
changeset
|
916 uc->log = *r->log; |
be6c250b827b
Fixed null pointer dereference in resolver (ticket #91).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4474
diff
changeset
|
917 uc->log.handler = ngx_resolver_log_error; |
be6c250b827b
Fixed null pointer dereference in resolver (ticket #91).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4474
diff
changeset
|
918 uc->log.data = uc; |
be6c250b827b
Fixed null pointer dereference in resolver (ticket #91).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4474
diff
changeset
|
919 uc->log.action = "resolving"; |
be6c250b827b
Fixed null pointer dereference in resolver (ticket #91).
Maxim Dounin <mdounin@mdounin.ru>
parents:
4474
diff
changeset
|
920 |
1649 | 921 if (ngx_udp_connect(uc) != NGX_OK) { |
922 return NGX_ERROR; | |
923 } | |
924 | |
925 uc->connection->data = r; | |
926 uc->connection->read->handler = ngx_resolver_read_response; | |
1906 | 927 uc->connection->read->resolver = 1; |
1649 | 928 } |
929 | |
930 n = ngx_send(uc->connection, rn->query, rn->qlen); | |
931 | |
932 if (n == -1) { | |
933 return NGX_ERROR; | |
934 } | |
935 | |
936 if ((size_t) n != (size_t) rn->qlen) { | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
937 ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete"); |
1649 | 938 return NGX_ERROR; |
939 } | |
940 | |
941 return NGX_OK; | |
942 } | |
943 | |
944 | |
945 static void | |
946 ngx_resolver_resend_handler(ngx_event_t *ev) | |
947 { | |
948 time_t timer, atimer, ntimer; | |
949 ngx_resolver_t *r; | |
950 | |
951 r = ev->data; | |
952 | |
953 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, | |
954 "resolver resend handler"); | |
955 | |
956 /* lock name mutex */ | |
957 | |
958 ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue); | |
959 | |
960 /* unlock name mutex */ | |
961 | |
962 /* lock addr mutex */ | |
963 | |
964 atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue); | |
1679
ca317d9b5c09
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1649
diff
changeset
|
965 |
1649 | 966 /* unlock addr mutex */ |
967 | |
968 if (ntimer == 0) { | |
969 timer = atimer; | |
970 | |
971 } else if (atimer == 0) { | |
972 timer = ntimer; | |
973 | |
974 } else { | |
975 timer = (atimer < ntimer) ? atimer : ntimer; | |
976 } | |
977 | |
978 if (timer) { | |
979 ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000)); | |
980 } | |
981 } | |
982 | |
983 | |
984 static time_t | |
985 ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue) | |
986 { | |
987 time_t now; | |
988 ngx_queue_t *q; | |
989 ngx_resolver_node_t *rn; | |
990 | |
991 now = ngx_time(); | |
992 | |
993 for ( ;; ) { | |
994 if (ngx_queue_empty(queue)) { | |
995 return 0; | |
996 } | |
997 | |
998 q = ngx_queue_last(queue); | |
999 | |
1000 rn = ngx_queue_data(q, ngx_resolver_node_t, queue); | |
1001 | |
1002 if (now < rn->expire) { | |
1003 return rn->expire - now; | |
1004 } | |
1005 | |
1774 | 1006 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, |
1007 "resolver resend \"%*s\" %p", | |
1008 (size_t) rn->nlen, rn->name, rn->waiting); | |
1649 | 1009 |
1010 ngx_queue_remove(q); | |
1011 | |
1012 if (rn->waiting) { | |
1013 | |
4683
84d8e60b65f0
Fixed crash in ngx_resolver_cleanup_tree().
Ruslan Ermilov <ru@nginx.com>
parents:
4671
diff
changeset
|
1014 (void) ngx_resolver_send_query(r, rn); |
84d8e60b65f0
Fixed crash in ngx_resolver_cleanup_tree().
Ruslan Ermilov <ru@nginx.com>
parents:
4671
diff
changeset
|
1015 |
84d8e60b65f0
Fixed crash in ngx_resolver_cleanup_tree().
Ruslan Ermilov <ru@nginx.com>
parents:
4671
diff
changeset
|
1016 rn->expire = now + r->resend_timeout; |
84d8e60b65f0
Fixed crash in ngx_resolver_cleanup_tree().
Ruslan Ermilov <ru@nginx.com>
parents:
4671
diff
changeset
|
1017 |
84d8e60b65f0
Fixed crash in ngx_resolver_cleanup_tree().
Ruslan Ermilov <ru@nginx.com>
parents:
4671
diff
changeset
|
1018 ngx_queue_insert_head(queue, q); |
1879
cf4ee321d195
do not delete failed DNS request if there are waiting clients
Igor Sysoev <igor@sysoev.ru>
parents:
1878
diff
changeset
|
1019 |
cf4ee321d195
do not delete failed DNS request if there are waiting clients
Igor Sysoev <igor@sysoev.ru>
parents:
1878
diff
changeset
|
1020 continue; |
1649 | 1021 } |
1022 | |
1023 ngx_rbtree_delete(tree, &rn->node); | |
1024 | |
1025 ngx_resolver_free_node(r, rn); | |
1026 } | |
1027 } | |
1028 | |
1029 | |
1030 static void | |
1031 ngx_resolver_read_response(ngx_event_t *rev) | |
1032 { | |
1033 ssize_t n; | |
1034 ngx_connection_t *c; | |
1035 u_char buf[NGX_RESOLVER_UDP_SIZE]; | |
1036 | |
1037 c = rev->data; | |
1038 | |
1039 do { | |
1689 | 1040 n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE); |
1041 | |
1042 if (n < 0) { | |
1649 | 1043 return; |
1044 } | |
1045 | |
1046 ngx_resolver_process_response(c->data, buf, n); | |
1047 | |
1048 } while (rev->ready); | |
1049 } | |
1050 | |
1051 | |
1052 static void | |
1053 ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n) | |
1054 { | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1055 char *err; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1056 ngx_uint_t i, times, ident, qident, flags, code, nqs, nan, |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1057 qtype, qclass; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1058 ngx_queue_t *q; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1059 ngx_resolver_qs_t *qs; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1060 ngx_resolver_hdr_t *response; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1061 ngx_resolver_node_t *rn; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1062 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1063 if (n < sizeof(ngx_resolver_hdr_t)) { |
1649 | 1064 goto short_response; |
1065 } | |
1066 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1067 response = (ngx_resolver_hdr_t *) buf; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1068 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1069 ident = (response->ident_hi << 8) + response->ident_lo; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1070 flags = (response->flags_hi << 8) + response->flags_lo; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1071 nqs = (response->nqs_hi << 8) + response->nqs_lo; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1072 nan = (response->nan_hi << 8) + response->nan_lo; |
1649 | 1073 |
1074 ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0, | |
4653
134ccdf44647
Resolver: fixed format specification.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4643
diff
changeset
|
1075 "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud", |
1649 | 1076 ident, flags, nqs, nan, |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1077 (response->nns_hi << 8) + response->nns_lo, |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1078 (response->nar_hi << 8) + response->nar_lo); |
1649 | 1079 |
5470
aebdca7e8f8f
Resolver: fixed response processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5469
diff
changeset
|
1080 /* response to a standard query */ |
aebdca7e8f8f
Resolver: fixed response processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5469
diff
changeset
|
1081 if ((flags & 0xf870) != 0x8000) { |
1649 | 1082 ngx_log_error(r->log_level, r->log, 0, |
1967
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1083 "invalid DNS response %ui fl:%04Xui", ident, flags); |
1649 | 1084 return; |
1085 } | |
1086 | |
5470
aebdca7e8f8f
Resolver: fixed response processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5469
diff
changeset
|
1087 code = flags & 0xf; |
1649 | 1088 |
2282
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1089 if (code == NGX_RESOLVE_FORMERR) { |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1090 |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1091 times = 0; |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1092 |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1093 for (q = ngx_queue_head(&r->name_resend_queue); |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1094 q != ngx_queue_sentinel(&r->name_resend_queue) || times++ < 100; |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1095 q = ngx_queue_next(q)) |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1096 { |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1097 rn = ngx_queue_data(q, ngx_resolver_node_t, queue); |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1098 qident = (rn->query[0] << 8) + rn->query[1]; |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1099 |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1100 if (qident == ident) { |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1101 ngx_log_error(r->log_level, r->log, 0, |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1102 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"", |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1103 code, ngx_resolver_strerror(code), ident, |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1104 rn->nlen, rn->name); |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1105 return; |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1106 } |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1107 } |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1108 |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1109 goto dns_error; |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1110 } |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1111 |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1112 if (code > NGX_RESOLVE_REFUSED) { |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1113 goto dns_error; |
1649 | 1114 } |
1115 | |
1116 if (nqs != 1) { | |
1117 err = "invalid number of questions in DNS response"; | |
1118 goto done; | |
1119 } | |
1120 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1121 i = sizeof(ngx_resolver_hdr_t); |
1649 | 1122 |
1123 while (i < (ngx_uint_t) n) { | |
1124 if (buf[i] == '\0') { | |
1125 goto found; | |
1126 } | |
1127 | |
5470
aebdca7e8f8f
Resolver: fixed response processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5469
diff
changeset
|
1128 i += 1 + buf[i]; |
1649 | 1129 } |
1130 | |
1131 goto short_response; | |
1132 | |
1133 found: | |
1134 | |
5470
aebdca7e8f8f
Resolver: fixed response processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5469
diff
changeset
|
1135 if (i++ == sizeof(ngx_resolver_hdr_t)) { |
1649 | 1136 err = "zero-length domain name in DNS response"; |
1137 goto done; | |
1138 } | |
1139 | |
1140 if (i + sizeof(ngx_resolver_qs_t) + nan * (2 + sizeof(ngx_resolver_an_t)) | |
1141 > (ngx_uint_t) n) | |
1142 { | |
1143 goto short_response; | |
1144 } | |
1145 | |
1146 qs = (ngx_resolver_qs_t *) &buf[i]; | |
1147 | |
1148 qtype = (qs->type_hi << 8) + qs->type_lo; | |
1149 qclass = (qs->class_hi << 8) + qs->class_lo; | |
1150 | |
1151 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, | |
1967
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1152 "resolver DNS response qt:%ui cl:%ui", qtype, qclass); |
1649 | 1153 |
1154 if (qclass != 1) { | |
1155 ngx_log_error(r->log_level, r->log, 0, | |
1967
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1156 "unknown query class %ui in DNS response", qclass); |
1649 | 1157 return; |
1158 } | |
1159 | |
1160 switch (qtype) { | |
1161 | |
1162 case NGX_RESOLVE_A: | |
1163 | |
1164 ngx_resolver_process_a(r, buf, n, ident, code, nan, | |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1165 i + sizeof(ngx_resolver_qs_t)); |
1649 | 1166 |
1167 break; | |
1168 | |
1169 case NGX_RESOLVE_PTR: | |
1170 | |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1171 ngx_resolver_process_ptr(r, buf, n, ident, code, nan); |
1649 | 1172 |
1173 break; | |
1174 | |
1175 default: | |
1176 ngx_log_error(r->log_level, r->log, 0, | |
1967
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1177 "unknown query type %ui in DNS response", qtype); |
1649 | 1178 return; |
1179 } | |
1180 | |
1181 return; | |
1182 | |
1183 short_response: | |
1184 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1185 err = "short DNS response"; |
1649 | 1186 |
1187 done: | |
1188 | |
1189 ngx_log_error(r->log_level, r->log, 0, err); | |
1190 | |
1191 return; | |
2282
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1192 |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1193 dns_error: |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1194 |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1195 ngx_log_error(r->log_level, r->log, 0, |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1196 "DNS error (%ui: %s), query id:%ui", |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1197 code, ngx_resolver_strerror(code), ident); |
ec97eb9a8038
show name for a FORMERR DNS response
Igor Sysoev <igor@sysoev.ru>
parents:
2281
diff
changeset
|
1198 return; |
1649 | 1199 } |
1200 | |
1201 | |
1202 static void | |
1203 ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, | |
1204 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans) | |
583 | 1205 { |
1649 | 1206 char *err; |
1207 u_char *cname; | |
1208 size_t len; | |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1209 int32_t ttl; |
1649 | 1210 uint32_t hash; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1211 in_addr_t *addr; |
1649 | 1212 ngx_str_t name; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1213 ngx_addr_t *addrs; |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1214 ngx_uint_t type, class, qident, naddrs, a, i, n, start; |
1649 | 1215 ngx_resolver_an_t *an; |
1216 ngx_resolver_ctx_t *ctx, *next; | |
1217 ngx_resolver_node_t *rn; | |
1218 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1219 if (ngx_resolver_copy(r, &name, buf, |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1220 buf + sizeof(ngx_resolver_hdr_t), buf + last) |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1221 != NGX_OK) |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1222 { |
1649 | 1223 return; |
1224 } | |
1225 | |
1226 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name); | |
1227 | |
1228 hash = ngx_crc32_short(name.data, name.len); | |
1229 | |
1230 /* lock name mutex */ | |
1231 | |
1232 rn = ngx_resolver_lookup_name(r, &name, hash); | |
1233 | |
1234 if (rn == NULL || rn->query == NULL) { | |
1235 ngx_log_error(r->log_level, r->log, 0, | |
1236 "unexpected response for %V", &name); | |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1237 ngx_resolver_free(r, name.data); |
1649 | 1238 goto failed; |
1239 } | |
1240 | |
1241 qident = (rn->query[0] << 8) + rn->query[1]; | |
1242 | |
1243 if (ident != qident) { | |
1244 ngx_log_error(r->log_level, r->log, 0, | |
1967
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1245 "wrong ident %ui response for %V, expect %ui", |
1649 | 1246 ident, &name, qident); |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1247 ngx_resolver_free(r, name.data); |
1649 | 1248 goto failed; |
1249 } | |
1250 | |
3139 | 1251 ngx_resolver_free(r, name.data); |
1252 | |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1253 if (code == 0 && nan == 0) { |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1254 code = NGX_RESOLVE_NXDOMAIN; |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1255 } |
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1256 |
1649 | 1257 if (code) { |
1258 next = rn->waiting; | |
1259 rn->waiting = NULL; | |
1260 | |
1261 ngx_queue_remove(&rn->queue); | |
1262 | |
1263 ngx_rbtree_delete(&r->name_rbtree, &rn->node); | |
1264 | |
1265 ngx_resolver_free_node(r, rn); | |
1266 | |
1267 /* unlock name mutex */ | |
1268 | |
1269 while (next) { | |
5474
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1270 ctx = next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1271 ctx->state = code; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1272 next = ctx->next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1273 |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1274 ctx->handler(ctx); |
1649 | 1275 } |
1276 | |
1277 return; | |
1278 } | |
1279 | |
1280 i = ans; | |
1281 naddrs = 0; | |
1282 cname = NULL; | |
4296
783fd9c38d98
Silenced a warning for some compilers.
Ruslan Ermilov <ru@nginx.com>
parents:
4295
diff
changeset
|
1283 ttl = 0; |
1649 | 1284 |
1285 for (a = 0; a < nan; a++) { | |
1286 | |
1287 start = i; | |
1288 | |
1289 while (i < last) { | |
1290 | |
1291 if (buf[i] & 0xc0) { | |
1292 i += 2; | |
1293 goto found; | |
1294 } | |
1295 | |
1296 if (buf[i] == 0) { | |
1297 i++; | |
1298 goto test_length; | |
1299 } | |
1300 | |
1301 i += 1 + buf[i]; | |
1302 } | |
1303 | |
1304 goto short_response; | |
1305 | |
1306 test_length: | |
1307 | |
1308 if (i - start < 2) { | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1309 err = "invalid name in DNS response"; |
1649 | 1310 goto invalid; |
1311 } | |
1312 | |
1313 found: | |
1314 | |
1315 if (i + sizeof(ngx_resolver_an_t) >= last) { | |
1316 goto short_response; | |
1317 } | |
1318 | |
1319 an = (ngx_resolver_an_t *) &buf[i]; | |
1320 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1321 type = (an->type_hi << 8) + an->type_lo; |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1322 class = (an->class_hi << 8) + an->class_lo; |
1649 | 1323 len = (an->len_hi << 8) + an->len_lo; |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1324 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16) |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1325 + (an->ttl[2] << 8) + (an->ttl[3]); |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1326 |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1327 if (class != 1) { |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1328 ngx_log_error(r->log_level, r->log, 0, |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1329 "unexpected RR class %ui", class); |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1330 goto failed; |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1331 } |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1332 |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1333 if (ttl < 0) { |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1334 ttl = 0; |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1335 } |
1649 | 1336 |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1337 i += sizeof(ngx_resolver_an_t); |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1338 |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1339 switch (type) { |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1340 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1341 case NGX_RESOLVE_A: |
1649 | 1342 |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1343 if (len != 4) { |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1344 err = "invalid A record in DNS response"; |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1345 goto invalid; |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1346 } |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1347 |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1348 if (i + 4 > last) { |
1649 | 1349 goto short_response; |
1350 } | |
1351 | |
1352 naddrs++; | |
1353 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1354 break; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1355 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1356 case NGX_RESOLVE_CNAME: |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1357 |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1358 cname = &buf[i]; |
1965 | 1359 |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1360 break; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1361 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1362 case NGX_RESOLVE_DNAME: |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1363 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1364 break; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1365 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1366 default: |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1367 |
1966 | 1368 ngx_log_error(r->log_level, r->log, 0, |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1369 "unexpected RR type %ui", type); |
1649 | 1370 } |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1371 |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1372 i += len; |
1649 | 1373 } |
1374 | |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1375 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1376 "resolver naddrs:%ui cname:%p ttl:%d", |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1377 naddrs, cname, ttl); |
1649 | 1378 |
1379 if (naddrs) { | |
1380 | |
1381 if (naddrs == 1) { | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1382 addr = &rn->u.addr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1383 rn->naddrs = 1; |
1649 | 1384 |
1385 } else { | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1386 addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t)); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1387 if (addr == NULL) { |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1388 goto failed; |
1649 | 1389 } |
1390 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1391 rn->u.addrs = addr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1392 rn->naddrs = (u_short) naddrs; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1393 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1394 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1395 n = 0; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1396 i = ans; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1397 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1398 for (a = 0; a < nan; a++) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1399 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1400 for ( ;; ) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1401 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1402 if (buf[i] & 0xc0) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1403 i += 2; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1404 break; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1405 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1406 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1407 if (buf[i] == 0) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1408 i++; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1409 break; |
1649 | 1410 } |
1411 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1412 i += 1 + buf[i]; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1413 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1414 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1415 an = (ngx_resolver_an_t *) &buf[i]; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1416 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1417 type = (an->type_hi << 8) + an->type_lo; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1418 len = (an->len_hi << 8) + an->len_lo; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1419 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1420 i += sizeof(ngx_resolver_an_t); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1421 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1422 if (type == NGX_RESOLVE_A) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1423 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1424 addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16) |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1425 + (buf[i + 2] << 8) + (buf[i + 3])); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1426 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1427 if (++n == naddrs) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1428 break; |
1649 | 1429 } |
1430 } | |
1431 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1432 i += len; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1433 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1434 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1435 if (naddrs == 1) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1436 addrs = NULL; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1437 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1438 } else { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1439 addrs = ngx_resolver_export(r, rn->u.addrs, naddrs, 0); |
1649 | 1440 if (addrs == NULL) { |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1441 goto failed; |
1649 | 1442 } |
1443 } | |
1444 | |
1445 ngx_queue_remove(&rn->queue); | |
1446 | |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1447 rn->valid = ngx_time() + (r->valid ? r->valid : ttl); |
1649 | 1448 rn->expire = ngx_time() + r->expire; |
1449 | |
1450 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); | |
1451 | |
1452 next = rn->waiting; | |
1453 rn->waiting = NULL; | |
1454 | |
1455 /* unlock name mutex */ | |
1456 | |
1457 while (next) { | |
5474
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1458 ctx = next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1459 ctx->state = NGX_OK; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1460 ctx->naddrs = naddrs; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1461 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1462 if (addrs == NULL) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1463 ctx->addrs = &ctx->addr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1464 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1465 ctx->addr.socklen = sizeof(struct sockaddr_in); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1466 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in)); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1467 ctx->sin.sin_family = AF_INET; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1468 ctx->sin.sin_addr.s_addr = rn->u.addr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1469 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1470 } else { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1471 ctx->addrs = addrs; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1472 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1473 |
5474
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1474 next = ctx->next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1475 |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1476 ctx->handler(ctx); |
1649 | 1477 } |
1478 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1479 if (addrs != NULL) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1480 ngx_resolver_free(r, addrs->sockaddr); |
1649 | 1481 ngx_resolver_free(r, addrs); |
1482 } | |
1483 | |
4619
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
1484 ngx_resolver_free(r, rn->query); |
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
1485 rn->query = NULL; |
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
1486 |
1649 | 1487 return; |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1488 } |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1489 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1490 if (cname) { |
1649 | 1491 |
1492 /* CNAME only */ | |
1493 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1494 if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) { |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1495 goto failed; |
1649 | 1496 } |
1497 | |
1498 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, | |
1499 "resolver cname:\"%V\"", &name); | |
1500 | |
1741
0829024c924d
fix segfault if response will have CNAME only
Igor Sysoev <igor@sysoev.ru>
parents:
1689
diff
changeset
|
1501 ngx_queue_remove(&rn->queue); |
0829024c924d
fix segfault if response will have CNAME only
Igor Sysoev <igor@sysoev.ru>
parents:
1689
diff
changeset
|
1502 |
1649 | 1503 rn->cnlen = (u_short) name.len; |
1504 rn->u.cname = name.data; | |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1505 |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1506 rn->valid = ngx_time() + (r->valid ? r->valid : ttl); |
1649 | 1507 rn->expire = ngx_time() + r->expire; |
1508 | |
1509 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); | |
1510 | |
1511 ctx = rn->waiting; | |
1512 rn->waiting = NULL; | |
1513 | |
1514 if (ctx) { | |
1515 ctx->name = name; | |
1516 | |
1517 (void) ngx_resolve_name_locked(r, ctx); | |
1518 } | |
1519 | |
4619
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
1520 ngx_resolver_free(r, rn->query); |
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
1521 rn->query = NULL; |
3171ec7d0d05
Resolver: protection from duplicate responses.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4610
diff
changeset
|
1522 |
5471
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1523 /* unlock name mutex */ |
9c96782d9d05
Resolver: fixes in A processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5470
diff
changeset
|
1524 |
1649 | 1525 return; |
1526 } | |
1527 | |
1528 ngx_log_error(r->log_level, r->log, 0, | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1529 "no A or CNAME types in DNS response"); |
1649 | 1530 return; |
1531 | |
1532 short_response: | |
1533 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1534 err = "short DNS response"; |
1649 | 1535 |
1536 invalid: | |
1537 | |
1538 /* unlock name mutex */ | |
1539 | |
1540 ngx_log_error(r->log_level, r->log, 0, err); | |
1541 | |
1542 return; | |
1543 | |
1544 failed: | |
1545 | |
1546 /* unlock name mutex */ | |
1547 | |
1548 return; | |
1549 } | |
1550 | |
1551 | |
1552 static void | |
1553 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, | |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1554 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan) |
1649 | 1555 { |
1556 char *err; | |
1557 size_t len; | |
1558 in_addr_t addr; | |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1559 int32_t ttl; |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1560 ngx_int_t octet; |
1649 | 1561 ngx_str_t name; |
5472
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1562 ngx_uint_t i, mask, qident, class; |
1649 | 1563 ngx_resolver_an_t *an; |
1564 ngx_resolver_ctx_t *ctx, *next; | |
1565 ngx_resolver_node_t *rn; | |
1566 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1567 if (ngx_resolver_copy(r, NULL, buf, |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1568 buf + sizeof(ngx_resolver_hdr_t), buf + n) |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1569 != NGX_OK) |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1570 { |
5472
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1571 return; |
1649 | 1572 } |
1573 | |
1574 addr = 0; | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1575 i = sizeof(ngx_resolver_hdr_t); |
1649 | 1576 |
1577 for (mask = 0; mask < 32; mask += 8) { | |
1578 len = buf[i++]; | |
1579 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1580 octet = ngx_atoi(&buf[i], len); |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1581 if (octet == NGX_ERROR || octet > 255) { |
1649 | 1582 goto invalid_in_addr_arpa; |
1583 } | |
1584 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1585 addr += octet << mask; |
1649 | 1586 i += len; |
1587 } | |
1588 | |
1589 if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") != 0) { | |
1590 goto invalid_in_addr_arpa; | |
1591 } | |
1592 | |
1593 /* lock addr mutex */ | |
1594 | |
1595 rn = ngx_resolver_lookup_addr(r, addr); | |
1596 | |
1597 if (rn == NULL || rn->query == NULL) { | |
1598 ngx_log_error(r->log_level, r->log, 0, | |
1599 "unexpected response for %ud.%ud.%ud.%ud", | |
1600 (addr >> 24) & 0xff, (addr >> 16) & 0xff, | |
1601 (addr >> 8) & 0xff, addr & 0xff); | |
1602 goto failed; | |
1603 } | |
1604 | |
1605 qident = (rn->query[0] << 8) + rn->query[1]; | |
1606 | |
1607 if (ident != qident) { | |
1608 ngx_log_error(r->log_level, r->log, 0, | |
1967
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1609 "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui", |
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1610 ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff, |
4a4b15c9c474
use correct ngx_sprintf() formats
Igor Sysoev <igor@sysoev.ru>
parents:
1966
diff
changeset
|
1611 (addr >> 8) & 0xff, addr & 0xff, qident); |
1649 | 1612 goto failed; |
1613 } | |
1614 | |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1615 if (code == 0 && nan == 0) { |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1616 code = NGX_RESOLVE_NXDOMAIN; |
1742
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1617 } |
268b81386fe4
no answers in DNS response should be NXDOMAIN
Igor Sysoev <igor@sysoev.ru>
parents:
1741
diff
changeset
|
1618 |
1649 | 1619 if (code) { |
1620 next = rn->waiting; | |
1621 rn->waiting = NULL; | |
1622 | |
1623 ngx_queue_remove(&rn->queue); | |
1624 | |
1625 ngx_rbtree_delete(&r->addr_rbtree, &rn->node); | |
1626 | |
1627 ngx_resolver_free_node(r, rn); | |
1628 | |
1629 /* unlock addr mutex */ | |
1630 | |
1631 while (next) { | |
5474
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1632 ctx = next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1633 ctx->state = code; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1634 next = ctx->next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1635 |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1636 ctx->handler(ctx); |
1649 | 1637 } |
1638 | |
1639 return; | |
1640 } | |
1641 | |
1642 i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t); | |
1643 | |
5472
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1644 if (i + 2 + sizeof(ngx_resolver_an_t) >= n) { |
1649 | 1645 goto short_response; |
1646 } | |
1647 | |
1648 /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */ | |
1649 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1650 if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) { |
1649 | 1651 err = "invalid in-addr.arpa name in DNS response"; |
1652 goto invalid; | |
1653 } | |
1654 | |
1655 an = (ngx_resolver_an_t *) &buf[i + 2]; | |
1656 | |
5472
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1657 class = (an->class_hi << 8) + an->class_lo; |
1649 | 1658 len = (an->len_hi << 8) + an->len_lo; |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1659 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16) |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1660 + (an->ttl[2] << 8) + (an->ttl[3]); |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1661 |
5472
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1662 if (class != 1) { |
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1663 ngx_log_error(r->log_level, r->log, 0, |
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1664 "unexpected RR class %ui", class); |
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1665 goto failed; |
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1666 } |
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1667 |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1668 if (ttl < 0) { |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1669 ttl = 0; |
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1670 } |
1649 | 1671 |
1672 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, | |
3902
159b58f9c0bd
fix building by gcc 4.6 without --with-debug
Igor Sysoev <igor@sysoev.ru>
parents:
3763
diff
changeset
|
1673 "resolver qt:%ui cl:%ui len:%uz", |
159b58f9c0bd
fix building by gcc 4.6 without --with-debug
Igor Sysoev <igor@sysoev.ru>
parents:
3763
diff
changeset
|
1674 (an->type_hi << 8) + an->type_lo, |
5472
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1675 class, len); |
1649 | 1676 |
1677 i += 2 + sizeof(ngx_resolver_an_t); | |
1678 | |
5469
b2fc466a11a7
Resolver: removed unnecessary casts.
Ruslan Ermilov <ru@nginx.com>
parents:
5468
diff
changeset
|
1679 if (i + len > n) { |
1649 | 1680 goto short_response; |
1681 } | |
1682 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1683 if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) { |
5472
ab493c60d9ff
Resolver: fixes in PTR processing.
Ruslan Ermilov <ru@nginx.com>
parents:
5471
diff
changeset
|
1684 goto failed; |
1649 | 1685 } |
1686 | |
1687 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name); | |
1688 | |
2486
8de5dc3e7001
use length of uncompressed name
Igor Sysoev <igor@sysoev.ru>
parents:
2484
diff
changeset
|
1689 if (name.len != (size_t) rn->nlen |
8de5dc3e7001
use length of uncompressed name
Igor Sysoev <igor@sysoev.ru>
parents:
2484
diff
changeset
|
1690 || ngx_strncmp(name.data, rn->name, name.len) != 0) |
1649 | 1691 { |
2482
30ec8c5ac75b
fix reverse resolving cache: it stored zero length names
Igor Sysoev <igor@sysoev.ru>
parents:
2314
diff
changeset
|
1692 if (rn->nlen) { |
30ec8c5ac75b
fix reverse resolving cache: it stored zero length names
Igor Sysoev <igor@sysoev.ru>
parents:
2314
diff
changeset
|
1693 ngx_resolver_free(r, rn->name); |
30ec8c5ac75b
fix reverse resolving cache: it stored zero length names
Igor Sysoev <igor@sysoev.ru>
parents:
2314
diff
changeset
|
1694 } |
30ec8c5ac75b
fix reverse resolving cache: it stored zero length names
Igor Sysoev <igor@sysoev.ru>
parents:
2314
diff
changeset
|
1695 |
2490
1c87647b7ca5
fix building by msvc, introduced in r2487
Igor Sysoev <igor@sysoev.ru>
parents:
2487
diff
changeset
|
1696 rn->nlen = (u_short) name.len; |
1649 | 1697 rn->name = name.data; |
1698 | |
2486
8de5dc3e7001
use length of uncompressed name
Igor Sysoev <igor@sysoev.ru>
parents:
2484
diff
changeset
|
1699 name.data = ngx_resolver_dup(r, rn->name, name.len); |
1649 | 1700 if (name.data == NULL) { |
1701 goto failed; | |
1702 } | |
1703 } | |
1704 | |
1705 ngx_queue_remove(&rn->queue); | |
1706 | |
4295
05031fce7ce8
Now nginx uses TTL of a DNS response when calculating cache validity.
Ruslan Ermilov <ru@nginx.com>
parents:
4267
diff
changeset
|
1707 rn->valid = ngx_time() + (r->valid ? r->valid : ttl); |
1649 | 1708 rn->expire = ngx_time() + r->expire; |
1709 | |
1710 ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue); | |
1711 | |
1712 next = rn->waiting; | |
1713 rn->waiting = NULL; | |
1714 | |
1715 /* unlock addr mutex */ | |
1716 | |
1717 while (next) { | |
5474
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1718 ctx = next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1719 ctx->state = NGX_OK; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1720 ctx->name = name; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1721 next = ctx->next; |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1722 |
b43b02bb54db
Resolver: fixed indentation.
Ruslan Ermilov <ru@nginx.com>
parents:
5472
diff
changeset
|
1723 ctx->handler(ctx); |
1649 | 1724 } |
1725 | |
1726 ngx_resolver_free(r, name.data); | |
1727 | |
1728 return; | |
1729 | |
1730 invalid_in_addr_arpa: | |
1731 | |
1732 ngx_log_error(r->log_level, r->log, 0, | |
1733 "invalid in-addr.arpa name in DNS response"); | |
1734 return; | |
1735 | |
1736 short_response: | |
1737 | |
1738 err = "short DNS response"; | |
1739 | |
1740 invalid: | |
1741 | |
1742 /* unlock addr mutex */ | |
1743 | |
1744 ngx_log_error(r->log_level, r->log, 0, err); | |
1745 | |
1746 return; | |
1747 | |
1748 failed: | |
1749 | |
1750 /* unlock addr mutex */ | |
1751 | |
1752 return; | |
1753 } | |
1754 | |
1755 | |
1756 static ngx_resolver_node_t * | |
1757 ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash) | |
1758 { | |
1759 ngx_int_t rc; | |
1760 ngx_rbtree_node_t *node, *sentinel; | |
1761 ngx_resolver_node_t *rn; | |
1762 | |
1763 node = r->name_rbtree.root; | |
1764 sentinel = r->name_rbtree.sentinel; | |
1765 | |
1766 while (node != sentinel) { | |
1767 | |
1768 if (hash < node->key) { | |
1769 node = node->left; | |
1770 continue; | |
1771 } | |
1772 | |
1773 if (hash > node->key) { | |
1774 node = node->right; | |
1775 continue; | |
1776 } | |
1777 | |
1778 /* hash == node->key */ | |
1779 | |
4497
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1780 rn = (ngx_resolver_node_t *) node; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1781 |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1782 rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen); |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1783 |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1784 if (rc == 0) { |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1785 return rn; |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1786 } |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1787 |
95ab6658654a
Fix of rbtree lookup on hash collisions.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4496
diff
changeset
|
1788 node = (rc < 0) ? node->left : node->right; |
1649 | 1789 } |
1790 | |
1791 /* not found */ | |
1792 | |
1793 return NULL; | |
1794 } | |
1795 | |
1796 | |
1797 static ngx_resolver_node_t * | |
1798 ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr) | |
1799 { | |
1800 ngx_rbtree_node_t *node, *sentinel; | |
1801 | |
1802 node = r->addr_rbtree.root; | |
1803 sentinel = r->addr_rbtree.sentinel; | |
1804 | |
1805 while (node != sentinel) { | |
1806 | |
1807 if (addr < node->key) { | |
1808 node = node->left; | |
1809 continue; | |
1810 } | |
1811 | |
1812 if (addr > node->key) { | |
1813 node = node->right; | |
1814 continue; | |
1815 } | |
1816 | |
1817 /* addr == node->key */ | |
1818 | |
1819 return (ngx_resolver_node_t *) node; | |
1820 } | |
1821 | |
1822 /* not found */ | |
1823 | |
1824 return NULL; | |
1825 } | |
1826 | |
1827 | |
1828 static void | |
1829 ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp, | |
1830 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) | |
1831 { | |
1832 ngx_rbtree_node_t **p; | |
1833 ngx_resolver_node_t *rn, *rn_temp; | |
1834 | |
1835 for ( ;; ) { | |
1836 | |
1837 if (node->key < temp->key) { | |
1838 | |
1839 p = &temp->left; | |
1840 | |
1841 } else if (node->key > temp->key) { | |
1842 | |
1843 p = &temp->right; | |
1844 | |
1845 } else { /* node->key == temp->key */ | |
1846 | |
1847 rn = (ngx_resolver_node_t *) node; | |
1848 rn_temp = (ngx_resolver_node_t *) temp; | |
1849 | |
3143
ab6258e18099
fix resolver cache rbtree comparison
Igor Sysoev <igor@sysoev.ru>
parents:
3139
diff
changeset
|
1850 p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen) |
ab6258e18099
fix resolver cache rbtree comparison
Igor Sysoev <igor@sysoev.ru>
parents:
3139
diff
changeset
|
1851 < 0) ? &temp->left : &temp->right; |
1649 | 1852 } |
1853 | |
1854 if (*p == sentinel) { | |
1855 break; | |
1856 } | |
1857 | |
1858 temp = *p; | |
1859 } | |
1860 | |
1861 *p = node; | |
1862 node->parent = temp; | |
1863 node->left = sentinel; | |
1864 node->right = sentinel; | |
1865 ngx_rbt_red(node); | |
1866 } | |
1867 | |
1868 | |
1869 static ngx_int_t | |
1870 ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) | |
1871 { | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1872 u_char *p, *s; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1873 size_t len, nlen; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1874 ngx_uint_t ident; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1875 ngx_resolver_qs_t *qs; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1876 ngx_resolver_hdr_t *query; |
1649 | 1877 |
3306
61bdaac6c668
fix resolving an empty name (".")
Igor Sysoev <igor@sysoev.ru>
parents:
3299
diff
changeset
|
1878 nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1; |
61bdaac6c668
fix resolving an empty name (".")
Igor Sysoev <igor@sysoev.ru>
parents:
3299
diff
changeset
|
1879 |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1880 len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t); |
1649 | 1881 |
3307
34e99a97fbd6
use ngx_resolver_alloc() instead of ngx_resolver_calloc()
Igor Sysoev <igor@sysoev.ru>
parents:
3306
diff
changeset
|
1882 p = ngx_resolver_alloc(ctx->resolver, len); |
1649 | 1883 if (p == NULL) { |
1884 return NGX_ERROR; | |
1885 } | |
1886 | |
1887 rn->qlen = (u_short) len; | |
1888 rn->query = p; | |
1889 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1890 query = (ngx_resolver_hdr_t *) p; |
1649 | 1891 |
1892 ident = ngx_random(); | |
1893 | |
1894 ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, | |
1895 "resolve: \"%V\" %i", &ctx->name, ident & 0xffff); | |
1896 | |
1897 query->ident_hi = (u_char) ((ident >> 8) & 0xff); | |
1898 query->ident_lo = (u_char) (ident & 0xff); | |
1899 | |
1900 /* recursion query */ | |
1901 query->flags_hi = 1; query->flags_lo = 0; | |
1902 | |
1903 /* one question */ | |
1904 query->nqs_hi = 0; query->nqs_lo = 1; | |
1905 query->nan_hi = 0; query->nan_lo = 0; | |
1906 query->nns_hi = 0; query->nns_lo = 0; | |
1907 query->nar_hi = 0; query->nar_lo = 0; | |
1908 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1909 p += sizeof(ngx_resolver_hdr_t) + nlen; |
1649 | 1910 |
1911 qs = (ngx_resolver_qs_t *) p; | |
1912 | |
1913 /* query type */ | |
1914 qs->type_hi = 0; qs->type_lo = (u_char) ctx->type; | |
1915 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1916 /* IN query class */ |
1649 | 1917 qs->class_hi = 0; qs->class_lo = 1; |
1918 | |
1919 /* convert "www.example.com" to "\3www\7example\3com\0" */ | |
1920 | |
1921 len = 0; | |
1922 p--; | |
1923 *p-- = '\0'; | |
1924 | |
4610
778d2cc03e22
Fixed segmentation fault in ngx_resolver_create_name_query().
Ruslan Ermilov <ru@nginx.com>
parents:
4556
diff
changeset
|
1925 if (ctx->name.len == 0) { |
778d2cc03e22
Fixed segmentation fault in ngx_resolver_create_name_query().
Ruslan Ermilov <ru@nginx.com>
parents:
4556
diff
changeset
|
1926 return NGX_DECLINED; |
778d2cc03e22
Fixed segmentation fault in ngx_resolver_create_name_query().
Ruslan Ermilov <ru@nginx.com>
parents:
4556
diff
changeset
|
1927 } |
778d2cc03e22
Fixed segmentation fault in ngx_resolver_create_name_query().
Ruslan Ermilov <ru@nginx.com>
parents:
4556
diff
changeset
|
1928 |
1649 | 1929 for (s = ctx->name.data + ctx->name.len - 1; s >= ctx->name.data; s--) { |
1930 if (*s != '.') { | |
1931 *p = *s; | |
1932 len++; | |
1933 | |
1934 } else { | |
4556
1bddc91e78d6
Resolver: added missing sanity checking when creating name queries.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4497
diff
changeset
|
1935 if (len == 0 || len > 255) { |
1961
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
1936 return NGX_DECLINED; |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
1937 } |
99b9feacccb4
return NXDOMAIN for ".." in host name
Igor Sysoev <igor@sysoev.ru>
parents:
1960
diff
changeset
|
1938 |
1649 | 1939 *p = (u_char) len; |
1940 len = 0; | |
1941 } | |
1942 | |
1943 p--; | |
1944 } | |
1945 | |
4556
1bddc91e78d6
Resolver: added missing sanity checking when creating name queries.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4497
diff
changeset
|
1946 if (len == 0 || len > 255) { |
1bddc91e78d6
Resolver: added missing sanity checking when creating name queries.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4497
diff
changeset
|
1947 return NGX_DECLINED; |
1bddc91e78d6
Resolver: added missing sanity checking when creating name queries.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4497
diff
changeset
|
1948 } |
1bddc91e78d6
Resolver: added missing sanity checking when creating name queries.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4497
diff
changeset
|
1949 |
1649 | 1950 *p = (u_char) len; |
1951 | |
1952 return NGX_OK; | |
1953 } | |
1954 | |
1955 | |
1956 /* AF_INET only */ | |
1957 | |
1958 static ngx_int_t | |
1959 ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) | |
1960 { | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1961 u_char *p, *d; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1962 size_t len; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1963 in_addr_t addr; |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1964 ngx_int_t n; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1965 ngx_uint_t ident; |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1966 ngx_resolver_hdr_t *query; |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1967 struct sockaddr_in *sin; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1968 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1969 if (ctx->addr.sockaddr->sa_family != AF_INET) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1970 return NGX_ERROR; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
1971 } |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1972 |
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1973 len = sizeof(ngx_resolver_hdr_t) |
1649 | 1974 + sizeof(".255.255.255.255.in-addr.arpa.") - 1 |
1975 + sizeof(ngx_resolver_qs_t); | |
1976 | |
3307
34e99a97fbd6
use ngx_resolver_alloc() instead of ngx_resolver_calloc()
Igor Sysoev <igor@sysoev.ru>
parents:
3306
diff
changeset
|
1977 p = ngx_resolver_alloc(ctx->resolver, len); |
1649 | 1978 if (p == NULL) { |
1979 return NGX_ERROR; | |
1980 } | |
1981 | |
1982 rn->query = p; | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1983 query = (ngx_resolver_hdr_t *) p; |
1649 | 1984 |
1985 ident = ngx_random(); | |
1986 | |
1987 query->ident_hi = (u_char) ((ident >> 8) & 0xff); | |
1988 query->ident_lo = (u_char) (ident & 0xff); | |
1989 | |
1990 /* recursion query */ | |
1991 query->flags_hi = 1; query->flags_lo = 0; | |
1992 | |
1993 /* one question */ | |
1994 query->nqs_hi = 0; query->nqs_lo = 1; | |
1995 query->nan_hi = 0; query->nan_lo = 0; | |
1996 query->nns_hi = 0; query->nns_lo = 0; | |
1997 query->nar_hi = 0; query->nar_lo = 0; | |
1998 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
1999 p += sizeof(ngx_resolver_hdr_t); |
1649 | 2000 |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2001 sin = (struct sockaddr_in *) ctx->addr.sockaddr; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2002 addr = ntohl(sin->sin_addr.s_addr); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2003 |
3642 | 2004 for (n = 0; n < 32; n += 8) { |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2005 d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff); |
1649 | 2006 *p = (u_char) (d - &p[1]); |
2007 p = d; | |
2008 } | |
2009 | |
5468
5c410d6ca7dd
Resolver: improved code readability.
Ruslan Ermilov <ru@nginx.com>
parents:
5360
diff
changeset
|
2010 /* query type "PTR", IN query class */ |
1649 | 2011 ngx_memcpy(p, "\7in-addr\4arpa\0\0\14\0\1", 18); |
2012 | |
2013 rn->qlen = (u_short) | |
2014 (p + sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t) | |
2015 - rn->query); | |
2016 | |
2017 return NGX_OK; | |
2018 } | |
2019 | |
2020 | |
2021 static ngx_int_t | |
2022 ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src, | |
2023 u_char *last) | |
2024 { | |
2025 char *err; | |
2026 u_char *p, *dst; | |
2027 ssize_t len; | |
2028 ngx_uint_t i, n; | |
2029 | |
2030 p = src; | |
2031 len = -1; | |
2032 | |
2033 /* | |
2034 * compression pointers allow to create endless loop, so we set limit; | |
2035 * 128 pointers should be enough to store 255-byte name | |
2036 */ | |
2037 | |
2038 for (i = 0; i < 128; i++) { | |
2039 n = *p++; | |
2040 | |
2041 if (n == 0) { | |
2042 goto done; | |
2043 } | |
2044 | |
2045 if (n & 0xc0) { | |
2314
52987a023486
fix compression pointer for big (>255) DNS responses
Igor Sysoev <igor@sysoev.ru>
parents:
2282
diff
changeset
|
2046 n = ((n & 0x3f) << 8) + *p; |
1649 | 2047 p = &buf[n]; |
2048 | |
2049 } else { | |
2050 len += 1 + n; | |
2051 p = &p[n]; | |
2052 } | |
2053 | |
2054 if (p >= last) { | |
2055 err = "name is out of response"; | |
2056 goto invalid; | |
2057 } | |
2058 } | |
2059 | |
2060 err = "compression pointers loop"; | |
2061 | |
2062 invalid: | |
2063 | |
2064 ngx_log_error(r->log_level, r->log, 0, err); | |
2065 | |
2066 return NGX_ERROR; | |
2067 | |
2068 done: | |
2069 | |
2070 if (name == NULL) { | |
583 | 2071 return NGX_OK; |
2072 } | |
2073 | |
3298
847ab5a32307
fix "PTR ." case in address resolver
Igor Sysoev <igor@sysoev.ru>
parents:
3297
diff
changeset
|
2074 if (len == -1) { |
847ab5a32307
fix "PTR ." case in address resolver
Igor Sysoev <igor@sysoev.ru>
parents:
3297
diff
changeset
|
2075 name->len = 0; |
847ab5a32307
fix "PTR ." case in address resolver
Igor Sysoev <igor@sysoev.ru>
parents:
3297
diff
changeset
|
2076 name->data = NULL; |
847ab5a32307
fix "PTR ." case in address resolver
Igor Sysoev <igor@sysoev.ru>
parents:
3297
diff
changeset
|
2077 return NGX_OK; |
847ab5a32307
fix "PTR ." case in address resolver
Igor Sysoev <igor@sysoev.ru>
parents:
3297
diff
changeset
|
2078 } |
847ab5a32307
fix "PTR ." case in address resolver
Igor Sysoev <igor@sysoev.ru>
parents:
3297
diff
changeset
|
2079 |
1649 | 2080 dst = ngx_resolver_alloc(r, len); |
2081 if (dst == NULL) { | |
2082 return NGX_ERROR; | |
2083 } | |
2084 | |
2085 name->data = dst; | |
2086 | |
2087 n = *src++; | |
2088 | |
2089 for ( ;; ) { | |
4267
768212ca0745
Fixed compression pointer processing in DNS response greater than 255 bytes.
Igor Sysoev <igor@sysoev.ru>
parents:
4225
diff
changeset
|
2090 if (n & 0xc0) { |
768212ca0745
Fixed compression pointer processing in DNS response greater than 255 bytes.
Igor Sysoev <igor@sysoev.ru>
parents:
4225
diff
changeset
|
2091 n = ((n & 0x3f) << 8) + *src; |
768212ca0745
Fixed compression pointer processing in DNS response greater than 255 bytes.
Igor Sysoev <igor@sysoev.ru>
parents:
4225
diff
changeset
|
2092 src = &buf[n]; |
768212ca0745
Fixed compression pointer processing in DNS response greater than 255 bytes.
Igor Sysoev <igor@sysoev.ru>
parents:
4225
diff
changeset
|
2093 |
768212ca0745
Fixed compression pointer processing in DNS response greater than 255 bytes.
Igor Sysoev <igor@sysoev.ru>
parents:
4225
diff
changeset
|
2094 n = *src++; |
768212ca0745
Fixed compression pointer processing in DNS response greater than 255 bytes.
Igor Sysoev <igor@sysoev.ru>
parents:
4225
diff
changeset
|
2095 |
768212ca0745
Fixed compression pointer processing in DNS response greater than 255 bytes.
Igor Sysoev <igor@sysoev.ru>
parents:
4225
diff
changeset
|
2096 } else { |
1649 | 2097 ngx_memcpy(dst, src, n); |
2098 dst += n; | |
2099 src += n; | |
2100 | |
2101 n = *src++; | |
2102 | |
2103 if (n != 0) { | |
2104 *dst++ = '.'; | |
2105 } | |
2106 } | |
2107 | |
2108 if (n == 0) { | |
2109 name->len = dst - name->data; | |
2110 return NGX_OK; | |
2111 } | |
2112 } | |
2113 } | |
2114 | |
2115 | |
2116 static void | |
2117 ngx_resolver_timeout_handler(ngx_event_t *ev) | |
2118 { | |
2119 ngx_resolver_ctx_t *ctx; | |
2120 | |
2121 ctx = ev->data; | |
2122 | |
2123 ctx->state = NGX_RESOLVE_TIMEDOUT; | |
2124 | |
2125 ctx->handler(ctx); | |
2126 } | |
2127 | |
2128 | |
2129 static void | |
2130 ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn) | |
2131 { | |
2132 /* lock alloc mutex */ | |
2133 | |
2134 if (rn->query) { | |
2135 ngx_resolver_free_locked(r, rn->query); | |
2136 } | |
2137 | |
2138 if (rn->name) { | |
2139 ngx_resolver_free_locked(r, rn->name); | |
2140 } | |
2141 | |
2142 if (rn->cnlen) { | |
2143 ngx_resolver_free_locked(r, rn->u.cname); | |
2144 } | |
2145 | |
2146 if (rn->naddrs > 1) { | |
2147 ngx_resolver_free_locked(r, rn->u.addrs); | |
2148 } | |
2149 | |
2150 ngx_resolver_free_locked(r, rn); | |
2151 | |
2152 /* unlock alloc mutex */ | |
2153 } | |
2154 | |
2155 | |
2156 static void * | |
2157 ngx_resolver_alloc(ngx_resolver_t *r, size_t size) | |
2158 { | |
2159 u_char *p; | |
2160 | |
2161 /* lock alloc mutex */ | |
2162 | |
2163 p = ngx_alloc(size, r->log); | |
2164 | |
2165 /* unlock alloc mutex */ | |
2166 | |
2167 return p; | |
2168 } | |
2169 | |
2170 | |
1903 | 2171 static void * |
1649 | 2172 ngx_resolver_calloc(ngx_resolver_t *r, size_t size) |
2173 { | |
2174 u_char *p; | |
2175 | |
2176 p = ngx_resolver_alloc(r, size); | |
2177 | |
2178 if (p) { | |
2179 ngx_memzero(p, size); | |
2180 } | |
2181 | |
2182 return p; | |
2183 } | |
2184 | |
2185 | |
2186 static void | |
2187 ngx_resolver_free(ngx_resolver_t *r, void *p) | |
2188 { | |
2189 /* lock alloc mutex */ | |
2190 | |
2191 ngx_free(p); | |
2192 | |
2193 /* unlock alloc mutex */ | |
2194 } | |
2195 | |
2196 | |
2197 static void | |
2198 ngx_resolver_free_locked(ngx_resolver_t *r, void *p) | |
2199 { | |
2200 ngx_free(p); | |
2201 } | |
2202 | |
2203 | |
2204 static void * | |
2205 ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size) | |
2206 { | |
2207 void *dst; | |
2208 | |
2209 dst = ngx_resolver_alloc(r, size); | |
2210 | |
2211 if (dst == NULL) { | |
2212 return dst; | |
2213 } | |
2214 | |
2215 ngx_memcpy(dst, src, size); | |
2216 | |
2217 return dst; | |
2218 } | |
2219 | |
2220 | |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2221 static ngx_addr_t * |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2222 ngx_resolver_export(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n, |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2223 ngx_uint_t rotate) |
4871
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2224 { |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2225 ngx_addr_t *dst; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2226 ngx_uint_t i, j; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2227 struct sockaddr_in *sin; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2228 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2229 dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t)); |
4892
063ac68d89dc
Resolver: added missing memory allocation error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4871
diff
changeset
|
2230 if (dst == NULL) { |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2231 return NULL; |
4892
063ac68d89dc
Resolver: added missing memory allocation error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4871
diff
changeset
|
2232 } |
063ac68d89dc
Resolver: added missing memory allocation error handling.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4871
diff
changeset
|
2233 |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2234 sin = ngx_resolver_calloc(r, n * sizeof(struct sockaddr_in)); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2235 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2236 if (sin == NULL) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2237 ngx_resolver_free(r, dst); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2238 return NULL; |
4871
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2239 } |
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2240 |
5475
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2241 j = rotate ? ngx_random() % n : 0; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2242 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2243 for (i = 0; i < n; i++) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2244 dst[i].sockaddr = (struct sockaddr *) &sin[i]; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2245 dst[i].socklen = sizeof(struct sockaddr_in); |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2246 sin[i].sin_family = AF_INET; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2247 sin[i].sin_addr.s_addr = src[j++]; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2248 |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2249 if (j == n) { |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2250 j = 0; |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2251 } |
07dd5bd222ac
Changed resolver API to use ngx_addr_t.
Ruslan Ermilov <ru@nginx.com>
parents:
5474
diff
changeset
|
2252 } |
4871
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2253 |
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2254 return dst; |
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2255 } |
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2256 |
c85cefbdaafe
Resolver: cached addresses are returned with random rotation now.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4784
diff
changeset
|
2257 |
1649 | 2258 char * |
2259 ngx_resolver_strerror(ngx_int_t err) | |
2260 { | |
2261 static char *errors[] = { | |
2262 "Format error", /* FORMERR */ | |
2263 "Server failure", /* SERVFAIL */ | |
2264 "Host not found", /* NXDOMAIN */ | |
2265 "Unimplemented", /* NOTIMP */ | |
2266 "Operation refused" /* REFUSED */ | |
2267 }; | |
2268 | |
2269 if (err > 0 && err < 6) { | |
2270 return errors[err - 1]; | |
2271 } | |
2272 | |
2273 if (err == NGX_RESOLVE_TIMEDOUT) { | |
2274 return "Operation timed out"; | |
2275 } | |
2276 | |
2277 return "Unknown error"; | |
2278 } | |
2279 | |
2280 | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2281 static u_char * |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2282 ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len) |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2283 { |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2284 u_char *p; |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2285 ngx_udp_connection_t *uc; |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2286 |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2287 p = buf; |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2288 |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2289 if (log->action) { |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2290 p = ngx_snprintf(buf, len, " while %s", log->action); |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2291 len -= p - buf; |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2292 } |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2293 |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2294 uc = log->data; |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2295 |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2296 if (uc) { |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2297 p = ngx_snprintf(p, len, ", resolver: %V", &uc->server); |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2298 } |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2299 |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2300 return p; |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2301 } |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2302 |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2303 |
1649 | 2304 ngx_int_t |
2305 ngx_udp_connect(ngx_udp_connection_t *uc) | |
2306 { | |
2307 int rc; | |
2308 ngx_int_t event; | |
2309 ngx_event_t *rev, *wev; | |
2310 ngx_socket_t s; | |
2311 ngx_connection_t *c; | |
2312 | |
4671
af9342747669
Support for IPv6 literals and an optional port in resolver.
Ruslan Ermilov <ru@nginx.com>
parents:
4653
diff
changeset
|
2313 s = ngx_socket(uc->sockaddr->sa_family, SOCK_DGRAM, 0); |
583 | 2314 |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2315 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s); |
583 | 2316 |
5360
3d2d3e1cf427
Win32: MinGW GCC compatibility.
Maxim Dounin <mdounin@mdounin.ru>
parents:
4892
diff
changeset
|
2317 if (s == (ngx_socket_t) -1) { |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2318 ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, |
583 | 2319 ngx_socket_n " failed"); |
2320 return NGX_ERROR; | |
2321 } | |
2322 | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2323 c = ngx_get_connection(s, &uc->log); |
583 | 2324 |
2325 if (c == NULL) { | |
2326 if (ngx_close_socket(s) == -1) { | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2327 ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, |
583 | 2328 ngx_close_socket_n "failed"); |
2329 } | |
2330 | |
2331 return NGX_ERROR; | |
2332 } | |
2333 | |
1649 | 2334 if (ngx_nonblocking(s) == -1) { |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2335 ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, |
1649 | 2336 ngx_nonblocking_n " failed"); |
2337 | |
2338 ngx_free_connection(c); | |
2339 | |
2340 if (ngx_close_socket(s) == -1) { | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2341 ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno, |
1649 | 2342 ngx_close_socket_n " failed"); |
2343 } | |
2344 | |
2345 return NGX_ERROR; | |
2346 } | |
2347 | |
583 | 2348 rev = c->read; |
2349 wev = c->write; | |
2350 | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2351 rev->log = &uc->log; |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2352 wev->log = &uc->log; |
1649 | 2353 |
2354 uc->connection = c; | |
583 | 2355 |
2356 c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); | |
2357 | |
2358 #if (NGX_THREADS) | |
1649 | 2359 |
2360 /* TODO: lock event when call completion handler */ | |
2361 | |
2362 rev->lock = &c->lock; | |
2363 wev->lock = &c->lock; | |
583 | 2364 rev->own_lock = &c->lock; |
2365 wev->own_lock = &c->lock; | |
1649 | 2366 |
583 | 2367 #endif |
2368 | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2369 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0, |
1649 | 2370 "connect to %V, fd:%d #%d", &uc->server, s, c->number); |
2371 | |
2372 rc = connect(s, uc->sockaddr, uc->socklen); | |
2373 | |
2374 /* TODO: aio, iocp */ | |
583 | 2375 |
2376 if (rc == -1) { | |
3408
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2377 ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno, |
71193a456616
add context to a resolver log
Igor Sysoev <igor@sysoev.ru>
parents:
3376
diff
changeset
|
2378 "connect() failed"); |
583 | 2379 |
2380 return NGX_ERROR; | |
2381 } | |
2382 | |
1649 | 2383 /* UDP sockets are always ready to write */ |
2384 wev->ready = 1; | |
2385 | |
2386 if (ngx_add_event) { | |
2387 | |
2388 event = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ? | |
2389 /* kqueue, epoll */ NGX_CLEAR_EVENT: | |
2390 /* select, poll, /dev/poll */ NGX_LEVEL_EVENT; | |
2391 /* eventport event type has no meaning: oneshot only */ | |
2392 | |
2393 if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) { | |
2394 return NGX_ERROR; | |
2395 } | |
2396 | |
2397 } else { | |
2398 /* rtsig */ | |
2399 | |
583 | 2400 if (ngx_add_conn(c) == NGX_ERROR) { |
2401 return NGX_ERROR; | |
2402 } | |
2403 } | |
2404 | |
2405 return NGX_OK; | |
2406 } |