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