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