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