Bug Summary

File:core/ngx_resolver.c
Location:line 925, column 5
Description:Value stored to 'addr' is never read

Annotated Source Code

1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_event.h>
11
12
13#define NGX_RESOLVER_UDP_SIZE4096 4096
14
15#define NGX_RESOLVER_TCP_RSIZE(2 + 65535) (2 + 65535)
16#define NGX_RESOLVER_TCP_WSIZE8192 8192
17
18
19typedef struct {
20 u_char ident_hi;
21 u_char ident_lo;
22 u_char flags_hi;
23 u_char flags_lo;
24 u_char nqs_hi;
25 u_char nqs_lo;
26 u_char nan_hi;
27 u_char nan_lo;
28 u_char nns_hi;
29 u_char nns_lo;
30 u_char nar_hi;
31 u_char nar_lo;
32} ngx_resolver_hdr_t;
33
34
35typedef struct {
36 u_char type_hi;
37 u_char type_lo;
38 u_char class_hi;
39 u_char class_lo;
40} ngx_resolver_qs_t;
41
42
43typedef struct {
44 u_char type_hi;
45 u_char type_lo;
46 u_char class_hi;
47 u_char class_lo;
48 u_char ttl[4];
49 u_char len_hi;
50 u_char len_lo;
51} ngx_resolver_an_t;
52
53
54#define ngx_resolver_node(n)(ngx_resolver_node_t *) ((u_char *) (n) - __builtin_offsetof(
ngx_resolver_node_t, node))
\
55 (ngx_resolver_node_t *) \
56 ((u_char *) (n) - offsetof(ngx_resolver_node_t, node)__builtin_offsetof(ngx_resolver_node_t, node))
57
58
59ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec);
60ngx_int_t ngx_tcp_connect(ngx_resolver_connection_t *rec);
61
62
63static void ngx_resolver_cleanup(void *data);
64static void ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree);
65static ngx_int_t ngx_resolve_name_locked(ngx_resolver_t *r,
66 ngx_resolver_ctx_t *ctx, ngx_str_t *name);
67static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree,
68 ngx_queue_t *queue);
69static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r,
70 ngx_resolver_node_t *rn);
71static ngx_int_t ngx_resolver_send_udp_query(ngx_resolver_t *r,
72 ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
73static ngx_int_t ngx_resolver_send_tcp_query(ngx_resolver_t *r,
74 ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
75static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r,
76 ngx_resolver_node_t *rn, ngx_str_t *name);
77static ngx_int_t ngx_resolver_create_srv_query(ngx_resolver_t *r,
78 ngx_resolver_node_t *rn, ngx_str_t *name);
79static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r,
80 ngx_resolver_node_t *rn, ngx_resolver_addr_t *addr);
81static void ngx_resolver_resend_handler(ngx_event_t *ev);
82static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree,
83 ngx_queue_t *queue);
84static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r);
85static void ngx_resolver_udp_read(ngx_event_t *rev);
86static void ngx_resolver_tcp_write(ngx_event_t *wev);
87static void ngx_resolver_tcp_read(ngx_event_t *rev);
88static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
89 size_t n, ngx_uint_t tcp);
90static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
91 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
92 ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans);
93static void ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
94 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
95 ngx_uint_t trunc, ngx_uint_t ans);
96static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
97 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
98static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
99 ngx_str_t *name, uint32_t hash);
100static ngx_resolver_node_t *ngx_resolver_lookup_srv(ngx_resolver_t *r,
101 ngx_str_t *name, uint32_t hash);
102static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
103 in_addr_t addr);
104static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
105 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
106static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name,
107 u_char *buf, u_char *src, u_char *last);
108static void ngx_resolver_timeout_handler(ngx_event_t *ev);
109static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn);
110static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size);
111static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
112static void ngx_resolver_free(ngx_resolver_t *r, void *p);
113static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
114static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
115static ngx_resolver_addr_t *ngx_resolver_export(ngx_resolver_t *r,
116 ngx_resolver_node_t *rn, ngx_uint_t rotate);
117static void ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx);
118static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
119static void ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx,
120 ngx_resolver_node_t *rn);
121static void ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *ctx);
122static ngx_int_t ngx_resolver_cmp_srvs(const void *one, const void *two);
123
124#if (NGX_HAVE_INET6)
125static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
126 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
127static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
128 struct in6_addr *addr, uint32_t hash);
129#endif
130
131
132ngx_resolver_t *
133ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
134{
135 ngx_str_t s;
136 ngx_url_t u;
137 ngx_uint_t i, j;
138 ngx_resolver_t *r;
139 ngx_pool_cleanup_t *cln;
140 ngx_resolver_connection_t *rec;
141
142 cln = ngx_pool_cleanup_add(cf->pool, 0);
143 if (cln == NULL((void*)0)) {
144 return NULL((void*)0);
145 }
146
147 cln->handler = ngx_resolver_cleanup;
148
149 r = ngx_calloc(sizeof(ngx_resolver_t), cf->log);
150 if (r == NULL((void*)0)) {
151 return NULL((void*)0);
152 }
153
154 cln->data = r;
155
156 r->event = ngx_calloc(sizeof(ngx_event_t), cf->log);
157 if (r->event == NULL((void*)0)) {
158 return NULL((void*)0);
159 }
160
161 ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,((&r->name_sentinel)->color = 0); (&r->name_rbtree
)->root = &r->name_sentinel; (&r->name_rbtree
)->sentinel = &r->name_sentinel; (&r->name_rbtree
)->insert = ngx_resolver_rbtree_insert_value
162 ngx_resolver_rbtree_insert_value)((&r->name_sentinel)->color = 0); (&r->name_rbtree
)->root = &r->name_sentinel; (&r->name_rbtree
)->sentinel = &r->name_sentinel; (&r->name_rbtree
)->insert = ngx_resolver_rbtree_insert_value
;
163
164 ngx_rbtree_init(&r->srv_rbtree, &r->srv_sentinel,((&r->srv_sentinel)->color = 0); (&r->srv_rbtree
)->root = &r->srv_sentinel; (&r->srv_rbtree)
->sentinel = &r->srv_sentinel; (&r->srv_rbtree
)->insert = ngx_resolver_rbtree_insert_value
165 ngx_resolver_rbtree_insert_value)((&r->srv_sentinel)->color = 0); (&r->srv_rbtree
)->root = &r->srv_sentinel; (&r->srv_rbtree)
->sentinel = &r->srv_sentinel; (&r->srv_rbtree
)->insert = ngx_resolver_rbtree_insert_value
;
166
167 ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,((&r->addr_sentinel)->color = 0); (&r->addr_rbtree
)->root = &r->addr_sentinel; (&r->addr_rbtree
)->sentinel = &r->addr_sentinel; (&r->addr_rbtree
)->insert = ngx_rbtree_insert_value
168 ngx_rbtree_insert_value)((&r->addr_sentinel)->color = 0); (&r->addr_rbtree
)->root = &r->addr_sentinel; (&r->addr_rbtree
)->sentinel = &r->addr_sentinel; (&r->addr_rbtree
)->insert = ngx_rbtree_insert_value
;
169
170 ngx_queue_init(&r->name_resend_queue)(&r->name_resend_queue)->prev = &r->name_resend_queue
; (&r->name_resend_queue)->next = &r->name_resend_queue
;
171 ngx_queue_init(&r->srv_resend_queue)(&r->srv_resend_queue)->prev = &r->srv_resend_queue
; (&r->srv_resend_queue)->next = &r->srv_resend_queue
;
172 ngx_queue_init(&r->addr_resend_queue)(&r->addr_resend_queue)->prev = &r->addr_resend_queue
; (&r->addr_resend_queue)->next = &r->addr_resend_queue
;
173
174 ngx_queue_init(&r->name_expire_queue)(&r->name_expire_queue)->prev = &r->name_expire_queue
; (&r->name_expire_queue)->next = &r->name_expire_queue
;
175 ngx_queue_init(&r->srv_expire_queue)(&r->srv_expire_queue)->prev = &r->srv_expire_queue
; (&r->srv_expire_queue)->next = &r->srv_expire_queue
;
176 ngx_queue_init(&r->addr_expire_queue)(&r->addr_expire_queue)->prev = &r->addr_expire_queue
; (&r->addr_expire_queue)->next = &r->addr_expire_queue
;
177
178#if (NGX_HAVE_INET6)
179 r->ipv6 = 1;
180
181 ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel,((&r->addr6_sentinel)->color = 0); (&r->addr6_rbtree
)->root = &r->addr6_sentinel; (&r->addr6_rbtree
)->sentinel = &r->addr6_sentinel; (&r->addr6_rbtree
)->insert = ngx_resolver_rbtree_insert_addr6_value
182 ngx_resolver_rbtree_insert_addr6_value)((&r->addr6_sentinel)->color = 0); (&r->addr6_rbtree
)->root = &r->addr6_sentinel; (&r->addr6_rbtree
)->sentinel = &r->addr6_sentinel; (&r->addr6_rbtree
)->insert = ngx_resolver_rbtree_insert_addr6_value
;
183
184 ngx_queue_init(&r->addr6_resend_queue)(&r->addr6_resend_queue)->prev = &r->addr6_resend_queue
; (&r->addr6_resend_queue)->next = &r->addr6_resend_queue
;
185
186 ngx_queue_init(&r->addr6_expire_queue)(&r->addr6_expire_queue)->prev = &r->addr6_expire_queue
; (&r->addr6_expire_queue)->next = &r->addr6_expire_queue
;
187#endif
188
189 r->event->handler = ngx_resolver_resend_handler;
190 r->event->data = r;
191 r->event->log = &cf->cycle->new_log;
192 r->ident = -1;
193
194 r->resend_timeout = 5;
195 r->tcp_timeout = 5;
196 r->expire = 30;
197 r->valid = 0;
198
199 r->log = &cf->cycle->new_log;
200 r->log_level = NGX_LOG_ERR4;
201
202 if (n) {
203 if (ngx_array_init(&r->connections, cf->pool, n,
204 sizeof(ngx_resolver_connection_t))
205 != NGX_OK0)
206 {
207 return NULL((void*)0);
208 }
209 }
210
211 for (i = 0; i < n; i++) {
212 if (ngx_strncmp(names[i].data, "valid=", 6)(__extension__ (__builtin_constant_p (6) && ((__builtin_constant_p
((const char *) names[i].data) && strlen ((const char
*) names[i].data) < ((size_t) (6))) || (__builtin_constant_p
((const char *) "valid=") && strlen ((const char *) "valid="
) < ((size_t) (6)))) ? __extension__ ({ size_t __s1_len, __s2_len
; (__builtin_constant_p ((const char *) names[i].data) &&
__builtin_constant_p ((const char *) "valid=") && (__s1_len
= strlen ((const char *) names[i].data), __s2_len = strlen (
(const char *) "valid="), (!((size_t)(const void *)(((const char
*) names[i].data) + 1) - (size_t)(const void *)((const char *
) names[i].data) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)(((const char *) "valid=") + 1) - (size_t)(const
void *)((const char *) "valid=") == 1) || __s2_len >= 4))
? __builtin_strcmp ((const char *) names[i].data, (const char
*) "valid=") : (__builtin_constant_p ((const char *) names[i
].data) && ((size_t)(const void *)(((const char *) names
[i].data) + 1) - (size_t)(const void *)((const char *) names[
i].data) == 1) && (__s1_len = strlen ((const char *) names
[i].data), __s1_len < 4) ? (__builtin_constant_p ((const char
*) "valid=") && ((size_t)(const void *)(((const char
*) "valid=") + 1) - (size_t)(const void *)((const char *) "valid="
) == 1) ? __builtin_strcmp ((const char *) names[i].data, (const
char *) "valid=") : (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) ((const char *) "valid="
); int __result = (((const unsigned char *) (const char *) ((
const char *) names[i].data))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) ((const char *) names[i].data))[1] - __s2[
1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) names
[i].data))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
const char *) names[i].data))[3] - __s2[3]); } } __result; })
)) : (__builtin_constant_p ((const char *) "valid=") &&
((size_t)(const void *)(((const char *) "valid=") + 1) - (size_t
)(const void *)((const char *) "valid=") == 1) && (__s2_len
= strlen ((const char *) "valid="), __s2_len < 4) ? (__builtin_constant_p
((const char *) names[i].data) && ((size_t)(const void
*)(((const char *) names[i].data) + 1) - (size_t)(const void
*)((const char *) names[i].data) == 1) ? __builtin_strcmp ((
const char *) names[i].data, (const char *) "valid=") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) names[i].data); int __result = (((const
unsigned char *) (const char *) ((const char *) "valid="))[0
] - __s2[0]); if (__s2_len > 0 && __result == 0) {
__result = (((const unsigned char *) (const char *) ((const char
*) "valid="))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) "valid="))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "valid="))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp ((const char *) names[i].data, (const
char *) "valid=")))); }) : strncmp ((const char *) names[i].
data, (const char *) "valid=", 6)))
== 0) {
213 s.len = names[i].len - 6;
214 s.data = names[i].data + 6;
215
216 r->valid = ngx_parse_time(&s, 1);
217
218 if (r->valid == (time_t) NGX_ERROR-1) {
219 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
220 "invalid parameter: %V", &names[i]);
221 return NULL((void*)0);
222 }
223
224 continue;
225 }
226
227#if (NGX_HAVE_INET6)
228 if (ngx_strncmp(names[i].data, "ipv6=", 5)(__extension__ (__builtin_constant_p (5) && ((__builtin_constant_p
((const char *) names[i].data) && strlen ((const char
*) names[i].data) < ((size_t) (5))) || (__builtin_constant_p
((const char *) "ipv6=") && strlen ((const char *) "ipv6="
) < ((size_t) (5)))) ? __extension__ ({ size_t __s1_len, __s2_len
; (__builtin_constant_p ((const char *) names[i].data) &&
__builtin_constant_p ((const char *) "ipv6=") && (__s1_len
= strlen ((const char *) names[i].data), __s2_len = strlen (
(const char *) "ipv6="), (!((size_t)(const void *)(((const char
*) names[i].data) + 1) - (size_t)(const void *)((const char *
) names[i].data) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)(((const char *) "ipv6=") + 1) - (size_t)(const
void *)((const char *) "ipv6=") == 1) || __s2_len >= 4)) ?
__builtin_strcmp ((const char *) names[i].data, (const char *
) "ipv6=") : (__builtin_constant_p ((const char *) names[i].data
) && ((size_t)(const void *)(((const char *) names[i]
.data) + 1) - (size_t)(const void *)((const char *) names[i].
data) == 1) && (__s1_len = strlen ((const char *) names
[i].data), __s1_len < 4) ? (__builtin_constant_p ((const char
*) "ipv6=") && ((size_t)(const void *)(((const char *
) "ipv6=") + 1) - (size_t)(const void *)((const char *) "ipv6="
) == 1) ? __builtin_strcmp ((const char *) names[i].data, (const
char *) "ipv6=") : (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) ((const char *) "ipv6="
); int __result = (((const unsigned char *) (const char *) ((
const char *) names[i].data))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) ((const char *) names[i].data))[1] - __s2[
1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) names
[i].data))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
const char *) names[i].data))[3] - __s2[3]); } } __result; })
)) : (__builtin_constant_p ((const char *) "ipv6=") &&
((size_t)(const void *)(((const char *) "ipv6=") + 1) - (size_t
)(const void *)((const char *) "ipv6=") == 1) && (__s2_len
= strlen ((const char *) "ipv6="), __s2_len < 4) ? (__builtin_constant_p
((const char *) names[i].data) && ((size_t)(const void
*)(((const char *) names[i].data) + 1) - (size_t)(const void
*)((const char *) names[i].data) == 1) ? __builtin_strcmp ((
const char *) names[i].data, (const char *) "ipv6=") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) names[i].data); int __result = (((const
unsigned char *) (const char *) ((const char *) "ipv6="))[0]
- __s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) "ipv6="
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "ipv6="))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "ipv6="))[3] - __s2[3]); } } __result; })
))) : __builtin_strcmp ((const char *) names[i].data, (const char
*) "ipv6=")))); }) : strncmp ((const char *) names[i].data, (
const char *) "ipv6=", 5)))
== 0) {
229
230 if (ngx_strcmp(&names[i].data[5], "on")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) &names[i].data[5]) && __builtin_constant_p
((const char *) "on") && (__s1_len = strlen ((const char
*) &names[i].data[5]), __s2_len = strlen ((const char *)
"on"), (!((size_t)(const void *)(((const char *) &names[
i].data[5]) + 1) - (size_t)(const void *)((const char *) &
names[i].data[5]) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)(((const char *) "on") + 1) - (size_t)(const void
*)((const char *) "on") == 1) || __s2_len >= 4)) ? __builtin_strcmp
((const char *) &names[i].data[5], (const char *) "on") :
(__builtin_constant_p ((const char *) &names[i].data[5])
&& ((size_t)(const void *)(((const char *) &names
[i].data[5]) + 1) - (size_t)(const void *)((const char *) &
names[i].data[5]) == 1) && (__s1_len = strlen ((const
char *) &names[i].data[5]), __s1_len < 4) ? (__builtin_constant_p
((const char *) "on") && ((size_t)(const void *)(((const
char *) "on") + 1) - (size_t)(const void *)((const char *) "on"
) == 1) ? __builtin_strcmp ((const char *) &names[i].data
[5], (const char *) "on") : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) ((const char *
) "on"); int __result = (((const unsigned char *) (const char
*) ((const char *) &names[i].data[5]))[0] - __s2[0]); if
(__s1_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) ((const char *) &names[i
].data[5]))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) &names[i].data[5]))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((const char *) &names[i].data[5]
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
(const char *) "on") && ((size_t)(const void *)(((const
char *) "on") + 1) - (size_t)(const void *)((const char *) "on"
) == 1) && (__s2_len = strlen ((const char *) "on"), __s2_len
< 4) ? (__builtin_constant_p ((const char *) &names[i
].data[5]) && ((size_t)(const void *)(((const char *)
&names[i].data[5]) + 1) - (size_t)(const void *)((const char
*) &names[i].data[5]) == 1) ? __builtin_strcmp ((const char
*) &names[i].data[5], (const char *) "on") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) &names[i].data[5]); int __result
= (((const unsigned char *) (const char *) ((const char *) "on"
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "on"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((const char *) "on"))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ((const char *) "on"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp ((const char *) &names[i].data
[5], (const char *) "on")))); })
== 0) {
231 r->ipv6 = 1;
232
233 } else if (ngx_strcmp(&names[i].data[5], "off")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) &names[i].data[5]) && __builtin_constant_p
((const char *) "off") && (__s1_len = strlen ((const
char *) &names[i].data[5]), __s2_len = strlen ((const char
*) "off"), (!((size_t)(const void *)(((const char *) &names
[i].data[5]) + 1) - (size_t)(const void *)((const char *) &
names[i].data[5]) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)(((const char *) "off") + 1) - (size_t)(const void
*)((const char *) "off") == 1) || __s2_len >= 4)) ? __builtin_strcmp
((const char *) &names[i].data[5], (const char *) "off")
: (__builtin_constant_p ((const char *) &names[i].data[5
]) && ((size_t)(const void *)(((const char *) &names
[i].data[5]) + 1) - (size_t)(const void *)((const char *) &
names[i].data[5]) == 1) && (__s1_len = strlen ((const
char *) &names[i].data[5]), __s1_len < 4) ? (__builtin_constant_p
((const char *) "off") && ((size_t)(const void *)(((
const char *) "off") + 1) - (size_t)(const void *)((const char
*) "off") == 1) ? __builtin_strcmp ((const char *) &names
[i].data[5], (const char *) "off") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ((const char
*) "off"); int __result = (((const unsigned char *) (const char
*) ((const char *) &names[i].data[5]))[0] - __s2[0]); if
(__s1_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) ((const char *) &names[i
].data[5]))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) &names[i].data[5]))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((const char *) &names[i].data[5]
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
(const char *) "off") && ((size_t)(const void *)(((const
char *) "off") + 1) - (size_t)(const void *)((const char *) "off"
) == 1) && (__s2_len = strlen ((const char *) "off"),
__s2_len < 4) ? (__builtin_constant_p ((const char *) &
names[i].data[5]) && ((size_t)(const void *)(((const char
*) &names[i].data[5]) + 1) - (size_t)(const void *)((const
char *) &names[i].data[5]) == 1) ? __builtin_strcmp ((const
char *) &names[i].data[5], (const char *) "off") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) &names[i].data[5]); int __result
= (((const unsigned char *) (const char *) ((const char *) "off"
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "off"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((const char *) "off"))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ((const char *) "off"))[3] - __s2[3]); } }
__result; })))) : __builtin_strcmp ((const char *) &names
[i].data[5], (const char *) "off")))); })
== 0) {
234 r->ipv6 = 0;
235
236 } else {
237 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
238 "invalid parameter: %V", &names[i]);
239 return NULL((void*)0);
240 }
241
242 continue;
243 }
244#endif
245
246 ngx_memzero(&u, sizeof(ngx_url_t))(void) memset(&u, 0, sizeof(ngx_url_t));
247
248 u.url = names[i];
249 u.default_port = 53;
250
251 if (ngx_parse_url(cf->pool, &u) != NGX_OK0) {
252 if (u.err) {
253 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
254 "%s in resolver \"%V\"",
255 u.err, &u.url);
256 }
257
258 return NULL((void*)0);
259 }
260
261 rec = ngx_array_push_n(&r->connections, u.naddrs);
262 if (rec == NULL((void*)0)) {
263 return NULL((void*)0);
264 }
265
266 ngx_memzero(rec, u.naddrs * sizeof(ngx_resolver_connection_t))(void) memset(rec, 0, u.naddrs * sizeof(ngx_resolver_connection_t
))
;
267
268 for (j = 0; j < u.naddrs; j++) {
269 rec[j].sockaddr = u.addrs[j].sockaddr;
270 rec[j].socklen = u.addrs[j].socklen;
271 rec[j].server = u.addrs[j].name;
272 rec[j].resolver = r;
273 }
274 }
275
276 return r;
277}
278
279
280static void
281ngx_resolver_cleanup(void *data)
282{
283 ngx_resolver_t *r = data;
284
285 ngx_uint_t i;
286 ngx_resolver_connection_t *rec;
287
288 if (r) {
289 ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
290 "cleanup resolver");
291
292 ngx_resolver_cleanup_tree(r, &r->name_rbtree);
293
294 ngx_resolver_cleanup_tree(r, &r->srv_rbtree);
295
296 ngx_resolver_cleanup_tree(r, &r->addr_rbtree);
297
298#if (NGX_HAVE_INET6)
299 ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
300#endif
301
302 if (r->event) {
303 ngx_freefree(r->event);
304 }
305
306
307 rec = r->connections.elts;
308
309 for (i = 0; i < r->connections.nelts; i++) {
310 if (rec[i].udp) {
311 ngx_close_connection(rec[i].udp);
312 }
313
314 if (rec[i].tcp) {
315 ngx_close_connection(rec[i].tcp);
316 }
317
318 if (rec[i].read_buf) {
319 ngx_resolver_free(r, rec[i].read_buf->start);
320 ngx_resolver_free(r, rec[i].read_buf);
321 }
322
323 if (rec[i].write_buf) {
324 ngx_resolver_free(r, rec[i].write_buf->start);
325 ngx_resolver_free(r, rec[i].write_buf);
326 }
327 }
328
329 ngx_freefree(r);
330 }
331}
332
333
334static void
335ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree)
336{
337 ngx_resolver_ctx_t *ctx, *next;
338 ngx_resolver_node_t *rn;
339
340 while (tree->root != tree->sentinel) {
341
342 rn = ngx_resolver_node(ngx_rbtree_min(tree->root, tree->sentinel))(ngx_resolver_node_t *) ((u_char *) (ngx_rbtree_min(tree->
root, tree->sentinel)) - __builtin_offsetof(ngx_resolver_node_t
, node))
;
343
344 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
345
346 for (ctx = rn->waiting; ctx; ctx = next) {
347 next = ctx->next;
348
349 if (ctx->event) {
350 ngx_resolver_free(r, ctx->event);
351 }
352
353 ngx_resolver_free(r, ctx);
354 }
355
356 ngx_rbtree_delete(tree, &rn->node);
357
358 ngx_resolver_free_node(r, rn);
359 }
360}
361
362
363ngx_resolver_ctx_t *
364ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
365{
366 in_addr_t addr;
367 ngx_resolver_ctx_t *ctx;
368
369 if (temp) {
370 addr = ngx_inet_addr(temp->name.data, temp->name.len);
371
372 if (addr != INADDR_NONE((in_addr_t) 0xffffffff)) {
373 temp->resolver = r;
374 temp->state = NGX_OK0;
375 temp->naddrs = 1;
376 temp->addrs = &temp->addr;
377 temp->addr.sockaddr = (struct sockaddr *) &temp->sin;
378 temp->addr.socklen = sizeof(struct sockaddr_in);
379 ngx_memzero(&temp->sin, sizeof(struct sockaddr_in))(void) memset(&temp->sin, 0, sizeof(struct sockaddr_in
))
;
380 temp->sin.sin_family = AF_INET2;
381 temp->sin.sin_addr.s_addr = addr;
382 temp->quick = 1;
383
384 return temp;
385 }
386 }
387
388 if (r->connections.nelts == 0) {
389 return NGX_NO_RESOLVER(void *) -1;
390 }
391
392 ctx = ngx_resolver_calloc(r, sizeof(ngx_resolver_ctx_t));
393
394 if (ctx) {
395 ctx->resolver = r;
396 }
397
398 return ctx;
399}
400
401
402ngx_int_t
403ngx_resolve_name(ngx_resolver_ctx_t *ctx)
404{
405 size_t slen;
406 ngx_int_t rc;
407 ngx_str_t name;
408 ngx_resolver_t *r;
409
410 r = ctx->resolver;
411
412 if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') {
413 ctx->name.len--;
414 }
415
416 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
417 "resolve: \"%V\"", &ctx->name);
418
419 if (ctx->quick) {
420 ctx->handler(ctx);
421 return NGX_OK0;
422 }
423
424 if (ctx->service.len) {
425 slen = ctx->service.len;
426
427 if (ngx_strlchr(ctx->service.data,
428 ctx->service.data + ctx->service.len, '.')
429 == NULL((void*)0))
430 {
431 slen += sizeof("_._tcp") - 1;
432 }
433
434 name.len = slen + 1 + ctx->name.len;
435
436 name.data = ngx_resolver_alloc(r, name.len);
437 if (name.data == NULL((void*)0)) {
438 return NGX_ERROR-1;
439 }
440
441 if (slen == ctx->service.len) {
442 ngx_sprintf(name.data, "%V.%V", &ctx->service, &ctx->name);
443
444 } else {
445 ngx_sprintf(name.data, "_%V._tcp.%V", &ctx->service, &ctx->name);
446 }
447
448 /* lock name mutex */
449
450 rc = ngx_resolve_name_locked(r, ctx, &name);
451
452 ngx_resolver_free(r, name.data);
453
454 } else {
455 /* lock name mutex */
456
457 rc = ngx_resolve_name_locked(r, ctx, &ctx->name);
458 }
459
460 if (rc == NGX_OK0) {
461 return NGX_OK0;
462 }
463
464 /* unlock name mutex */
465
466 if (rc == NGX_AGAIN-2) {
467 return NGX_OK0;
468 }
469
470 /* NGX_ERROR */
471
472 if (ctx->event) {
473 ngx_resolver_free(r, ctx->event);
474 }
475
476 ngx_resolver_free(r, ctx);
477
478 return NGX_ERROR-1;
479}
480
481
482void
483ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
484{
485 ngx_uint_t i;
486 ngx_resolver_t *r;
487 ngx_resolver_ctx_t *w, **p;
488 ngx_resolver_node_t *rn;
489
490 r = ctx->resolver;
491
492 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
493 "resolve name done: %i", ctx->state);
494
495 if (ctx->quick) {
496 return;
497 }
498
499 if (ctx->event && ctx->event->timer_set) {
500 ngx_del_timerngx_event_del_timer(ctx->event);
501 }
502
503 /* lock name mutex */
504
505 if (ctx->nsrvs) {
506 for (i = 0; i < ctx->nsrvs; i++) {
507 if (ctx->srvs[i].ctx) {
508 ngx_resolve_name_done(ctx->srvs[i].ctx);
509 }
510
511 if (ctx->srvs[i].addrs) {
512 ngx_resolver_free(r, ctx->srvs[i].addrs->sockaddr);
513 ngx_resolver_free(r, ctx->srvs[i].addrs);
514 }
515
516 ngx_resolver_free(r, ctx->srvs[i].name.data);
517 }
518
519 ngx_resolver_free(r, ctx->srvs);
520 }
521
522 if (ctx->state == NGX_AGAIN-2 || ctx->state == NGX_RESOLVE_TIMEDOUT110) {
523
524 rn = ctx->node;
525
526 if (rn) {
527 p = &rn->waiting;
528 w = rn->waiting;
529
530 while (w) {
531 if (w == ctx) {
532 *p = w->next;
533
534 goto done;
535 }
536
537 p = &w->next;
538 w = w->next;
539 }
540
541 ngx_log_error(NGX_LOG_ALERT, r->log, 0,if ((r->log)->log_level >= 2) ngx_log_error_core(2, r
->log, 0, "could not cancel %V resolving", &ctx->name
)
542 "could not cancel %V resolving", &ctx->name)if ((r->log)->log_level >= 2) ngx_log_error_core(2, r
->log, 0, "could not cancel %V resolving", &ctx->name
)
;
543 }
544 }
545
546done:
547
548 if (ctx->service.len) {
549 ngx_resolver_expire(r, &r->srv_rbtree, &r->srv_expire_queue);
550
551 } else {
552 ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue);
553 }
554
555 /* unlock name mutex */
556
557 /* lock alloc mutex */
558
559 if (ctx->event) {
560 ngx_resolver_free_locked(r, ctx->event);
561 }
562
563 ngx_resolver_free_locked(r, ctx);
564
565 /* unlock alloc mutex */
566
567 if (r->event->timer_set && ngx_resolver_resend_empty(r)) {
568 ngx_del_timerngx_event_del_timer(r->event);
569 }
570}
571
572
573static ngx_int_t
574ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
575 ngx_str_t *name)
576{
577 uint32_t hash;
578 ngx_int_t rc;
579 ngx_str_t cname;
580 ngx_uint_t i, naddrs;
581 ngx_queue_t *resend_queue, *expire_queue;
582 ngx_rbtree_t *tree;
583 ngx_resolver_ctx_t *next, *last;
584 ngx_resolver_addr_t *addrs;
585 ngx_resolver_node_t *rn;
586
587 ngx_strlow(name->data, name->data, name->len);
588
589 hash = ngx_crc32_short(name->data, name->len);
590
591 if (ctx->service.len) {
592 rn = ngx_resolver_lookup_srv(r, name, hash);
593
594 tree = &r->srv_rbtree;
595 resend_queue = &r->srv_resend_queue;
596 expire_queue = &r->srv_expire_queue;
597
598 } else {
599 rn = ngx_resolver_lookup_name(r, name, hash);
600
601 tree = &r->name_rbtree;
602 resend_queue = &r->name_resend_queue;
603 expire_queue = &r->name_expire_queue;
604 }
605
606 if (rn) {
607
608 /* ctx can be a list after NGX_RESOLVE_CNAME */
609 for (last = ctx; last->next; last = last->next);
610
611 if (rn->valid >= ngx_time()ngx_cached_time->sec) {
612
613 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached");
614
615 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
616
617 rn->expire = ngx_time()ngx_cached_time->sec + r->expire;
618
619 ngx_queue_insert_head(expire_queue, &rn->queue)(&rn->queue)->next = (expire_queue)->next; (&
rn->queue)->next->prev = &rn->queue; (&rn
->queue)->prev = expire_queue; (expire_queue)->next =
&rn->queue
;
620
621 naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
622#if (NGX_HAVE_INET6)
623 naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
624#endif
625
626 if (naddrs) {
627
628 if (naddrs == 1 && rn->naddrs == 1) {
629 addrs = NULL((void*)0);
630
631 } else {
632 addrs = ngx_resolver_export(r, rn, 1);
633 if (addrs == NULL((void*)0)) {
634 return NGX_ERROR-1;
635 }
636 }
637
638 last->next = rn->waiting;
639 rn->waiting = NULL((void*)0);
640
641 /* unlock name mutex */
642
643 do {
644 ctx->state = NGX_OK0;
645 ctx->valid = rn->valid;
646 ctx->naddrs = naddrs;
647
648 if (addrs == NULL((void*)0)) {
649 ctx->addrs = &ctx->addr;
650 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
651 ctx->addr.socklen = sizeof(struct sockaddr_in);
652 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in))(void) memset(&ctx->sin, 0, sizeof(struct sockaddr_in)
)
;
653 ctx->sin.sin_family = AF_INET2;
654 ctx->sin.sin_addr.s_addr = rn->u.addr;
655
656 } else {
657 ctx->addrs = addrs;
658 }
659
660 next = ctx->next;
661
662 ctx->handler(ctx);
663
664 ctx = next;
665 } while (ctx);
666
667 if (addrs != NULL((void*)0)) {
668 ngx_resolver_free(r, addrs->sockaddr);
669 ngx_resolver_free(r, addrs);
670 }
671
672 return NGX_OK0;
673 }
674
675 if (rn->nsrvs) {
676 last->next = rn->waiting;
677 rn->waiting = NULL((void*)0);
678
679 /* unlock name mutex */
680
681 do {
682 next = ctx->next;
683
684 ngx_resolver_resolve_srv_names(ctx, rn);
685
686 ctx = next;
687 } while (ctx);
688
689 return NGX_OK0;
690 }
691
692 /* NGX_RESOLVE_CNAME */
693
694 if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION50) {
695
696 cname.len = rn->cnlen;
697 cname.data = rn->u.cname;
698
699 return ngx_resolve_name_locked(r, ctx, &cname);
700 }
701
702 last->next = rn->waiting;
703 rn->waiting = NULL((void*)0);
704
705 /* unlock name mutex */
706
707 do {
708 ctx->state = NGX_RESOLVE_NXDOMAIN3;
709 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
710 next = ctx->next;
711
712 ctx->handler(ctx);
713
714 ctx = next;
715 } while (ctx);
716
717 return NGX_OK0;
718 }
719
720 if (rn->waiting) {
721
722 if (ctx->event == NULL((void*)0) && ctx->timeout) {
723 ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
724 if (ctx->event == NULL((void*)0)) {
725 return NGX_ERROR-1;
726 }
727
728 ctx->event->handler = ngx_resolver_timeout_handler;
729 ctx->event->data = ctx;
730 ctx->event->log = r->log;
731 ctx->ident = -1;
732
733 ngx_add_timerngx_event_add_timer(ctx->event, ctx->timeout);
734 }
735
736 last->next = rn->waiting;
737 rn->waiting = ctx;
738 ctx->state = NGX_AGAIN-2;
739
740 do {
741 ctx->node = rn;
742 ctx = ctx->next;
743 } while (ctx);
744
745 return NGX_AGAIN-2;
746 }
747
748 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
749
750 /* lock alloc mutex */
751
752 if (rn->query) {
753 ngx_resolver_free_locked(r, rn->query);
754 rn->query = NULL((void*)0);
755#if (NGX_HAVE_INET6)
756 rn->query6 = NULL((void*)0);
757#endif
758 }
759
760 if (rn->cnlen) {
761 ngx_resolver_free_locked(r, rn->u.cname);
762 }
763
764 if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
765 ngx_resolver_free_locked(r, rn->u.addrs);
766 }
767
768#if (NGX_HAVE_INET6)
769 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
770 ngx_resolver_free_locked(r, rn->u6.addrs6);
771 }
772#endif
773
774 if (rn->nsrvs) {
775 for (i = 0; i < rn->nsrvs; i++) {
776 if (rn->u.srvs[i].name.data) {
777 ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
778 }
779 }
780
781 ngx_resolver_free_locked(r, rn->u.srvs);
782 }
783
784 /* unlock alloc mutex */
785
786 } else {
787
788 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
789 if (rn == NULL((void*)0)) {
790 return NGX_ERROR-1;
791 }
792
793 rn->name = ngx_resolver_dup(r, name->data, name->len);
794 if (rn->name == NULL((void*)0)) {
795 ngx_resolver_free(r, rn);
796 return NGX_ERROR-1;
797 }
798
799 rn->node.key = hash;
800 rn->nlen = (u_short) name->len;
801 rn->query = NULL((void*)0);
802#if (NGX_HAVE_INET6)
803 rn->query6 = NULL((void*)0);
804#endif
805
806 ngx_rbtree_insert(tree, &rn->node);
807 }
808
809 if (ctx->service.len) {
810 rc = ngx_resolver_create_srv_query(r, rn, name);
811
812 } else {
813 rc = ngx_resolver_create_name_query(r, rn, name);
814 }
815
816 if (rc == NGX_ERROR-1) {
817 goto failed;
818 }
819
820 if (rc == NGX_DECLINED-5) {
821 ngx_rbtree_delete(tree, &rn->node);
822
823 ngx_resolver_free(r, rn->query);
824 ngx_resolver_free(r, rn->name);
825 ngx_resolver_free(r, rn);
826
827 do {
828 ctx->state = NGX_RESOLVE_NXDOMAIN3;
829 next = ctx->next;
830
831 ctx->handler(ctx);
832
833 ctx = next;
834 } while (ctx);
835
836 return NGX_OK0;
837 }
838
839 rn->last_connection = r->last_connection++;
840 if (r->last_connection == r->connections.nelts) {
841 r->last_connection = 0;
842 }
843
844 rn->naddrs = (u_short) -1;
845 rn->tcp = 0;
846#if (NGX_HAVE_INET6)
847 rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
848 rn->tcp6 = 0;
849#endif
850 rn->nsrvs = 0;
851
852 if (ngx_resolver_send_query(r, rn) != NGX_OK0) {
853 goto failed;
854 }
855
856 if (ctx->event == NULL((void*)0) && ctx->timeout) {
857 ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
858 if (ctx->event == NULL((void*)0)) {
859 goto failed;
860 }
861
862 ctx->event->handler = ngx_resolver_timeout_handler;
863 ctx->event->data = ctx;
864 ctx->event->log = r->log;
865 ctx->ident = -1;
866
867 ngx_add_timerngx_event_add_timer(ctx->event, ctx->timeout);
868 }
869
870 if (ngx_queue_empty(resend_queue)(resend_queue == (resend_queue)->prev)) {
871 ngx_add_timerngx_event_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
872 }
873
874 rn->expire = ngx_time()ngx_cached_time->sec + r->resend_timeout;
875
876 ngx_queue_insert_head(resend_queue, &rn->queue)(&rn->queue)->next = (resend_queue)->next; (&
rn->queue)->next->prev = &rn->queue; (&rn
->queue)->prev = resend_queue; (resend_queue)->next =
&rn->queue
;
877
878 rn->code = 0;
879 rn->cnlen = 0;
880 rn->valid = 0;
881 rn->ttl = NGX_MAX_UINT32_VALUE(uint32_t) 0xffffffff;
882 rn->waiting = ctx;
883
884 ctx->state = NGX_AGAIN-2;
885
886 do {
887 ctx->node = rn;
888 ctx = ctx->next;
889 } while (ctx);
890
891 return NGX_AGAIN-2;
892
893failed:
894
895 ngx_rbtree_delete(tree, &rn->node);
896
897 if (rn->query) {
898 ngx_resolver_free(r, rn->query);
899 }
900
901 ngx_resolver_free(r, rn->name);
902
903 ngx_resolver_free(r, rn);
904
905 return NGX_ERROR-1;
906}
907
908
909ngx_int_t
910ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
911{
912 u_char *name;
913 in_addr_t addr;
914 ngx_queue_t *resend_queue, *expire_queue;
915 ngx_rbtree_t *tree;
916 ngx_resolver_t *r;
917 struct sockaddr_in *sin;
918 ngx_resolver_node_t *rn;
919#if (NGX_HAVE_INET6)
920 uint32_t hash;
921 struct sockaddr_in6 *sin6;
922#endif
923
924#if (NGX_SUPPRESS_WARN1)
925 addr = 0;
Value stored to 'addr' is never read
926#if (NGX_HAVE_INET6)
927 hash = 0;
928 sin6 = NULL((void*)0);
929#endif
930#endif
931
932 r = ctx->resolver;
933
934 switch (ctx->addr.sockaddr->sa_family) {
935
936#if (NGX_HAVE_INET6)
937 case AF_INET610:
938 sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
939 hash = ngx_crc32_short(sin6->sin6_addr.s6_addr__in6_u.__u6_addr8, 16);
940
941 /* lock addr mutex */
942
943 rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
944
945 tree = &r->addr6_rbtree;
946 resend_queue = &r->addr6_resend_queue;
947 expire_queue = &r->addr6_expire_queue;
948
949 break;
950#endif
951
952 default: /* AF_INET */
953 sin = (struct sockaddr_in *) ctx->addr.sockaddr;
954 addr = ntohl(sin->sin_addr.s_addr)(__extension__ ({ unsigned int __v, __x = (sin->sin_addr.s_addr
); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
955
956 /* lock addr mutex */
957
958 rn = ngx_resolver_lookup_addr(r, addr);
959
960 tree = &r->addr_rbtree;
961 resend_queue = &r->addr_resend_queue;
962 expire_queue = &r->addr_expire_queue;
963 }
964
965 if (rn) {
966
967 if (rn->valid >= ngx_time()ngx_cached_time->sec) {
968
969 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached");
970
971 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
972
973 rn->expire = ngx_time()ngx_cached_time->sec + r->expire;
974
975 ngx_queue_insert_head(expire_queue, &rn->queue)(&rn->queue)->next = (expire_queue)->next; (&
rn->queue)->next->prev = &rn->queue; (&rn
->queue)->prev = expire_queue; (expire_queue)->next =
&rn->queue
;
976
977 name = ngx_resolver_dup(r, rn->name, rn->nlen);
978 if (name == NULL((void*)0)) {
979 goto failed;
980 }
981
982 ctx->name.len = rn->nlen;
983 ctx->name.data = name;
984
985 /* unlock addr mutex */
986
987 ctx->state = NGX_OK0;
988 ctx->valid = rn->valid;
989
990 ctx->handler(ctx);
991
992 ngx_resolver_free(r, name);
993
994 return NGX_OK0;
995 }
996
997 if (rn->waiting) {
998
999 if (ctx->event == NULL((void*)0) && ctx->timeout) {
1000 ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
1001 if (ctx->event == NULL((void*)0)) {
1002 return NGX_ERROR-1;
1003 }
1004
1005 ctx->event->handler = ngx_resolver_timeout_handler;
1006 ctx->event->data = ctx;
1007 ctx->event->log = r->log;
1008 ctx->ident = -1;
1009
1010 ngx_add_timerngx_event_add_timer(ctx->event, ctx->timeout);
1011 }
1012
1013 ctx->next = rn->waiting;
1014 rn->waiting = ctx;
1015 ctx->state = NGX_AGAIN-2;
1016 ctx->node = rn;
1017
1018 /* unlock addr mutex */
1019
1020 return NGX_OK0;
1021 }
1022
1023 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
1024
1025 ngx_resolver_free(r, rn->query);
1026 rn->query = NULL((void*)0);
1027#if (NGX_HAVE_INET6)
1028 rn->query6 = NULL((void*)0);
1029#endif
1030
1031 } else {
1032 rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
1033 if (rn == NULL((void*)0)) {
1034 goto failed;
1035 }
1036
1037 switch (ctx->addr.sockaddr->sa_family) {
1038
1039#if (NGX_HAVE_INET6)
1040 case AF_INET610:
1041 rn->addr6 = sin6->sin6_addr;
1042 rn->node.key = hash;
1043 break;
1044#endif
1045
1046 default: /* AF_INET */
1047 rn->node.key = addr;
1048 }
1049
1050 rn->query = NULL((void*)0);
1051#if (NGX_HAVE_INET6)
1052 rn->query6 = NULL((void*)0);
1053#endif
1054
1055 ngx_rbtree_insert(tree, &rn->node);
1056 }
1057
1058 if (ngx_resolver_create_addr_query(r, rn, &ctx->addr) != NGX_OK0) {
1059 goto failed;
1060 }
1061
1062 rn->last_connection = r->last_connection++;
1063 if (r->last_connection == r->connections.nelts) {
1064 r->last_connection = 0;
1065 }
1066
1067 rn->naddrs = (u_short) -1;
1068 rn->tcp = 0;
1069#if (NGX_HAVE_INET6)
1070 rn->naddrs6 = (u_short) -1;
1071 rn->tcp6 = 0;
1072#endif
1073 rn->nsrvs = 0;
1074
1075 if (ngx_resolver_send_query(r, rn) != NGX_OK0) {
1076 goto failed;
1077 }
1078
1079 if (ctx->event == NULL((void*)0) && ctx->timeout) {
1080 ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
1081 if (ctx->event == NULL((void*)0)) {
1082 goto failed;
1083 }
1084
1085 ctx->event->handler = ngx_resolver_timeout_handler;
1086 ctx->event->data = ctx;
1087 ctx->event->log = r->log;
1088 ctx->ident = -1;
1089
1090 ngx_add_timerngx_event_add_timer(ctx->event, ctx->timeout);
1091 }
1092
1093 if (ngx_queue_empty(resend_queue)(resend_queue == (resend_queue)->prev)) {
1094 ngx_add_timerngx_event_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
1095 }
1096
1097 rn->expire = ngx_time()ngx_cached_time->sec + r->resend_timeout;
1098
1099 ngx_queue_insert_head(resend_queue, &rn->queue)(&rn->queue)->next = (resend_queue)->next; (&
rn->queue)->next->prev = &rn->queue; (&rn
->queue)->prev = resend_queue; (resend_queue)->next =
&rn->queue
;
1100
1101 rn->code = 0;
1102 rn->cnlen = 0;
1103 rn->name = NULL((void*)0);
1104 rn->nlen = 0;
1105 rn->valid = 0;
1106 rn->ttl = NGX_MAX_UINT32_VALUE(uint32_t) 0xffffffff;
1107 rn->waiting = ctx;
1108
1109 /* unlock addr mutex */
1110
1111 ctx->state = NGX_AGAIN-2;
1112 ctx->node = rn;
1113
1114 return NGX_OK0;
1115
1116failed:
1117
1118 if (rn) {
1119 ngx_rbtree_delete(tree, &rn->node);
1120
1121 if (rn->query) {
1122 ngx_resolver_free(r, rn->query);
1123 }
1124
1125 ngx_resolver_free(r, rn);
1126 }
1127
1128 /* unlock addr mutex */
1129
1130 if (ctx->event) {
1131 ngx_resolver_free(r, ctx->event);
1132 }
1133
1134 ngx_resolver_free(r, ctx);
1135
1136 return NGX_ERROR-1;
1137}
1138
1139
1140void
1141ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
1142{
1143 ngx_queue_t *expire_queue;
1144 ngx_rbtree_t *tree;
1145 ngx_resolver_t *r;
1146 ngx_resolver_ctx_t *w, **p;
1147 ngx_resolver_node_t *rn;
1148
1149 r = ctx->resolver;
1150
1151 switch (ctx->addr.sockaddr->sa_family) {
1152
1153#if (NGX_HAVE_INET6)
1154 case AF_INET610:
1155 tree = &r->addr6_rbtree;
1156 expire_queue = &r->addr6_expire_queue;
1157 break;
1158#endif
1159
1160 default: /* AF_INET */
1161 tree = &r->addr_rbtree;
1162 expire_queue = &r->addr_expire_queue;
1163 }
1164
1165 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
1166 "resolve addr done: %i", ctx->state);
1167
1168 if (ctx->event && ctx->event->timer_set) {
1169 ngx_del_timerngx_event_del_timer(ctx->event);
1170 }
1171
1172 /* lock addr mutex */
1173
1174 if (ctx->state == NGX_AGAIN-2 || ctx->state == NGX_RESOLVE_TIMEDOUT110) {
1175
1176 rn = ctx->node;
1177
1178 if (rn) {
1179 p = &rn->waiting;
1180 w = rn->waiting;
1181
1182 while (w) {
1183 if (w == ctx) {
1184 *p = w->next;
1185
1186 goto done;
1187 }
1188
1189 p = &w->next;
1190 w = w->next;
1191 }
1192 }
1193
1194 {
1195 u_char text[NGX_SOCKADDR_STRLEN(sizeof("unix:") - 1 + (sizeof(struct sockaddr_un) - __builtin_offsetof
(struct sockaddr_un, sun_path)))
];
1196 ngx_str_t addrtext;
1197
1198 addrtext.data = text;
1199 addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen,
1200 text, NGX_SOCKADDR_STRLEN(sizeof("unix:") - 1 + (sizeof(struct sockaddr_un) - __builtin_offsetof
(struct sockaddr_un, sun_path)))
, 0);
1201
1202 ngx_log_error(NGX_LOG_ALERT, r->log, 0,if ((r->log)->log_level >= 2) ngx_log_error_core(2, r
->log, 0, "could not cancel %V resolving", &addrtext)
1203 "could not cancel %V resolving", &addrtext)if ((r->log)->log_level >= 2) ngx_log_error_core(2, r
->log, 0, "could not cancel %V resolving", &addrtext)
;
1204 }
1205 }
1206
1207done:
1208
1209 ngx_resolver_expire(r, tree, expire_queue);
1210
1211 /* unlock addr mutex */
1212
1213 /* lock alloc mutex */
1214
1215 if (ctx->event) {
1216 ngx_resolver_free_locked(r, ctx->event);
1217 }
1218
1219 ngx_resolver_free_locked(r, ctx);
1220
1221 /* unlock alloc mutex */
1222
1223 if (r->event->timer_set && ngx_resolver_resend_empty(r)) {
1224 ngx_del_timerngx_event_del_timer(r->event);
1225 }
1226}
1227
1228
1229static void
1230ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
1231{
1232 time_t now;
1233 ngx_uint_t i;
1234 ngx_queue_t *q;
1235 ngx_resolver_node_t *rn;
1236
1237 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver expire");
1238
1239 now = ngx_time()ngx_cached_time->sec;
1240
1241 for (i = 0; i < 2; i++) {
1242 if (ngx_queue_empty(queue)(queue == (queue)->prev)) {
1243 return;
1244 }
1245
1246 q = ngx_queue_last(queue)(queue)->prev;
1247
1248 rn = ngx_queue_data(q, ngx_resolver_node_t, queue)(ngx_resolver_node_t *) ((u_char *) q - __builtin_offsetof(ngx_resolver_node_t
, queue))
;
1249
1250 if (now <= rn->expire) {
1251 return;
1252 }
1253
1254 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
1255 "resolver expire \"%*s\"", (size_t) rn->nlen, rn->name);
1256
1257 ngx_queue_remove(q)(q)->next->prev = (q)->prev; (q)->prev->next =
(q)->next
;
1258
1259 ngx_rbtree_delete(tree, &rn->node);
1260
1261 ngx_resolver_free_node(r, rn);
1262 }
1263}
1264
1265
1266static ngx_int_t
1267ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
1268{
1269 ngx_int_t rc;
1270 ngx_resolver_connection_t *rec;
1271
1272 rec = r->connections.elts;
1273 rec = &rec[rn->last_connection];
1274
1275 if (rec->log.handler == NULL((void*)0)) {
1276 rec->log = *r->log;
1277 rec->log.handler = ngx_resolver_log_error;
1278 rec->log.data = rec;
1279 rec->log.action = "resolving";
1280 }
1281
1282 if (rn->naddrs == (u_short) -1) {
1283 rc = rn->tcp ? ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen)
1284 : ngx_resolver_send_udp_query(r, rec, rn->query, rn->qlen);
1285
1286 if (rc != NGX_OK0) {
1287 return rc;
1288 }
1289 }
1290
1291#if (NGX_HAVE_INET6)
1292
1293 if (rn->query6 && rn->naddrs6 == (u_short) -1) {
1294 rc = rn->tcp6
1295 ? ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen)
1296 : ngx_resolver_send_udp_query(r, rec, rn->query6, rn->qlen);
1297
1298 if (rc != NGX_OK0) {
1299 return rc;
1300 }
1301 }
1302
1303#endif
1304
1305 return NGX_OK0;
1306}
1307
1308
1309static ngx_int_t
1310ngx_resolver_send_udp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec,
1311 u_char *query, u_short qlen)
1312{
1313 ssize_t n;
1314
1315 if (rec->udp == NULL((void*)0)) {
1316 if (ngx_udp_connect(rec) != NGX_OK0) {
1317 return NGX_ERROR-1;
1318 }
1319
1320 rec->udp->data = rec;
1321 rec->udp->read->handler = ngx_resolver_udp_read;
1322 rec->udp->read->resolver = 1;
1323 }
1324
1325 n = ngx_sendngx_io.send(rec->udp, query, qlen);
1326
1327 if (n == -1) {
1328 return NGX_ERROR-1;
1329 }
1330
1331 if ((size_t) n != (size_t) qlen) {
1332 ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "send() incomplete")if ((&rec->log)->log_level >= 3) ngx_log_error_core
(3, &rec->log, 0, "send() incomplete")
;
1333 return NGX_ERROR-1;
1334 }
1335
1336 return NGX_OK0;
1337}
1338
1339
1340static ngx_int_t
1341ngx_resolver_send_tcp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec,
1342 u_char *query, u_short qlen)
1343{
1344 ngx_buf_t *b;
1345 ngx_int_t rc;
1346
1347 rc = NGX_OK0;
1348
1349 if (rec->tcp == NULL((void*)0)) {
1350 b = rec->read_buf;
1351
1352 if (b == NULL((void*)0)) {
1353 b = ngx_resolver_calloc(r, sizeof(ngx_buf_t));
1354 if (b == NULL((void*)0)) {
1355 return NGX_ERROR-1;
1356 }
1357
1358 b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_RSIZE(2 + 65535));
1359 if (b->start == NULL((void*)0)) {
1360 ngx_resolver_free(r, b);
1361 return NGX_ERROR-1;
1362 }
1363
1364 b->end = b->start + NGX_RESOLVER_TCP_RSIZE(2 + 65535);
1365
1366 rec->read_buf = b;
1367 }
1368
1369 b->pos = b->start;
1370 b->last = b->start;
1371
1372 b = rec->write_buf;
1373
1374 if (b == NULL((void*)0)) {
1375 b = ngx_resolver_calloc(r, sizeof(ngx_buf_t));
1376 if (b == NULL((void*)0)) {
1377 return NGX_ERROR-1;
1378 }
1379
1380 b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_WSIZE8192);
1381 if (b->start == NULL((void*)0)) {
1382 ngx_resolver_free(r, b);
1383 return NGX_ERROR-1;
1384 }
1385
1386 b->end = b->start + NGX_RESOLVER_TCP_WSIZE8192;
1387
1388 rec->write_buf = b;
1389 }
1390
1391 b->pos = b->start;
1392 b->last = b->start;
1393
1394 rc = ngx_tcp_connect(rec);
1395 if (rc == NGX_ERROR-1) {
1396 return NGX_ERROR-1;
1397 }
1398
1399 rec->tcp->data = rec;
1400 rec->tcp->write->handler = ngx_resolver_tcp_write;
1401 rec->tcp->read->handler = ngx_resolver_tcp_read;
1402 rec->tcp->read->resolver = 1;
1403
1404 ngx_add_timerngx_event_add_timer(rec->tcp->write, (ngx_msec_t) (r->tcp_timeout * 1000));
1405 }
1406
1407 b = rec->write_buf;
1408
1409 if (b->end - b->last < 2 + qlen) {
1410 ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "buffer overflow")if ((&rec->log)->log_level >= 3) ngx_log_error_core
(3, &rec->log, 0, "buffer overflow")
;
1411 return NGX_ERROR-1;
1412 }
1413
1414 *b->last++ = (u_char) (qlen >> 8);
1415 *b->last++ = (u_char) qlen;
1416 b->last = ngx_cpymem(b->last, query, qlen)(((u_char *) memcpy(b->last, query, qlen)) + (qlen));
1417
1418 if (rc == NGX_OK0) {
1419 ngx_resolver_tcp_write(rec->tcp->write);
1420 }
1421
1422 return NGX_OK0;
1423}
1424
1425
1426static void
1427ngx_resolver_resend_handler(ngx_event_t *ev)
1428{
1429 time_t timer, atimer, stimer, ntimer;
1430#if (NGX_HAVE_INET6)
1431 time_t a6timer;
1432#endif
1433 ngx_resolver_t *r;
1434
1435 r = ev->data;
1436
1437 ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0,
1438 "resolver resend handler");
1439
1440 /* lock name mutex */
1441
1442 ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue);
1443
1444 stimer = ngx_resolver_resend(r, &r->srv_rbtree, &r->srv_resend_queue);
1445
1446 /* unlock name mutex */
1447
1448 /* lock addr mutex */
1449
1450 atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue);
1451
1452 /* unlock addr mutex */
1453
1454#if (NGX_HAVE_INET6)
1455
1456 /* lock addr6 mutex */
1457
1458 a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue);
1459
1460 /* unlock addr6 mutex */
1461
1462#endif
1463
1464 timer = ntimer;
1465
1466 if (timer == 0) {
1467 timer = atimer;
1468
1469 } else if (atimer) {
1470 timer = ngx_min(timer, atimer)((timer > atimer) ? (atimer) : (timer));
1471 }
1472
1473 if (timer == 0) {
1474 timer = stimer;
1475
1476 } else if (stimer) {
1477 timer = ngx_min(timer, stimer)((timer > stimer) ? (stimer) : (timer));
1478 }
1479
1480#if (NGX_HAVE_INET6)
1481
1482 if (timer == 0) {
1483 timer = a6timer;
1484
1485 } else if (a6timer) {
1486 timer = ngx_min(timer, a6timer)((timer > a6timer) ? (a6timer) : (timer));
1487 }
1488
1489#endif
1490
1491 if (timer) {
1492 ngx_add_timerngx_event_add_timer(r->event, (ngx_msec_t) (timer * 1000));
1493 }
1494}
1495
1496
1497static time_t
1498ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
1499{
1500 time_t now;
1501 ngx_queue_t *q;
1502 ngx_resolver_node_t *rn;
1503
1504 now = ngx_time()ngx_cached_time->sec;
1505
1506 for ( ;; ) {
1507 if (ngx_queue_empty(queue)(queue == (queue)->prev)) {
1508 return 0;
1509 }
1510
1511 q = ngx_queue_last(queue)(queue)->prev;
1512
1513 rn = ngx_queue_data(q, ngx_resolver_node_t, queue)(ngx_resolver_node_t *) ((u_char *) q - __builtin_offsetof(ngx_resolver_node_t
, queue))
;
1514
1515 if (now < rn->expire) {
1516 return rn->expire - now;
1517 }
1518
1519 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
1520 "resolver resend \"%*s\" %p",
1521 (size_t) rn->nlen, rn->name, rn->waiting);
1522
1523 ngx_queue_remove(q)(q)->next->prev = (q)->prev; (q)->prev->next =
(q)->next
;
1524
1525 if (rn->waiting) {
1526
1527 if (++rn->last_connection == r->connections.nelts) {
1528 rn->last_connection = 0;
1529 }
1530
1531 (void) ngx_resolver_send_query(r, rn);
1532
1533 rn->expire = now + r->resend_timeout;
1534
1535 ngx_queue_insert_head(queue, q)(q)->next = (queue)->next; (q)->next->prev = q; (
q)->prev = queue; (queue)->next = q
;
1536
1537 continue;
1538 }
1539
1540 ngx_rbtree_delete(tree, &rn->node);
1541
1542 ngx_resolver_free_node(r, rn);
1543 }
1544}
1545
1546
1547static ngx_uint_t
1548ngx_resolver_resend_empty(ngx_resolver_t *r)
1549{
1550 return ngx_queue_empty(&r->name_resend_queue)(&r->name_resend_queue == (&r->name_resend_queue
)->prev)
1551#if (NGX_HAVE_INET6)
1552 && ngx_queue_empty(&r->addr6_resend_queue)(&r->addr6_resend_queue == (&r->addr6_resend_queue
)->prev)
1553#endif
1554 && ngx_queue_empty(&r->addr_resend_queue)(&r->addr_resend_queue == (&r->addr_resend_queue
)->prev)
;
1555}
1556
1557
1558static void
1559ngx_resolver_udp_read(ngx_event_t *rev)
1560{
1561 ssize_t n;
1562 ngx_connection_t *c;
1563 ngx_resolver_connection_t *rec;
1564 u_char buf[NGX_RESOLVER_UDP_SIZE4096];
1565
1566 c = rev->data;
1567 rec = c->data;
1568
1569 do {
1570 n = ngx_udp_recvngx_io.udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE4096);
1571
1572 if (n < 0) {
1573 return;
1574 }
1575
1576 ngx_resolver_process_response(rec->resolver, buf, n, 0);
1577
1578 } while (rev->ready);
1579}
1580
1581
1582static void
1583ngx_resolver_tcp_write(ngx_event_t *wev)
1584{
1585 off_t sent;
1586 ssize_t n;
1587 ngx_buf_t *b;
1588 ngx_resolver_t *r;
1589 ngx_connection_t *c;
1590 ngx_resolver_connection_t *rec;
1591
1592 c = wev->data;
1593 rec = c->data;
1594 b = rec->write_buf;
1595 r = rec->resolver;
1596
1597 if (wev->timedout) {
1598 goto failed;
1599 }
1600
1601 sent = c->sent;
1602
1603 while (wev->ready && b->pos < b->last) {
1604 n = ngx_sendngx_io.send(c, b->pos, b->last - b->pos);
1605
1606 if (n == NGX_AGAIN-2) {
1607 break;
1608 }
1609
1610 if (n == NGX_ERROR-1) {
1611 goto failed;
1612 }
1613
1614 b->pos += n;
1615 }
1616
1617 if (b->pos != b->start) {
1618 b->last = ngx_movemem(b->start, b->pos, b->last - b->pos)(((u_char *) memmove(b->start, b->pos, b->last - b->
pos)) + (b->last - b->pos))
;
1619 b->pos = b->start;
1620 }
1621
1622 if (c->sent != sent) {
1623 ngx_add_timerngx_event_add_timer(wev, (ngx_msec_t) (r->tcp_timeout * 1000));
1624 }
1625
1626 if (ngx_handle_write_event(wev, 0) != NGX_OK0) {
1627 goto failed;
1628 }
1629
1630 return;
1631
1632failed:
1633
1634 ngx_close_connection(c);
1635 rec->tcp = NULL((void*)0);
1636}
1637
1638
1639static void
1640ngx_resolver_tcp_read(ngx_event_t *rev)
1641{
1642 u_char *p;
1643 size_t size;
1644 ssize_t n;
1645 u_short qlen;
1646 ngx_buf_t *b;
1647 ngx_resolver_t *r;
1648 ngx_connection_t *c;
1649 ngx_resolver_connection_t *rec;
1650
1651 c = rev->data;
1652 rec = c->data;
1653 b = rec->read_buf;
1654 r = rec->resolver;
1655
1656 while (rev->ready) {
1657 n = ngx_recvngx_io.recv(c, b->last, b->end - b->last);
1658
1659 if (n == NGX_AGAIN-2) {
1660 break;
1661 }
1662
1663 if (n == NGX_ERROR-1 || n == 0) {
1664 goto failed;
1665 }
1666
1667 b->last += n;
1668
1669 for ( ;; ) {
1670 p = b->pos;
1671 size = b->last - p;
1672
1673 if (size < 2) {
1674 break;
1675 }
1676
1677 qlen = (u_short) *p++ << 8;
1678 qlen += *p++;
1679
1680 if (size < (size_t) (2 + qlen)) {
1681 break;
1682 }
1683
1684 ngx_resolver_process_response(r, p, qlen, 1);
1685
1686 b->pos += 2 + qlen;
1687 }
1688
1689 if (b->pos != b->start) {
1690 b->last = ngx_movemem(b->start, b->pos, b->last - b->pos)(((u_char *) memmove(b->start, b->pos, b->last - b->
pos)) + (b->last - b->pos))
;
1691 b->pos = b->start;
1692 }
1693 }
1694
1695 if (ngx_handle_read_event(rev, 0) != NGX_OK0) {
1696 goto failed;
1697 }
1698
1699 return;
1700
1701failed:
1702
1703 ngx_close_connection(c);
1704 rec->tcp = NULL((void*)0);
1705}
1706
1707
1708static void
1709ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n,
1710 ngx_uint_t tcp)
1711{
1712 char *err;
1713 ngx_uint_t i, times, ident, qident, flags, code, nqs, nan, trunc,
1714 qtype, qclass;
1715#if (NGX_HAVE_INET6)
1716 ngx_uint_t qident6;
1717#endif
1718 ngx_queue_t *q;
1719 ngx_resolver_qs_t *qs;
1720 ngx_resolver_hdr_t *response;
1721 ngx_resolver_node_t *rn;
1722
1723 if (n < sizeof(ngx_resolver_hdr_t)) {
1724 goto short_response;
1725 }
1726
1727 response = (ngx_resolver_hdr_t *) buf;
1728
1729 ident = (response->ident_hi << 8) + response->ident_lo;
1730 flags = (response->flags_hi << 8) + response->flags_lo;
1731 nqs = (response->nqs_hi << 8) + response->nqs_lo;
1732 nan = (response->nan_hi << 8) + response->nan_lo;
1733 trunc = flags & 0x0200;
1734
1735 ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
1736 "resolver DNS response %ui fl:%04Xi %ui/%ui/%ud/%ud",
1737 ident, flags, nqs, nan,
1738 (response->nns_hi << 8) + response->nns_lo,
1739 (response->nar_hi << 8) + response->nar_lo);
1740
1741 /* response to a standard query */
1742 if ((flags & 0xf870) != 0x8000 || (trunc && tcp)) {
1743 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "invalid %s DNS response %ui fl:%04Xi"
, tcp ? "TCP" : "UDP", ident, flags)
1744 "invalid %s DNS response %ui fl:%04Xi",if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "invalid %s DNS response %ui fl:%04Xi"
, tcp ? "TCP" : "UDP", ident, flags)
1745 tcp ? "TCP" : "UDP", ident, flags)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "invalid %s DNS response %ui fl:%04Xi"
, tcp ? "TCP" : "UDP", ident, flags)
;
1746 return;
1747 }
1748
1749 code = flags & 0xf;
1750
1751 if (code == NGX_RESOLVE_FORMERR1) {
1752
1753 times = 0;
1754
1755 for (q = ngx_queue_head(&r->name_resend_queue)(&r->name_resend_queue)->next;
1756 q != ngx_queue_sentinel(&r->name_resend_queue)(&r->name_resend_queue) && times++ < 100;
1757 q = ngx_queue_next(q)(q)->next)
1758 {
1759 rn = ngx_queue_data(q, ngx_resolver_node_t, queue)(ngx_resolver_node_t *) ((u_char *) q - __builtin_offsetof(ngx_resolver_node_t
, queue))
;
1760 qident = (rn->query[0] << 8) + rn->query[1];
1761
1762 if (qident == ident) {
1763 goto dns_error_name;
1764 }
1765
1766#if (NGX_HAVE_INET6)
1767 if (rn->query6) {
1768 qident6 = (rn->query6[0] << 8) + rn->query6[1];
1769
1770 if (qident6 == ident) {
1771 goto dns_error_name;
1772 }
1773 }
1774#endif
1775 }
1776
1777 goto dns_error;
1778 }
1779
1780 if (code > NGX_RESOLVE_REFUSED5) {
1781 goto dns_error;
1782 }
1783
1784 if (nqs != 1) {
1785 err = "invalid number of questions in DNS response";
1786 goto done;
1787 }
1788
1789 i = sizeof(ngx_resolver_hdr_t);
1790
1791 while (i < (ngx_uint_t) n) {
1792 if (buf[i] == '\0') {
1793 goto found;
1794 }
1795
1796 i += 1 + buf[i];
1797 }
1798
1799 goto short_response;
1800
1801found:
1802
1803 if (i++ == sizeof(ngx_resolver_hdr_t)) {
1804 err = "zero-length domain name in DNS response";
1805 goto done;
1806 }
1807
1808 if (i + sizeof(ngx_resolver_qs_t) + nan * (2 + sizeof(ngx_resolver_an_t))
1809 > (ngx_uint_t) n)
1810 {
1811 goto short_response;
1812 }
1813
1814 qs = (ngx_resolver_qs_t *) &buf[i];
1815
1816 qtype = (qs->type_hi << 8) + qs->type_lo;
1817 qclass = (qs->class_hi << 8) + qs->class_lo;
1818
1819 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
1820 "resolver DNS response qt:%ui cl:%ui", qtype, qclass);
1821
1822 if (qclass != 1) {
1823 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unknown query class %ui in DNS response"
, qclass)
1824 "unknown query class %ui in DNS response", qclass)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unknown query class %ui in DNS response"
, qclass)
;
1825 return;
1826 }
1827
1828 switch (qtype) {
1829
1830 case NGX_RESOLVE_A1:
1831#if (NGX_HAVE_INET6)
1832 case NGX_RESOLVE_AAAA:
1833#endif
1834
1835 ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc,
1836 i + sizeof(ngx_resolver_qs_t));
1837
1838 break;
1839
1840 case NGX_RESOLVE_SRV33:
1841
1842 ngx_resolver_process_srv(r, buf, n, ident, code, nan, trunc,
1843 i + sizeof(ngx_resolver_qs_t));
1844
1845 break;
1846
1847 case NGX_RESOLVE_PTR12:
1848
1849 ngx_resolver_process_ptr(r, buf, n, ident, code, nan);
1850
1851 break;
1852
1853 default:
1854 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unknown query type %ui in DNS response"
, qtype)
1855 "unknown query type %ui in DNS response", qtype)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unknown query type %ui in DNS response"
, qtype)
;
1856 return;
1857 }
1858
1859 return;
1860
1861short_response:
1862
1863 err = "short DNS response";
1864
1865done:
1866
1867 ngx_log_error(r->log_level, r->log, 0, err)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, err)
;
1868
1869 return;
1870
1871dns_error_name:
1872
1873 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui, name:\"%*s\""
, code, ngx_resolver_strerror(code), ident, (size_t) rn->nlen
, rn->name)
1874 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui, name:\"%*s\""
, code, ngx_resolver_strerror(code), ident, (size_t) rn->nlen
, rn->name)
1875 code, ngx_resolver_strerror(code), ident,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui, name:\"%*s\""
, code, ngx_resolver_strerror(code), ident, (size_t) rn->nlen
, rn->name)
1876 (size_t) rn->nlen, rn->name)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui, name:\"%*s\""
, code, ngx_resolver_strerror(code), ident, (size_t) rn->nlen
, rn->name)
;
1877 return;
1878
1879dns_error:
1880
1881 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui"
, code, ngx_resolver_strerror(code), ident)
1882 "DNS error (%ui: %s), query id:%ui",if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui"
, code, ngx_resolver_strerror(code), ident)
1883 code, ngx_resolver_strerror(code), ident)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui"
, code, ngx_resolver_strerror(code), ident)
;
1884 return;
1885}
1886
1887
1888static void
1889ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
1890 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
1891 ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans)
1892{
1893 char *err;
1894 u_char *cname;
1895 size_t len;
1896 int32_t ttl;
1897 uint32_t hash;
1898 in_addr_t *addr;
1899 ngx_str_t name;
1900 ngx_uint_t type, class, qident, naddrs, a, i, j, start;
1901#if (NGX_HAVE_INET6)
1902 struct in6_addr *addr6;
1903#endif
1904 ngx_resolver_an_t *an;
1905 ngx_resolver_ctx_t *ctx, *next;
1906 ngx_resolver_node_t *rn;
1907 ngx_resolver_addr_t *addrs;
1908 ngx_resolver_connection_t *rec;
1909
1910 if (ngx_resolver_copy(r, &name, buf,
1911 buf + sizeof(ngx_resolver_hdr_t), buf + n)
1912 != NGX_OK0)
1913 {
1914 return;
1915 }
1916
1917 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);
1918
1919 hash = ngx_crc32_short(name.data, name.len);
1920
1921 /* lock name mutex */
1922
1923 rn = ngx_resolver_lookup_name(r, &name, hash);
1924
1925 if (rn == NULL((void*)0)) {
1926 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
1927 "unexpected response for %V", &name)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
;
1928 ngx_resolver_free(r, name.data);
1929 goto failed;
1930 }
1931
1932 switch (qtype) {
1933
1934#if (NGX_HAVE_INET6)
1935 case NGX_RESOLVE_AAAA:
1936
1937 if (rn->query6 == NULL((void*)0) || rn->naddrs6 != (u_short) -1) {
1938 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
1939 "unexpected response for %V", &name)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
;
1940 ngx_resolver_free(r, name.data);
1941 goto failed;
1942 }
1943
1944 if (trunc && rn->tcp6) {
1945 ngx_resolver_free(r, name.data);
1946 goto failed;
1947 }
1948
1949 qident = (rn->query6[0] << 8) + rn->query6[1];
1950
1951 break;
1952#endif
1953
1954 default: /* NGX_RESOLVE_A */
1955
1956 if (rn->query == NULL((void*)0) || rn->naddrs != (u_short) -1) {
1957 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
1958 "unexpected response for %V", &name)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
;
1959 ngx_resolver_free(r, name.data);
1960 goto failed;
1961 }
1962
1963 if (trunc && rn->tcp) {
1964 ngx_resolver_free(r, name.data);
1965 goto failed;
1966 }
1967
1968 qident = (rn->query[0] << 8) + rn->query[1];
1969 }
1970
1971 if (ident != qident) {
1972 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
1973 "wrong ident %ui response for %V, expect %ui",if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
1974 ident, &name, qident)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
;
1975 ngx_resolver_free(r, name.data);
1976 goto failed;
1977 }
1978
1979 ngx_resolver_free(r, name.data);
1980
1981 if (trunc) {
1982
1983 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
1984
1985 if (rn->waiting == NULL((void*)0)) {
1986 ngx_rbtree_delete(&r->name_rbtree, &rn->node);
1987 ngx_resolver_free_node(r, rn);
1988 goto next;
1989 }
1990
1991 rec = r->connections.elts;
1992 rec = &rec[rn->last_connection];
1993
1994 switch (qtype) {
1995
1996#if (NGX_HAVE_INET6)
1997 case NGX_RESOLVE_AAAA:
1998
1999 rn->tcp6 = 1;
2000
2001 (void) ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen);
2002
2003 break;
2004#endif
2005
2006 default: /* NGX_RESOLVE_A */
2007
2008 rn->tcp = 1;
2009
2010 (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen);
2011 }
2012
2013 rn->expire = ngx_time()ngx_cached_time->sec + r->resend_timeout;
2014
2015 ngx_queue_insert_head(&r->name_resend_queue, &rn->queue)(&rn->queue)->next = (&r->name_resend_queue)
->next; (&rn->queue)->next->prev = &rn->
queue; (&rn->queue)->prev = &r->name_resend_queue
; (&r->name_resend_queue)->next = &rn->queue
;
2016
2017 goto next;
2018 }
2019
2020 if (code == 0 && rn->code) {
2021 code = rn->code;
2022 }
2023
2024 if (code == 0 && nan == 0) {
2025
2026#if (NGX_HAVE_INET6)
2027 switch (qtype) {
2028
2029 case NGX_RESOLVE_AAAA:
2030
2031 rn->naddrs6 = 0;
2032
2033 if (rn->naddrs == (u_short) -1) {
2034 goto next;
2035 }
2036
2037 if (rn->naddrs) {
2038 goto export;
2039 }
2040
2041 break;
2042
2043 default: /* NGX_RESOLVE_A */
2044
2045 rn->naddrs = 0;
2046
2047 if (rn->naddrs6 == (u_short) -1) {
2048 goto next;
2049 }
2050
2051 if (rn->naddrs6) {
2052 goto export;
2053 }
2054 }
2055#endif
2056
2057 code = NGX_RESOLVE_NXDOMAIN3;
2058 }
2059
2060 if (code) {
2061
2062#if (NGX_HAVE_INET6)
2063 switch (qtype) {
2064
2065 case NGX_RESOLVE_AAAA:
2066
2067 rn->naddrs6 = 0;
2068
2069 if (rn->naddrs == (u_short) -1) {
2070 rn->code = (u_char) code;
2071 goto next;
2072 }
2073
2074 break;
2075
2076 default: /* NGX_RESOLVE_A */
2077
2078 rn->naddrs = 0;
2079
2080 if (rn->naddrs6 == (u_short) -1) {
2081 rn->code = (u_char) code;
2082 goto next;
2083 }
2084 }
2085#endif
2086
2087 next = rn->waiting;
2088 rn->waiting = NULL((void*)0);
2089
2090 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
2091
2092 ngx_rbtree_delete(&r->name_rbtree, &rn->node);
2093
2094 /* unlock name mutex */
2095
2096 while (next) {
2097 ctx = next;
2098 ctx->state = code;
2099 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
2100 next = ctx->next;
2101
2102 ctx->handler(ctx);
2103 }
2104
2105 ngx_resolver_free_node(r, rn);
2106
2107 return;
2108 }
2109
2110 i = ans;
2111 naddrs = 0;
2112 cname = NULL((void*)0);
2113
2114 for (a = 0; a < nan; a++) {
2115
2116 start = i;
2117
2118 while (i < n) {
2119
2120 if (buf[i] & 0xc0) {
2121 i += 2;
2122 goto found;
2123 }
2124
2125 if (buf[i] == 0) {
2126 i++;
2127 goto test_length;
2128 }
2129
2130 i += 1 + buf[i];
2131 }
2132
2133 goto short_response;
2134
2135 test_length:
2136
2137 if (i - start < 2) {
2138 err = "invalid name in DNS response";
2139 goto invalid;
2140 }
2141
2142 found:
2143
2144 if (i + sizeof(ngx_resolver_an_t) >= n) {
2145 goto short_response;
2146 }
2147
2148 an = (ngx_resolver_an_t *) &buf[i];
2149
2150 type = (an->type_hi << 8) + an->type_lo;
2151 class = (an->class_hi << 8) + an->class_lo;
2152 len = (an->len_hi << 8) + an->len_lo;
2153 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
2154 + (an->ttl[2] << 8) + (an->ttl[3]);
2155
2156 if (class != 1) {
2157 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR class %ui", class
)
2158 "unexpected RR class %ui", class)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR class %ui", class
)
;
2159 goto failed;
2160 }
2161
2162 if (ttl < 0) {
2163 ttl = 0;
2164 }
2165
2166 rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl)((rn->ttl > (uint32_t) ttl) ? ((uint32_t) ttl) : (rn->
ttl))
;
2167
2168 i += sizeof(ngx_resolver_an_t);
2169
2170 switch (type) {
2171
2172 case NGX_RESOLVE_A1:
2173
2174 if (qtype != NGX_RESOLVE_A1) {
2175 err = "unexpected A record in DNS response";
2176 goto invalid;
2177 }
2178
2179 if (len != 4) {
2180 err = "invalid A record in DNS response";
2181 goto invalid;
2182 }
2183
2184 if (i + 4 > n) {
2185 goto short_response;
2186 }
2187
2188 naddrs++;
2189
2190 break;
2191
2192#if (NGX_HAVE_INET6)
2193 case NGX_RESOLVE_AAAA:
2194
2195 if (qtype != NGX_RESOLVE_AAAA) {
2196 err = "unexpected AAAA record in DNS response";
2197 goto invalid;
2198 }
2199
2200 if (len != 16) {
2201 err = "invalid AAAA record in DNS response";
2202 goto invalid;
2203 }
2204
2205 if (i + 16 > n) {
2206 goto short_response;
2207 }
2208
2209 naddrs++;
2210
2211 break;
2212#endif
2213
2214 case NGX_RESOLVE_CNAME5:
2215
2216 cname = &buf[i];
2217
2218 break;
2219
2220 case NGX_RESOLVE_DNAME39:
2221
2222 break;
2223
2224 default:
2225
2226 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR type %ui", type
)
2227 "unexpected RR type %ui", type)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR type %ui", type
)
;
2228 }
2229
2230 i += len;
2231 }
2232
2233 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
2234 "resolver naddrs:%ui cname:%p ttl:%uD",
2235 naddrs, cname, rn->ttl);
2236
2237 if (naddrs) {
2238
2239 switch (qtype) {
2240
2241#if (NGX_HAVE_INET6)
2242 case NGX_RESOLVE_AAAA:
2243
2244 if (naddrs == 1) {
2245 addr6 = &rn->u6.addr6;
2246 rn->naddrs6 = 1;
2247
2248 } else {
2249 addr6 = ngx_resolver_alloc(r, naddrs * sizeof(struct in6_addr));
2250 if (addr6 == NULL((void*)0)) {
2251 goto failed;
2252 }
2253
2254 rn->u6.addrs6 = addr6;
2255 rn->naddrs6 = (u_short) naddrs;
2256 }
2257
2258#if (NGX_SUPPRESS_WARN1)
2259 addr = NULL((void*)0);
2260#endif
2261
2262 break;
2263#endif
2264
2265 default: /* NGX_RESOLVE_A */
2266
2267 if (naddrs == 1) {
2268 addr = &rn->u.addr;
2269 rn->naddrs = 1;
2270
2271 } else {
2272 addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
2273 if (addr == NULL((void*)0)) {
2274 goto failed;
2275 }
2276
2277 rn->u.addrs = addr;
2278 rn->naddrs = (u_short) naddrs;
2279 }
2280
2281#if (NGX_HAVE_INET6 && NGX_SUPPRESS_WARN1)
2282 addr6 = NULL((void*)0);
2283#endif
2284 }
2285
2286 j = 0;
2287 i = ans;
2288
2289 for (a = 0; a < nan; a++) {
2290
2291 for ( ;; ) {
2292
2293 if (buf[i] & 0xc0) {
2294 i += 2;
2295 break;
2296 }
2297
2298 if (buf[i] == 0) {
2299 i++;
2300 break;
2301 }
2302
2303 i += 1 + buf[i];
2304 }
2305
2306 an = (ngx_resolver_an_t *) &buf[i];
2307
2308 type = (an->type_hi << 8) + an->type_lo;
2309 len = (an->len_hi << 8) + an->len_lo;
2310
2311 i += sizeof(ngx_resolver_an_t);
2312
2313 if (type == NGX_RESOLVE_A1) {
2314
2315 addr[j] = htonl((buf[i] << 24) + (buf[i + 1] << 16)(__extension__ ({ unsigned int __v, __x = ((buf[i] << 24
) + (buf[i + 1] << 16) + (buf[i + 2] << 8) + (buf
[i + 3])); if (__builtin_constant_p (__x)) __v = ((((__x) &
0xff000000) >> 24) | (((__x) & 0x00ff0000) >>
8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff
) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (
__x)); __v; }))
2316 + (buf[i + 2] << 8) + (buf[i + 3]))(__extension__ ({ unsigned int __v, __x = ((buf[i] << 24
) + (buf[i + 1] << 16) + (buf[i + 2] << 8) + (buf
[i + 3])); if (__builtin_constant_p (__x)) __v = ((((__x) &
0xff000000) >> 24) | (((__x) & 0x00ff0000) >>
8) | (((__x) & 0x0000ff00) << 8) | (((__x) & 0x000000ff
) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (
__x)); __v; }))
;
2317
2318 if (++j == naddrs) {
2319
2320#if (NGX_HAVE_INET6)
2321 if (rn->naddrs6 == (u_short) -1) {
2322 goto next;
2323 }
2324#endif
2325
2326 break;
2327 }
2328 }
2329
2330#if (NGX_HAVE_INET6)
2331 else if (type == NGX_RESOLVE_AAAA) {
2332
2333 ngx_memcpy(addr6[j].s6_addr, &buf[i], 16)(void) memcpy(addr6[j].__in6_u.__u6_addr8, &buf[i], 16);
2334
2335 if (++j == naddrs) {
2336
2337 if (rn->naddrs == (u_short) -1) {
2338 goto next;
2339 }
2340
2341 break;
2342 }
2343 }
2344#endif
2345
2346 i += len;
2347 }
2348 }
2349
2350 switch (qtype) {
2351
2352#if (NGX_HAVE_INET6)
2353 case NGX_RESOLVE_AAAA:
2354
2355 if (rn->naddrs6 == (u_short) -1) {
2356 rn->naddrs6 = 0;
2357 }
2358
2359 break;
2360#endif
2361
2362 default: /* NGX_RESOLVE_A */
2363
2364 if (rn->naddrs == (u_short) -1) {
2365 rn->naddrs = 0;
2366 }
2367 }
2368
2369 if (rn->naddrs != (u_short) -1
2370#if (NGX_HAVE_INET6)
2371 && rn->naddrs6 != (u_short) -1
2372#endif
2373 && rn->naddrs
2374#if (NGX_HAVE_INET6)
2375 + rn->naddrs6
2376#endif
2377 > 0)
2378 {
2379
2380#if (NGX_HAVE_INET6)
2381 export:
2382#endif
2383
2384 naddrs = rn->naddrs;
2385#if (NGX_HAVE_INET6)
2386 naddrs += rn->naddrs6;
2387#endif
2388
2389 if (naddrs == 1 && rn->naddrs == 1) {
2390 addrs = NULL((void*)0);
2391
2392 } else {
2393 addrs = ngx_resolver_export(r, rn, 0);
2394 if (addrs == NULL((void*)0)) {
2395 goto failed;
2396 }
2397 }
2398
2399 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
2400
2401 rn->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : (time_t) rn->ttl);
2402 rn->expire = ngx_time()ngx_cached_time->sec + r->expire;
2403
2404 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue)(&rn->queue)->next = (&r->name_expire_queue)
->next; (&rn->queue)->next->prev = &rn->
queue; (&rn->queue)->prev = &r->name_expire_queue
; (&r->name_expire_queue)->next = &rn->queue
;
2405
2406 next = rn->waiting;
2407 rn->waiting = NULL((void*)0);
2408
2409 /* unlock name mutex */
2410
2411 while (next) {
2412 ctx = next;
2413 ctx->state = NGX_OK0;
2414 ctx->valid = rn->valid;
2415 ctx->naddrs = naddrs;
2416
2417 if (addrs == NULL((void*)0)) {
2418 ctx->addrs = &ctx->addr;
2419 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
2420 ctx->addr.socklen = sizeof(struct sockaddr_in);
2421 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in))(void) memset(&ctx->sin, 0, sizeof(struct sockaddr_in)
)
;
2422 ctx->sin.sin_family = AF_INET2;
2423 ctx->sin.sin_addr.s_addr = rn->u.addr;
2424
2425 } else {
2426 ctx->addrs = addrs;
2427 }
2428
2429 next = ctx->next;
2430
2431 ctx->handler(ctx);
2432 }
2433
2434 if (addrs != NULL((void*)0)) {
2435 ngx_resolver_free(r, addrs->sockaddr);
2436 ngx_resolver_free(r, addrs);
2437 }
2438
2439 ngx_resolver_free(r, rn->query);
2440 rn->query = NULL((void*)0);
2441#if (NGX_HAVE_INET6)
2442 rn->query6 = NULL((void*)0);
2443#endif
2444
2445 return;
2446 }
2447
2448 if (cname) {
2449
2450 /* CNAME only */
2451
2452 if (rn->naddrs == (u_short) -1
2453#if (NGX_HAVE_INET6)
2454 || rn->naddrs6 == (u_short) -1
2455#endif
2456 )
2457 {
2458 goto next;
2459 }
2460
2461 if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK0) {
2462 goto failed;
2463 }
2464
2465 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
2466 "resolver cname:\"%V\"", &name);
2467
2468 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
2469
2470 rn->cnlen = (u_short) name.len;
2471 rn->u.cname = name.data;
2472
2473 rn->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : (time_t) rn->ttl);
2474 rn->expire = ngx_time()ngx_cached_time->sec + r->expire;
2475
2476 ngx_queue_insert_head(&r->name_expire_queue, &rn->queue)(&rn->queue)->next = (&r->name_expire_queue)
->next; (&rn->queue)->next->prev = &rn->
queue; (&rn->queue)->prev = &r->name_expire_queue
; (&r->name_expire_queue)->next = &rn->queue
;
2477
2478 ngx_resolver_free(r, rn->query);
2479 rn->query = NULL((void*)0);
2480#if (NGX_HAVE_INET6)
2481 rn->query6 = NULL((void*)0);
2482#endif
2483
2484 ctx = rn->waiting;
2485 rn->waiting = NULL((void*)0);
2486
2487 if (ctx) {
2488
2489 if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION50) {
2490
2491 /* unlock name mutex */
2492
2493 do {
2494 ctx->state = NGX_RESOLVE_NXDOMAIN3;
2495 next = ctx->next;
2496
2497 ctx->handler(ctx);
2498
2499 ctx = next;
2500 } while (ctx);
2501
2502 return;
2503 }
2504
2505 for (next = ctx; next; next = next->next) {
2506 next->node = NULL((void*)0);
2507 }
2508
2509 (void) ngx_resolve_name_locked(r, ctx, &name);
2510 }
2511
2512 /* unlock name mutex */
2513
2514 return;
2515 }
2516
2517 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "no A or CNAME types in DNS response"
)
2518 "no A or CNAME types in DNS response")if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "no A or CNAME types in DNS response"
)
;
2519 return;
2520
2521short_response:
2522
2523 err = "short DNS response";
2524
2525invalid:
2526
2527 /* unlock name mutex */
2528
2529 ngx_log_error(r->log_level, r->log, 0, err)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, err)
;
2530
2531 return;
2532
2533failed:
2534
2535next:
2536
2537 /* unlock name mutex */
2538
2539 return;
2540}
2541
2542
2543static void
2544ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
2545 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
2546 ngx_uint_t trunc, ngx_uint_t ans)
2547{
2548 char *err;
2549 u_char *cname;
2550 size_t len;
2551 int32_t ttl;
2552 uint32_t hash;
2553 ngx_str_t name;
2554 ngx_uint_t type, qident, class, start, nsrvs, a, i, j;
2555 ngx_resolver_an_t *an;
2556 ngx_resolver_ctx_t *ctx, *next;
2557 ngx_resolver_srv_t *srvs;
2558 ngx_resolver_node_t *rn;
2559 ngx_resolver_connection_t *rec;
2560
2561 if (ngx_resolver_copy(r, &name, buf,
2562 buf + sizeof(ngx_resolver_hdr_t), buf + n)
2563 != NGX_OK0)
2564 {
2565 return;
2566 }
2567
2568 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);
2569
2570 hash = ngx_crc32_short(name.data, name.len);
2571
2572 rn = ngx_resolver_lookup_srv(r, &name, hash);
2573
2574 if (rn == NULL((void*)0) || rn->query == NULL((void*)0)) {
2575 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
2576 "unexpected response for %V", &name)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
;
2577 ngx_resolver_free(r, name.data);
2578 goto failed;
2579 }
2580
2581 if (trunc && rn->tcp) {
2582 ngx_resolver_free(r, name.data);
2583 goto failed;
2584 }
2585
2586 qident = (rn->query[0] << 8) + rn->query[1];
2587
2588 if (ident != qident) {
2589 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
2590 "wrong ident %ui response for %V, expect %ui",if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
2591 ident, &name, qident)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
;
2592 ngx_resolver_free(r, name.data);
2593 goto failed;
2594 }
2595
2596 ngx_resolver_free(r, name.data);
2597
2598 if (trunc) {
2599
2600 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
2601
2602 if (rn->waiting == NULL((void*)0)) {
2603 ngx_rbtree_delete(&r->srv_rbtree, &rn->node);
2604 ngx_resolver_free_node(r, rn);
2605 return;
2606 }
2607
2608 rec = r->connections.elts;
2609 rec = &rec[rn->last_connection];
2610
2611 rn->tcp = 1;
2612
2613 (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen);
2614
2615 rn->expire = ngx_time()ngx_cached_time->sec + r->resend_timeout;
2616
2617 ngx_queue_insert_head(&r->srv_resend_queue, &rn->queue)(&rn->queue)->next = (&r->srv_resend_queue)->
next; (&rn->queue)->next->prev = &rn->queue
; (&rn->queue)->prev = &r->srv_resend_queue;
(&r->srv_resend_queue)->next = &rn->queue
;
2618
2619 return;
2620 }
2621
2622 if (code == 0 && rn->code) {
2623 code = rn->code;
2624 }
2625
2626 if (code == 0 && nan == 0) {
2627 code = NGX_RESOLVE_NXDOMAIN3;
2628 }
2629
2630 if (code) {
2631 next = rn->waiting;
2632 rn->waiting = NULL((void*)0);
2633
2634 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
2635
2636 ngx_rbtree_delete(&r->srv_rbtree, &rn->node);
2637
2638 while (next) {
2639 ctx = next;
2640 ctx->state = code;
2641 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
2642 next = ctx->next;
2643
2644 ctx->handler(ctx);
2645 }
2646
2647 ngx_resolver_free_node(r, rn);
2648
2649 return;
2650 }
2651
2652 i = ans;
2653 nsrvs = 0;
2654 cname = NULL((void*)0);
2655
2656 for (a = 0; a < nan; a++) {
2657
2658 start = i;
2659
2660 while (i < n) {
2661
2662 if (buf[i] & 0xc0) {
2663 i += 2;
2664 goto found;
2665 }
2666
2667 if (buf[i] == 0) {
2668 i++;
2669 goto test_length;
2670 }
2671
2672 i += 1 + buf[i];
2673 }
2674
2675 goto short_response;
2676
2677 test_length:
2678
2679 if (i - start < 2) {
2680 err = "invalid name DNS response";
2681 goto invalid;
2682 }
2683
2684 found:
2685
2686 if (i + sizeof(ngx_resolver_an_t) >= n) {
2687 goto short_response;
2688 }
2689
2690 an = (ngx_resolver_an_t *) &buf[i];
2691
2692 type = (an->type_hi << 8) + an->type_lo;
2693 class = (an->class_hi << 8) + an->class_lo;
2694 len = (an->len_hi << 8) + an->len_lo;
2695 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
2696 + (an->ttl[2] << 8) + (an->ttl[3]);
2697
2698 if (class != 1) {
2699 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR class %ui", class
)
2700 "unexpected RR class %ui", class)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR class %ui", class
)
;
2701 goto failed;
2702 }
2703
2704 if (ttl < 0) {
2705 ttl = 0;
2706 }
2707
2708 rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl)((rn->ttl > (uint32_t) ttl) ? ((uint32_t) ttl) : (rn->
ttl))
;
2709
2710 i += sizeof(ngx_resolver_an_t);
2711
2712 switch (type) {
2713
2714 case NGX_RESOLVE_SRV33:
2715
2716 if (i + 6 > n) {
2717 goto short_response;
2718 }
2719
2720 if (ngx_resolver_copy(r, NULL((void*)0), buf, &buf[i + 6], buf + n)
2721 != NGX_OK0)
2722 {
2723 goto failed;
2724 }
2725
2726 nsrvs++;
2727
2728 break;
2729
2730 case NGX_RESOLVE_CNAME5:
2731
2732 cname = &buf[i];
2733
2734 break;
2735
2736 case NGX_RESOLVE_DNAME39:
2737
2738 break;
2739
2740 default:
2741
2742 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR type %ui", type
)
2743 "unexpected RR type %ui", type)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR type %ui", type
)
;
2744 }
2745
2746 i += len;
2747 }
2748
2749 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
2750 "resolver nsrvs:%ui cname:%p ttl:%uD",
2751 nsrvs, cname, rn->ttl);
2752
2753 if (nsrvs) {
2754
2755 srvs = ngx_resolver_calloc(r, nsrvs * sizeof(ngx_resolver_srv_t));
2756 if (srvs == NULL((void*)0)) {
2757 goto failed;
2758 }
2759
2760 rn->u.srvs = srvs;
2761 rn->nsrvs = (u_short) nsrvs;
2762
2763 j = 0;
2764 i = ans;
2765
2766 for (a = 0; a < nan; a++) {
2767
2768 for ( ;; ) {
2769
2770 if (buf[i] & 0xc0) {
2771 i += 2;
2772 break;
2773 }
2774
2775 if (buf[i] == 0) {
2776 i++;
2777 break;
2778 }
2779
2780 i += 1 + buf[i];
2781 }
2782
2783 an = (ngx_resolver_an_t *) &buf[i];
2784
2785 type = (an->type_hi << 8) + an->type_lo;
2786 len = (an->len_hi << 8) + an->len_lo;
2787
2788 i += sizeof(ngx_resolver_an_t);
2789
2790 if (type == NGX_RESOLVE_SRV33) {
2791
2792 srvs[j].priority = (buf[i] << 8) + buf[i + 1];
2793 srvs[j].weight = (buf[i + 2] << 8) + buf[i + 3];
2794
2795 if (srvs[j].weight == 0) {
2796 srvs[j].weight = 1;
2797 }
2798
2799 srvs[j].port = (buf[i + 4] << 8) + buf[i + 5];
2800
2801 if (ngx_resolver_copy(r, &srvs[j].name, buf, &buf[i + 6],
2802 buf + n)
2803 != NGX_OK0)
2804 {
2805 goto failed;
2806 }
2807
2808 j++;
2809 }
2810
2811 i += len;
2812 }
2813
2814 ngx_sort(srvs, nsrvs, sizeof(ngx_resolver_srv_t),
2815 ngx_resolver_cmp_srvs);
2816
2817 ngx_resolver_free(r, rn->query);
2818 rn->query = NULL((void*)0);
2819
2820 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
2821
2822 rn->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : (time_t) rn->ttl);
2823 rn->expire = ngx_time()ngx_cached_time->sec + r->expire;
2824
2825 ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue)(&rn->queue)->next = (&r->srv_expire_queue)->
next; (&rn->queue)->next->prev = &rn->queue
; (&rn->queue)->prev = &r->srv_expire_queue;
(&r->srv_expire_queue)->next = &rn->queue
;
2826
2827 next = rn->waiting;
2828 rn->waiting = NULL((void*)0);
2829
2830 while (next) {
2831 ctx = next;
2832 next = ctx->next;
2833
2834 ngx_resolver_resolve_srv_names(ctx, rn);
2835 }
2836
2837 return;
2838 }
2839
2840 rn->nsrvs = 0;
2841
2842 if (cname) {
2843
2844 /* CNAME only */
2845
2846 if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK0) {
2847 goto failed;
2848 }
2849
2850 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
2851 "resolver cname:\"%V\"", &name);
2852
2853 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
2854
2855 rn->cnlen = (u_short) name.len;
2856 rn->u.cname = name.data;
2857
2858 rn->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : (time_t) rn->ttl);
2859 rn->expire = ngx_time()ngx_cached_time->sec + r->expire;
2860
2861 ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue)(&rn->queue)->next = (&r->srv_expire_queue)->
next; (&rn->queue)->next->prev = &rn->queue
; (&rn->queue)->prev = &r->srv_expire_queue;
(&r->srv_expire_queue)->next = &rn->queue
;
2862
2863 ngx_resolver_free(r, rn->query);
2864 rn->query = NULL((void*)0);
2865#if (NGX_HAVE_INET6)
2866 rn->query6 = NULL((void*)0);
2867#endif
2868
2869 ctx = rn->waiting;
2870 rn->waiting = NULL((void*)0);
2871
2872 if (ctx) {
2873
2874 if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION50) {
2875
2876 /* unlock name mutex */
2877
2878 do {
2879 ctx->state = NGX_RESOLVE_NXDOMAIN3;
2880 next = ctx->next;
2881
2882 ctx->handler(ctx);
2883
2884 ctx = next;
2885 } while (ctx);
2886
2887 return;
2888 }
2889
2890 for (next = ctx; next; next = next->next) {
2891 next->node = NULL((void*)0);
2892 }
2893
2894 (void) ngx_resolve_name_locked(r, ctx, &name);
2895 }
2896
2897 /* unlock name mutex */
2898
2899 return;
2900 }
2901
2902 ngx_log_error(r->log_level, r->log, 0, "no SRV type in DNS response")if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "no SRV type in DNS response"
)
;
2903
2904 return;
2905
2906short_response:
2907
2908 err = "short DNS response";
2909
2910invalid:
2911
2912 /* unlock name mutex */
2913
2914 ngx_log_error(r->log_level, r->log, 0, err)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, err)
;
2915
2916 return;
2917
2918failed:
2919
2920 /* unlock name mutex */
2921
2922 return;
2923}
2924
2925
2926static void
2927ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, ngx_resolver_node_t *rn)
2928{
2929 ngx_uint_t i;
2930 ngx_resolver_t *r;
2931 ngx_resolver_ctx_t *cctx;
2932 ngx_resolver_srv_name_t *srvs;
2933
2934 r = ctx->resolver;
2935
2936 ctx->node = NULL((void*)0);
2937 ctx->state = NGX_OK0;
2938 ctx->valid = rn->valid;
2939 ctx->count = rn->nsrvs;
2940
2941 srvs = ngx_resolver_calloc(r, rn->nsrvs * sizeof(ngx_resolver_srv_name_t));
2942 if (srvs == NULL((void*)0)) {
2943 goto failed;
2944 }
2945
2946 ctx->srvs = srvs;
2947 ctx->nsrvs = rn->nsrvs;
2948
2949 for (i = 0; i < rn->nsrvs; i++) {
2950 srvs[i].name.data = ngx_resolver_alloc(r, rn->u.srvs[i].name.len);
2951 if (srvs[i].name.data == NULL((void*)0)) {
2952 goto failed;
2953 }
2954
2955 srvs[i].name.len = rn->u.srvs[i].name.len;
2956 ngx_memcpy(srvs[i].name.data, rn->u.srvs[i].name.data,(void) memcpy(srvs[i].name.data, rn->u.srvs[i].name.data, srvs
[i].name.len)
2957 srvs[i].name.len)(void) memcpy(srvs[i].name.data, rn->u.srvs[i].name.data, srvs
[i].name.len)
;
2958
2959 cctx = ngx_resolve_start(r, NULL((void*)0));
2960 if (cctx == NULL((void*)0)) {
2961 goto failed;
2962 }
2963
2964 cctx->name = srvs[i].name;
2965 cctx->handler = ngx_resolver_srv_names_handler;
2966 cctx->data = ctx;
2967 cctx->srvs = &srvs[i];
2968 cctx->timeout = 0;
2969
2970 srvs[i].priority = rn->u.srvs[i].priority;
2971 srvs[i].weight = rn->u.srvs[i].weight;
2972 srvs[i].port = rn->u.srvs[i].port;
2973 srvs[i].ctx = cctx;
2974
2975 if (ngx_resolve_name(cctx) == NGX_ERROR-1) {
2976 srvs[i].ctx = NULL((void*)0);
2977 goto failed;
2978 }
2979 }
2980
2981 return;
2982
2983failed:
2984
2985 ctx->state = NGX_ERROR-1;
2986 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
2987
2988 ctx->handler(ctx);
2989}
2990
2991
2992static void
2993ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx)
2994{
2995 ngx_uint_t i;
2996 ngx_addr_t *addrs;
2997 ngx_resolver_t *r;
2998 ngx_sockaddr_t *sockaddr;
2999 struct sockaddr_in *sin;
3000 ngx_resolver_ctx_t *ctx;
3001 ngx_resolver_srv_name_t *srv;
3002#if (NGX_HAVE_INET6)
3003 struct sockaddr_in6 *sin6;
3004#endif
3005
3006 r = cctx->resolver;
3007 ctx = cctx->data;
3008 srv = cctx->srvs;
3009
3010 ctx->count--;
3011
3012 srv->ctx = NULL((void*)0);
3013
3014 if (cctx->naddrs) {
3015
3016 ctx->valid = ngx_min(ctx->valid, cctx->valid)((ctx->valid > cctx->valid) ? (cctx->valid) : (ctx
->valid))
;
3017
3018 addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t));
3019 if (addrs == NULL((void*)0)) {
3020 ngx_resolve_name_done(cctx);
3021
3022 ctx->state = NGX_ERROR-1;
3023 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
3024
3025 ctx->handler(ctx);
3026 return;
3027 }
3028
3029 sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t));
3030 if (sockaddr == NULL((void*)0)) {
3031 ngx_resolver_free(r, addrs);
3032 ngx_resolve_name_done(cctx);
3033
3034 ctx->state = NGX_ERROR-1;
3035 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
3036
3037 ctx->handler(ctx);
3038 return;
3039 }
3040
3041 for (i = 0; i < cctx->naddrs; i++) {
3042 addrs[i].sockaddr = &sockaddr[i].sockaddr;
3043 addrs[i].socklen = cctx->addrs[i].socklen;
3044
3045 ngx_memcpy(&sockaddr[i], cctx->addrs[i].sockaddr,(void) memcpy(&sockaddr[i], cctx->addrs[i].sockaddr, addrs
[i].socklen)
3046 addrs[i].socklen)(void) memcpy(&sockaddr[i], cctx->addrs[i].sockaddr, addrs
[i].socklen)
;
3047
3048 switch (addrs[i].sockaddr->sa_family) {
3049#if (NGX_HAVE_INET6)
3050 case AF_INET610:
3051 sin6 = (struct sockaddr_in6 *) addrs[i].sockaddr;
3052 sin6->sin6_port = htons(srv->port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (srv->port); if (__builtin_constant_p (__x)) __v = (
(unsigned short int) ((((__x) >> 8) & 0xff) | (((__x
) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r"
(__v) : "0" (__x) : "cc"); __v; }))
;
3053 break;
3054#endif
3055 default: /* AF_INET */
3056 sin = (struct sockaddr_in *) addrs[i].sockaddr;
3057 sin->sin_port = htons(srv->port)(__extension__ ({ unsigned short int __v, __x = (unsigned short
int) (srv->port); if (__builtin_constant_p (__x)) __v = (
(unsigned short int) ((((__x) >> 8) & 0xff) | (((__x
) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r"
(__v) : "0" (__x) : "cc"); __v; }))
;
3058 }
3059 }
3060
3061 srv->addrs = addrs;
3062 srv->naddrs = cctx->naddrs;
3063 }
3064
3065 ngx_resolve_name_done(cctx);
3066
3067 if (ctx->count == 0) {
3068 ngx_resolver_report_srv(r, ctx);
3069 }
3070}
3071
3072
3073static void
3074ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
3075 ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
3076{
3077 char *err;
3078 size_t len;
3079 in_addr_t addr;
3080 int32_t ttl;
3081 ngx_int_t octet;
3082 ngx_str_t name;
3083 ngx_uint_t mask, type, class, qident, a, i, start;
3084 ngx_queue_t *expire_queue;
3085 ngx_rbtree_t *tree;
3086 ngx_resolver_an_t *an;
3087 ngx_resolver_ctx_t *ctx, *next;
3088 ngx_resolver_node_t *rn;
3089#if (NGX_HAVE_INET6)
3090 uint32_t hash;
3091 ngx_int_t digit;
3092 struct in6_addr addr6;
3093#endif
3094
3095 if (ngx_resolver_copy(r, &name, buf,
3096 buf + sizeof(ngx_resolver_hdr_t), buf + n)
3097 != NGX_OK0)
3098 {
3099 return;
3100 }
3101
3102 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);
3103
3104 /* AF_INET */
3105
3106 addr = 0;
3107 i = sizeof(ngx_resolver_hdr_t);
3108
3109 for (mask = 0; mask < 32; mask += 8) {
3110 len = buf[i++];
3111
3112 octet = ngx_atoi(&buf[i], len);
3113 if (octet == NGX_ERROR-1 || octet > 255) {
3114 goto invalid_in_addr_arpa;
3115 }
3116
3117 addr += octet << mask;
3118 i += len;
3119 }
3120
3121 if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
3122 i += sizeof("\7in-addr\4arpa");
3123
3124 /* lock addr mutex */
3125
3126 rn = ngx_resolver_lookup_addr(r, addr);
3127
3128 tree = &r->addr_rbtree;
3129 expire_queue = &r->addr_expire_queue;
3130
3131 goto valid;
3132 }
3133
3134invalid_in_addr_arpa:
3135
3136#if (NGX_HAVE_INET6)
3137
3138 i = sizeof(ngx_resolver_hdr_t);
3139
3140 for (octet = 15; octet >= 0; octet--) {
3141 if (buf[i++] != '\1') {
3142 goto invalid_ip6_arpa;
3143 }
3144
3145 digit = ngx_hextoi(&buf[i++], 1);
3146 if (digit == NGX_ERROR-1) {
3147 goto invalid_ip6_arpa;
3148 }
3149
3150 addr6.s6_addr__in6_u.__u6_addr8[octet] = (u_char) digit;
3151
3152 if (buf[i++] != '\1') {
3153 goto invalid_ip6_arpa;
3154 }
3155
3156 digit = ngx_hextoi(&buf[i++], 1);
3157 if (digit == NGX_ERROR-1) {
3158 goto invalid_ip6_arpa;
3159 }
3160
3161 addr6.s6_addr__in6_u.__u6_addr8[octet] += (u_char) (digit * 16);
3162 }
3163
3164 if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
3165 i += sizeof("\3ip6\4arpa");
3166
3167 /* lock addr mutex */
3168
3169 hash = ngx_crc32_short(addr6.s6_addr__in6_u.__u6_addr8, 16);
3170 rn = ngx_resolver_lookup_addr6(r, &addr6, hash);
3171
3172 tree = &r->addr6_rbtree;
3173 expire_queue = &r->addr6_expire_queue;
3174
3175 goto valid;
3176 }
3177
3178invalid_ip6_arpa:
3179#endif
3180
3181 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "invalid in-addr.arpa or ip6.arpa name in DNS response"
)
3182 "invalid in-addr.arpa or ip6.arpa name in DNS response")if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "invalid in-addr.arpa or ip6.arpa name in DNS response"
)
;
3183 ngx_resolver_free(r, name.data);
3184 return;
3185
3186valid:
3187
3188 if (rn == NULL((void*)0) || rn->query == NULL((void*)0)) {
3189 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
3190 "unexpected response for %V", &name)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected response for %V",
&name)
;
3191 ngx_resolver_free(r, name.data);
3192 goto failed;
3193 }
3194
3195 qident = (rn->query[0] << 8) + rn->query[1];
3196
3197 if (ident != qident) {
3198 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
3199 "wrong ident %ui response for %V, expect %ui",if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
3200 ident, &name, qident)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui"
, ident, &name, qident)
;
3201 ngx_resolver_free(r, name.data);
3202 goto failed;
3203 }
3204
3205 ngx_resolver_free(r, name.data);
3206
3207 if (code == 0 && nan == 0) {
3208 code = NGX_RESOLVE_NXDOMAIN3;
3209 }
3210
3211 if (code) {
3212 next = rn->waiting;
3213 rn->waiting = NULL((void*)0);
3214
3215 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
3216
3217 ngx_rbtree_delete(tree, &rn->node);
3218
3219 /* unlock addr mutex */
3220
3221 while (next) {
3222 ctx = next;
3223 ctx->state = code;
3224 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
3225 next = ctx->next;
3226
3227 ctx->handler(ctx);
3228 }
3229
3230 ngx_resolver_free_node(r, rn);
3231
3232 return;
3233 }
3234
3235 i += sizeof(ngx_resolver_qs_t);
3236
3237 for (a = 0; a < nan; a++) {
3238
3239 start = i;
3240
3241 while (i < n) {
3242
3243 if (buf[i] & 0xc0) {
3244 i += 2;
3245 goto found;
3246 }
3247
3248 if (buf[i] == 0) {
3249 i++;
3250 goto test_length;
3251 }
3252
3253 i += 1 + buf[i];
3254 }
3255
3256 goto short_response;
3257
3258 test_length:
3259
3260 if (i - start < 2) {
3261 err = "invalid name in DNS response";
3262 goto invalid;
3263 }
3264
3265 found:
3266
3267 if (i + sizeof(ngx_resolver_an_t) >= n) {
3268 goto short_response;
3269 }
3270
3271 an = (ngx_resolver_an_t *) &buf[i];
3272
3273 type = (an->type_hi << 8) + an->type_lo;
3274 class = (an->class_hi << 8) + an->class_lo;
3275 len = (an->len_hi << 8) + an->len_lo;
3276 ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
3277 + (an->ttl[2] << 8) + (an->ttl[3]);
3278
3279 if (class != 1) {
3280 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR class %ui", class
)
3281 "unexpected RR class %ui", class)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR class %ui", class
)
;
3282 goto failed;
3283 }
3284
3285 if (ttl < 0) {
3286 ttl = 0;
3287 }
3288
3289 ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
3290 "resolver qt:%ui cl:%ui len:%uz",
3291 type, class, len);
3292
3293 i += sizeof(ngx_resolver_an_t);
3294
3295 switch (type) {
3296
3297 case NGX_RESOLVE_PTR12:
3298
3299 goto ptr;
3300
3301 case NGX_RESOLVE_CNAME5:
3302
3303 break;
3304
3305 default:
3306
3307 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR type %ui", type
)
3308 "unexpected RR type %ui", type)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "unexpected RR type %ui", type
)
;
3309 }
3310
3311 i += len;
3312 }
3313
3314 /* unlock addr mutex */
3315
3316 ngx_log_error(r->log_level, r->log, 0,if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "no PTR type in DNS response"
)
3317 "no PTR type in DNS response")if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, "no PTR type in DNS response"
)
;
3318 return;
3319
3320ptr:
3321
3322 if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK0) {
3323 goto failed;
3324 }
3325
3326 ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);
3327
3328 if (name.len != (size_t) rn->nlen
3329 || ngx_strncmp(name.data, rn->name, name.len)(__extension__ (__builtin_constant_p (name.len) && ((
__builtin_constant_p ((const char *) name.data) && strlen
((const char *) name.data) < ((size_t) (name.len))) || (__builtin_constant_p
((const char *) rn->name) && strlen ((const char *
) rn->name) < ((size_t) (name.len)))) ? __extension__ (
{ size_t __s1_len, __s2_len; (__builtin_constant_p ((const char
*) name.data) && __builtin_constant_p ((const char *
) rn->name) && (__s1_len = strlen ((const char *) name
.data), __s2_len = strlen ((const char *) rn->name), (!((size_t
)(const void *)(((const char *) name.data) + 1) - (size_t)(const
void *)((const char *) name.data) == 1) || __s1_len >= 4)
&& (!((size_t)(const void *)(((const char *) rn->
name) + 1) - (size_t)(const void *)((const char *) rn->name
) == 1) || __s2_len >= 4)) ? __builtin_strcmp ((const char
*) name.data, (const char *) rn->name) : (__builtin_constant_p
((const char *) name.data) && ((size_t)(const void *
)(((const char *) name.data) + 1) - (size_t)(const void *)((const
char *) name.data) == 1) && (__s1_len = strlen ((const
char *) name.data), __s1_len < 4) ? (__builtin_constant_p
((const char *) rn->name) && ((size_t)(const void
*)(((const char *) rn->name) + 1) - (size_t)(const void *
)((const char *) rn->name) == 1) ? __builtin_strcmp ((const
char *) name.data, (const char *) rn->name) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) rn->name); int __result = (((const
unsigned char *) (const char *) ((const char *) name.data))[
0] - __s2[0]); if (__s1_len > 0 && __result == 0) {
__result = (((const unsigned char *) (const char *) ((const char
*) name.data))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((const char *) name.data))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((const char *) name.data))[3] - __s2
[3]); } } __result; }))) : (__builtin_constant_p ((const char
*) rn->name) && ((size_t)(const void *)(((const char
*) rn->name) + 1) - (size_t)(const void *)((const char *)
rn->name) == 1) && (__s2_len = strlen ((const char
*) rn->name), __s2_len < 4) ? (__builtin_constant_p ((
const char *) name.data) && ((size_t)(const void *)((
(const char *) name.data) + 1) - (size_t)(const void *)((const
char *) name.data) == 1) ? __builtin_strcmp ((const char *) name
.data, (const char *) rn->name) : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
((const char *) name.data); int __result = (((const unsigned
char *) (const char *) ((const char *) rn->name))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) rn
->name))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) rn->name))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ((const char *) rn->name))[3] - __s2[3]
); } } __result; })))) : __builtin_strcmp ((const char *) name
.data, (const char *) rn->name)))); }) : strncmp ((const char
*) name.data, (const char *) rn->name, name.len)))
!= 0)
3330 {
3331 if (rn->nlen) {
3332 ngx_resolver_free(r, rn->name);
3333 }
3334
3335 rn->nlen = (u_short) name.len;
3336 rn->name = name.data;
3337
3338 name.data = ngx_resolver_dup(r, rn->name, name.len);
3339 if (name.data == NULL((void*)0)) {
3340 goto failed;
3341 }
3342 }
3343
3344 ngx_queue_remove(&rn->queue)(&rn->queue)->next->prev = (&rn->queue)->
prev; (&rn->queue)->prev->next = (&rn->queue
)->next
;
3345
3346 rn->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : ttl);
3347 rn->expire = ngx_time()ngx_cached_time->sec + r->expire;
3348
3349 ngx_queue_insert_head(expire_queue, &rn->queue)(&rn->queue)->next = (expire_queue)->next; (&
rn->queue)->next->prev = &rn->queue; (&rn
->queue)->prev = expire_queue; (expire_queue)->next =
&rn->queue
;
3350
3351 next = rn->waiting;
3352 rn->waiting = NULL((void*)0);
3353
3354 /* unlock addr mutex */
3355
3356 while (next) {
3357 ctx = next;
3358 ctx->state = NGX_OK0;
3359 ctx->valid = rn->valid;
3360 ctx->name = name;
3361 next = ctx->next;
3362
3363 ctx->handler(ctx);
3364 }
3365
3366 ngx_resolver_free(r, name.data);
3367
3368 return;
3369
3370short_response:
3371
3372 err = "short DNS response";
3373
3374invalid:
3375
3376 /* unlock addr mutex */
3377
3378 ngx_log_error(r->log_level, r->log, 0, err)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, err)
;
3379
3380 return;
3381
3382failed:
3383
3384 /* unlock addr mutex */
3385
3386 return;
3387}
3388
3389
3390static ngx_resolver_node_t *
3391ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
3392{
3393 ngx_int_t rc;
3394 ngx_rbtree_node_t *node, *sentinel;
3395 ngx_resolver_node_t *rn;
3396
3397 node = r->name_rbtree.root;
3398 sentinel = r->name_rbtree.sentinel;
3399
3400 while (node != sentinel) {
3401
3402 if (hash < node->key) {
3403 node = node->left;
3404 continue;
3405 }
3406
3407 if (hash > node->key) {
3408 node = node->right;
3409 continue;
3410 }
3411
3412 /* hash == node->key */
3413
3414 rn = ngx_resolver_node(node)(ngx_resolver_node_t *) ((u_char *) (node) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3415
3416 rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
3417
3418 if (rc == 0) {
3419 return rn;
3420 }
3421
3422 node = (rc < 0) ? node->left : node->right;
3423 }
3424
3425 /* not found */
3426
3427 return NULL((void*)0);
3428}
3429
3430
3431static ngx_resolver_node_t *
3432ngx_resolver_lookup_srv(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
3433{
3434 ngx_int_t rc;
3435 ngx_rbtree_node_t *node, *sentinel;
3436 ngx_resolver_node_t *rn;
3437
3438 node = r->srv_rbtree.root;
3439 sentinel = r->srv_rbtree.sentinel;
3440
3441 while (node != sentinel) {
3442
3443 if (hash < node->key) {
3444 node = node->left;
3445 continue;
3446 }
3447
3448 if (hash > node->key) {
3449 node = node->right;
3450 continue;
3451 }
3452
3453 /* hash == node->key */
3454
3455 rn = ngx_resolver_node(node)(ngx_resolver_node_t *) ((u_char *) (node) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3456
3457 rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);
3458
3459 if (rc == 0) {
3460 return rn;
3461 }
3462
3463 node = (rc < 0) ? node->left : node->right;
3464 }
3465
3466 /* not found */
3467
3468 return NULL((void*)0);
3469}
3470
3471
3472static ngx_resolver_node_t *
3473ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
3474{
3475 ngx_rbtree_node_t *node, *sentinel;
3476
3477 node = r->addr_rbtree.root;
3478 sentinel = r->addr_rbtree.sentinel;
3479
3480 while (node != sentinel) {
3481
3482 if (addr < node->key) {
3483 node = node->left;
3484 continue;
3485 }
3486
3487 if (addr > node->key) {
3488 node = node->right;
3489 continue;
3490 }
3491
3492 /* addr == node->key */
3493
3494 return ngx_resolver_node(node)(ngx_resolver_node_t *) ((u_char *) (node) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3495 }
3496
3497 /* not found */
3498
3499 return NULL((void*)0);
3500}
3501
3502
3503#if (NGX_HAVE_INET6)
3504
3505static ngx_resolver_node_t *
3506ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
3507 uint32_t hash)
3508{
3509 ngx_int_t rc;
3510 ngx_rbtree_node_t *node, *sentinel;
3511 ngx_resolver_node_t *rn;
3512
3513 node = r->addr6_rbtree.root;
3514 sentinel = r->addr6_rbtree.sentinel;
3515
3516 while (node != sentinel) {
3517
3518 if (hash < node->key) {
3519 node = node->left;
3520 continue;
3521 }
3522
3523 if (hash > node->key) {
3524 node = node->right;
3525 continue;
3526 }
3527
3528 /* hash == node->key */
3529
3530 rn = ngx_resolver_node(node)(ngx_resolver_node_t *) ((u_char *) (node) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3531
3532 rc = ngx_memcmp(addr, &rn->addr6, 16)memcmp((const char *) addr, (const char *) &rn->addr6,
16)
;
3533
3534 if (rc == 0) {
3535 return rn;
3536 }
3537
3538 node = (rc < 0) ? node->left : node->right;
3539 }
3540
3541 /* not found */
3542
3543 return NULL((void*)0);
3544}
3545
3546#endif
3547
3548
3549static void
3550ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
3551 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
3552{
3553 ngx_rbtree_node_t **p;
3554 ngx_resolver_node_t *rn, *rn_temp;
3555
3556 for ( ;; ) {
3557
3558 if (node->key < temp->key) {
3559
3560 p = &temp->left;
3561
3562 } else if (node->key > temp->key) {
3563
3564 p = &temp->right;
3565
3566 } else { /* node->key == temp->key */
3567
3568 rn = ngx_resolver_node(node)(ngx_resolver_node_t *) ((u_char *) (node) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3569 rn_temp = ngx_resolver_node(temp)(ngx_resolver_node_t *) ((u_char *) (temp) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3570
3571 p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen)
3572 < 0) ? &temp->left : &temp->right;
3573 }
3574
3575 if (*p == sentinel) {
3576 break;
3577 }
3578
3579 temp = *p;
3580 }
3581
3582 *p = node;
3583 node->parent = temp;
3584 node->left = sentinel;
3585 node->right = sentinel;
3586 ngx_rbt_red(node)((node)->color = 1);
3587}
3588
3589
3590#if (NGX_HAVE_INET6)
3591
3592static void
3593ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
3594 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
3595{
3596 ngx_rbtree_node_t **p;
3597 ngx_resolver_node_t *rn, *rn_temp;
3598
3599 for ( ;; ) {
3600
3601 if (node->key < temp->key) {
3602
3603 p = &temp->left;
3604
3605 } else if (node->key > temp->key) {
3606
3607 p = &temp->right;
3608
3609 } else { /* node->key == temp->key */
3610
3611 rn = ngx_resolver_node(node)(ngx_resolver_node_t *) ((u_char *) (node) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3612 rn_temp = ngx_resolver_node(temp)(ngx_resolver_node_t *) ((u_char *) (temp) - __builtin_offsetof
(ngx_resolver_node_t, node))
;
3613
3614 p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)memcmp((const char *) &rn->addr6, (const char *) &
rn_temp->addr6, 16)
3615 < 0) ? &temp->left : &temp->right;
3616 }
3617
3618 if (*p == sentinel) {
3619 break;
3620 }
3621
3622 temp = *p;
3623 }
3624
3625 *p = node;
3626 node->parent = temp;
3627 node->left = sentinel;
3628 node->right = sentinel;
3629 ngx_rbt_red(node)((node)->color = 1);
3630}
3631
3632#endif
3633
3634
3635static ngx_int_t
3636ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3637 ngx_str_t *name)
3638{
3639 u_char *p, *s;
3640 size_t len, nlen;
3641 ngx_uint_t ident;
3642 ngx_resolver_qs_t *qs;
3643 ngx_resolver_hdr_t *query;
3644
3645 nlen = name->len ? (1 + name->len + 1) : 1;
3646
3647 len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
3648
3649#if (NGX_HAVE_INET6)
3650 p = ngx_resolver_alloc(r, r->ipv6 ? len * 2 : len);
3651#else
3652 p = ngx_resolver_alloc(r, len);
3653#endif
3654 if (p == NULL((void*)0)) {
3655 return NGX_ERROR-1;
3656 }
3657
3658 rn->qlen = (u_short) len;
3659 rn->query = p;
3660
3661#if (NGX_HAVE_INET6)
3662 if (r->ipv6) {
3663 rn->query6 = p + len;
3664 }
3665#endif
3666
3667 query = (ngx_resolver_hdr_t *) p;
3668
3669 ident = ngx_randomrandom();
3670
3671 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
3672 "resolve: \"%V\" A %i", name, ident & 0xffff);
3673
3674 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
3675 query->ident_lo = (u_char) (ident & 0xff);
3676
3677 /* recursion query */
3678 query->flags_hi = 1; query->flags_lo = 0;
3679
3680 /* one question */
3681 query->nqs_hi = 0; query->nqs_lo = 1;
3682 query->nan_hi = 0; query->nan_lo = 0;
3683 query->nns_hi = 0; query->nns_lo = 0;
3684 query->nar_hi = 0; query->nar_lo = 0;
3685
3686 p += sizeof(ngx_resolver_hdr_t) + nlen;
3687
3688 qs = (ngx_resolver_qs_t *) p;
3689
3690 /* query type */
3691 qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_A1;
3692
3693 /* IN query class */
3694 qs->class_hi = 0; qs->class_lo = 1;
3695
3696 /* convert "www.example.com" to "\3www\7example\3com\0" */
3697
3698 len = 0;
3699 p--;
3700 *p-- = '\0';
3701
3702 if (name->len == 0) {
3703 return NGX_DECLINED-5;
3704 }
3705
3706 for (s = name->data + name->len - 1; s >= name->data; s--) {
3707 if (*s != '.') {
3708 *p = *s;
3709 len++;
3710
3711 } else {
3712 if (len == 0 || len > 255) {
3713 return NGX_DECLINED-5;
3714 }
3715
3716 *p = (u_char) len;
3717 len = 0;
3718 }
3719
3720 p--;
3721 }
3722
3723 if (len == 0 || len > 255) {
3724 return NGX_DECLINED-5;
3725 }
3726
3727 *p = (u_char) len;
3728
3729#if (NGX_HAVE_INET6)
3730 if (!r->ipv6) {
3731 return NGX_OK0;
3732 }
3733
3734 p = rn->query6;
3735
3736 ngx_memcpy(p, rn->query, rn->qlen)(void) memcpy(p, rn->query, rn->qlen);
3737
3738 query = (ngx_resolver_hdr_t *) p;
3739
3740 ident = ngx_randomrandom();
3741
3742 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
3743 "resolve: \"%V\" AAAA %i", name, ident & 0xffff);
3744
3745 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
3746 query->ident_lo = (u_char) (ident & 0xff);
3747
3748 p += sizeof(ngx_resolver_hdr_t) + nlen;
3749
3750 qs = (ngx_resolver_qs_t *) p;
3751
3752 qs->type_lo = NGX_RESOLVE_AAAA;
3753#endif
3754
3755 return NGX_OK0;
3756}
3757
3758
3759static ngx_int_t
3760ngx_resolver_create_srv_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3761 ngx_str_t *name)
3762{
3763 u_char *p, *s;
3764 size_t len, nlen;
3765 ngx_uint_t ident;
3766 ngx_resolver_qs_t *qs;
3767 ngx_resolver_hdr_t *query;
3768
3769 nlen = name->len ? (1 + name->len + 1) : 1;
3770
3771 len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);
3772
3773 p = ngx_resolver_alloc(r, len);
3774 if (p == NULL((void*)0)) {
3775 return NGX_ERROR-1;
3776 }
3777
3778 rn->qlen = (u_short) len;
3779 rn->query = p;
3780
3781 query = (ngx_resolver_hdr_t *) p;
3782
3783 ident = ngx_randomrandom();
3784
3785 ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
3786 "resolve: \"%V\" SRV %i", name, ident & 0xffff);
3787
3788 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
3789 query->ident_lo = (u_char) (ident & 0xff);
3790
3791 /* recursion query */
3792 query->flags_hi = 1; query->flags_lo = 0;
3793
3794 /* one question */
3795 query->nqs_hi = 0; query->nqs_lo = 1;
3796 query->nan_hi = 0; query->nan_lo = 0;
3797 query->nns_hi = 0; query->nns_lo = 0;
3798 query->nar_hi = 0; query->nar_lo = 0;
3799
3800 p += sizeof(ngx_resolver_hdr_t) + nlen;
3801
3802 qs = (ngx_resolver_qs_t *) p;
3803
3804 /* query type */
3805 qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_SRV33;
3806
3807 /* IN query class */
3808 qs->class_hi = 0; qs->class_lo = 1;
3809
3810 /* converts "www.example.com" to "\3www\7example\3com\0" */
3811
3812 len = 0;
3813 p--;
3814 *p-- = '\0';
3815
3816 if (name->len == 0) {
3817 return NGX_DECLINED-5;
3818 }
3819
3820 for (s = name->data + name->len - 1; s >= name->data; s--) {
3821 if (*s != '.') {
3822 *p = *s;
3823 len++;
3824
3825 } else {
3826 if (len == 0 || len > 255) {
3827 return NGX_DECLINED-5;
3828 }
3829
3830 *p = (u_char) len;
3831 len = 0;
3832 }
3833
3834 p--;
3835 }
3836
3837 if (len == 0 || len > 255) {
3838 return NGX_DECLINED-5;
3839 }
3840
3841 *p = (u_char) len;
3842
3843 return NGX_OK0;
3844}
3845
3846
3847static ngx_int_t
3848ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
3849 ngx_resolver_addr_t *addr)
3850{
3851 u_char *p, *d;
3852 size_t len;
3853 in_addr_t inaddr;
3854 ngx_int_t n;
3855 ngx_uint_t ident;
3856 ngx_resolver_hdr_t *query;
3857 struct sockaddr_in *sin;
3858#if (NGX_HAVE_INET6)
3859 struct sockaddr_in6 *sin6;
3860#endif
3861
3862 switch (addr->sockaddr->sa_family) {
3863
3864#if (NGX_HAVE_INET6)
3865 case AF_INET610:
3866 len = sizeof(ngx_resolver_hdr_t)
3867 + 64 + sizeof(".ip6.arpa.") - 1
3868 + sizeof(ngx_resolver_qs_t);
3869
3870 break;
3871#endif
3872
3873 default: /* AF_INET */
3874 len = sizeof(ngx_resolver_hdr_t)
3875 + sizeof(".255.255.255.255.in-addr.arpa.") - 1
3876 + sizeof(ngx_resolver_qs_t);
3877 }
3878
3879 p = ngx_resolver_alloc(r, len);
3880 if (p == NULL((void*)0)) {
3881 return NGX_ERROR-1;
3882 }
3883
3884 rn->query = p;
3885 query = (ngx_resolver_hdr_t *) p;
3886
3887 ident = ngx_randomrandom();
3888
3889 query->ident_hi = (u_char) ((ident >> 8) & 0xff);
3890 query->ident_lo = (u_char) (ident & 0xff);
3891
3892 /* recursion query */
3893 query->flags_hi = 1; query->flags_lo = 0;
3894
3895 /* one question */
3896 query->nqs_hi = 0; query->nqs_lo = 1;
3897 query->nan_hi = 0; query->nan_lo = 0;
3898 query->nns_hi = 0; query->nns_lo = 0;
3899 query->nar_hi = 0; query->nar_lo = 0;
3900
3901 p += sizeof(ngx_resolver_hdr_t);
3902
3903 switch (addr->sockaddr->sa_family) {
3904
3905#if (NGX_HAVE_INET6)
3906 case AF_INET610:
3907 sin6 = (struct sockaddr_in6 *) addr->sockaddr;
3908
3909 for (n = 15; n >= 0; n--) {
3910 p = ngx_sprintf(p, "\1%xd\1%xd",
3911 sin6->sin6_addr.s6_addr__in6_u.__u6_addr8[n] & 0xf,
3912 (sin6->sin6_addr.s6_addr__in6_u.__u6_addr8[n] >> 4) & 0xf);
3913 }
3914
3915 p = ngx_cpymem(p, "\3ip6\4arpa\0", 10)(((u_char *) memcpy(p, "\3ip6\4arpa\0", 10)) + (10));
3916
3917 break;
3918#endif
3919
3920 default: /* AF_INET */
3921
3922 sin = (struct sockaddr_in *) addr->sockaddr;
3923 inaddr = ntohl(sin->sin_addr.s_addr)(__extension__ ({ unsigned int __v, __x = (sin->sin_addr.s_addr
); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
3924
3925 for (n = 0; n < 32; n += 8) {
3926 d = ngx_sprintf(&p[1], "%ud", (inaddr >> n) & 0xff);
3927 *p = (u_char) (d - &p[1]);
3928 p = d;
3929 }
3930
3931 p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14)(((u_char *) memcpy(p, "\7in-addr\4arpa\0", 14)) + (14));
3932 }
3933
3934 /* query type "PTR", IN query class */
3935 p = ngx_cpymem(p, "\0\14\0\1", 4)(((u_char *) memcpy(p, "\0\14\0\1", 4)) + (4));
3936
3937 rn->qlen = (u_short) (p - rn->query);
3938
3939 return NGX_OK0;
3940}
3941
3942
3943static ngx_int_t
3944ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
3945 u_char *last)
3946{
3947 char *err;
3948 u_char *p, *dst;
3949 ssize_t len;
3950 ngx_uint_t i, n;
3951
3952 p = src;
3953 len = -1;
3954
3955 /*
3956 * compression pointers allow to create endless loop, so we set limit;
3957 * 128 pointers should be enough to store 255-byte name
3958 */
3959
3960 for (i = 0; i < 128; i++) {
3961 n = *p++;
3962
3963 if (n == 0) {
3964 goto done;
3965 }
3966
3967 if (n & 0xc0) {
3968 n = ((n & 0x3f) << 8) + *p;
3969 p = &buf[n];
3970
3971 } else {
3972 len += 1 + n;
3973 p = &p[n];
3974 }
3975
3976 if (p >= last) {
3977 err = "name is out of response";
3978 goto invalid;
3979 }
3980 }
3981
3982 err = "compression pointers loop";
3983
3984invalid:
3985
3986 ngx_log_error(r->log_level, r->log, 0, err)if ((r->log)->log_level >= r->log_level) ngx_log_error_core
(r->log_level, r->log, 0, err)
;
3987
3988 return NGX_ERROR-1;
3989
3990done:
3991
3992 if (name == NULL((void*)0)) {
3993 return NGX_OK0;
3994 }
3995
3996 if (len == -1) {
3997 ngx_str_null(name)(name)->len = 0; (name)->data = ((void*)0);
3998 return NGX_OK0;
3999 }
4000
4001 dst = ngx_resolver_alloc(r, len);
4002 if (dst == NULL((void*)0)) {
4003 return NGX_ERROR-1;
4004 }
4005
4006 name->data = dst;
4007
4008 n = *src++;
4009
4010 for ( ;; ) {
4011 if (n & 0xc0) {
4012 n = ((n & 0x3f) << 8) + *src;
4013 src = &buf[n];
4014
4015 n = *src++;
4016
4017 } else {
4018 ngx_strlow(dst, src, n);
4019 dst += n;
4020 src += n;
4021
4022 n = *src++;
4023
4024 if (n != 0) {
4025 *dst++ = '.';
4026 }
4027 }
4028
4029 if (n == 0) {
4030 name->len = dst - name->data;
4031 return NGX_OK0;
4032 }
4033 }
4034}
4035
4036
4037static void
4038ngx_resolver_timeout_handler(ngx_event_t *ev)
4039{
4040 ngx_resolver_ctx_t *ctx;
4041
4042 ctx = ev->data;
4043
4044 ctx->state = NGX_RESOLVE_TIMEDOUT110;
4045
4046 ctx->handler(ctx);
4047}
4048
4049
4050static void
4051ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
4052{
4053 ngx_uint_t i;
4054
4055 /* lock alloc mutex */
4056
4057 if (rn->query) {
4058 ngx_resolver_free_locked(r, rn->query);
4059 }
4060
4061 if (rn->name) {
4062 ngx_resolver_free_locked(r, rn->name);
4063 }
4064
4065 if (rn->cnlen) {
4066 ngx_resolver_free_locked(r, rn->u.cname);
4067 }
4068
4069 if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
4070 ngx_resolver_free_locked(r, rn->u.addrs);
4071 }
4072
4073#if (NGX_HAVE_INET6)
4074 if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
4075 ngx_resolver_free_locked(r, rn->u6.addrs6);
4076 }
4077#endif
4078
4079 if (rn->nsrvs) {
4080 for (i = 0; i < rn->nsrvs; i++) {
4081 if (rn->u.srvs[i].name.data) {
4082 ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
4083 }
4084 }
4085
4086 ngx_resolver_free_locked(r, rn->u.srvs);
4087 }
4088
4089 ngx_resolver_free_locked(r, rn);
4090
4091 /* unlock alloc mutex */
4092}
4093
4094
4095static void *
4096ngx_resolver_alloc(ngx_resolver_t *r, size_t size)
4097{
4098 u_char *p;
4099
4100 /* lock alloc mutex */
4101
4102 p = ngx_alloc(size, r->log);
4103
4104 /* unlock alloc mutex */
4105
4106 return p;
4107}
4108
4109
4110static void *
4111ngx_resolver_calloc(ngx_resolver_t *r, size_t size)
4112{
4113 u_char *p;
4114
4115 p = ngx_resolver_alloc(r, size);
4116
4117 if (p) {
4118 ngx_memzero(p, size)(void) memset(p, 0, size);
4119 }
4120
4121 return p;
4122}
4123
4124
4125static void
4126ngx_resolver_free(ngx_resolver_t *r, void *p)
4127{
4128 /* lock alloc mutex */
4129
4130 ngx_freefree(p);
4131
4132 /* unlock alloc mutex */
4133}
4134
4135
4136static void
4137ngx_resolver_free_locked(ngx_resolver_t *r, void *p)
4138{
4139 ngx_freefree(p);
4140}
4141
4142
4143static void *
4144ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
4145{
4146 void *dst;
4147
4148 dst = ngx_resolver_alloc(r, size);
4149
4150 if (dst == NULL((void*)0)) {
4151 return dst;
4152 }
4153
4154 ngx_memcpy(dst, src, size)(void) memcpy(dst, src, size);
4155
4156 return dst;
4157}
4158
4159
4160static ngx_resolver_addr_t *
4161ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
4162 ngx_uint_t rotate)
4163{
4164 ngx_uint_t d, i, j, n;
4165 in_addr_t *addr;
4166 ngx_sockaddr_t *sockaddr;
4167 struct sockaddr_in *sin;
4168 ngx_resolver_addr_t *dst;
4169#if (NGX_HAVE_INET6)
4170 struct in6_addr *addr6;
4171 struct sockaddr_in6 *sin6;
4172#endif
4173
4174 n = rn->naddrs;
4175#if (NGX_HAVE_INET6)
4176 n += rn->naddrs6;
4177#endif
4178
4179 dst = ngx_resolver_calloc(r, n * sizeof(ngx_resolver_addr_t));
4180 if (dst == NULL((void*)0)) {
4181 return NULL((void*)0);
4182 }
4183
4184 sockaddr = ngx_resolver_calloc(r, n * sizeof(ngx_sockaddr_t));
4185 if (sockaddr == NULL((void*)0)) {
4186 ngx_resolver_free(r, dst);
4187 return NULL((void*)0);
4188 }
4189
4190 i = 0;
4191 d = rotate ? ngx_randomrandom() % n : 0;
4192
4193 if (rn->naddrs) {
4194 j = rotate ? ngx_randomrandom() % rn->naddrs : 0;
4195
4196 addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;
4197
4198 do {
4199 sin = &sockaddr[d].sockaddr_in;
4200 sin->sin_family = AF_INET2;
4201 sin->sin_addr.s_addr = addr[j++];
4202 dst[d].sockaddr = (struct sockaddr *) sin;
4203 dst[d++].socklen = sizeof(struct sockaddr_in);
4204
4205 if (d == n) {
4206 d = 0;
4207 }
4208
4209 if (j == rn->naddrs) {
4210 j = 0;
4211 }
4212 } while (++i < rn->naddrs);
4213 }
4214
4215#if (NGX_HAVE_INET6)
4216 if (rn->naddrs6) {
4217 j = rotate ? ngx_randomrandom() % rn->naddrs6 : 0;
4218
4219 addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;
4220
4221 do {
4222 sin6 = &sockaddr[d].sockaddr_in6;
4223 sin6->sin6_family = AF_INET610;
4224 ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16)(void) memcpy(sin6->sin6_addr.__in6_u.__u6_addr8, addr6[j++
].__in6_u.__u6_addr8, 16)
;
4225 dst[d].sockaddr = (struct sockaddr *) sin6;
4226 dst[d++].socklen = sizeof(struct sockaddr_in6);
4227
4228 if (d == n) {
4229 d = 0;
4230 }
4231
4232 if (j == rn->naddrs6) {
4233 j = 0;
4234 }
4235 } while (++i < n);
4236 }
4237#endif
4238
4239 return dst;
4240}
4241
4242
4243static void
4244ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
4245{
4246 ngx_uint_t naddrs, nsrvs, nw, i, j, k, l, m, n, w;
4247 ngx_resolver_addr_t *addrs;
4248 ngx_resolver_srv_name_t *srvs;
4249
4250 naddrs = 0;
4251
4252 for (i = 0; i < ctx->nsrvs; i++) {
4253 naddrs += ctx->srvs[i].naddrs;
4254 }
4255
4256 if (naddrs == 0) {
4257 ctx->state = NGX_RESOLVE_NXDOMAIN3;
4258 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
4259
4260 ctx->handler(ctx);
4261 return;
4262 }
4263
4264 addrs = ngx_resolver_calloc(r, naddrs * sizeof(ngx_resolver_addr_t));
4265 if (addrs == NULL((void*)0)) {
4266 ctx->state = NGX_ERROR-1;
4267 ctx->valid = ngx_time()ngx_cached_time->sec + (r->valid ? r->valid : 10);
4268
4269 ctx->handler(ctx);
4270 return;
4271 }
4272
4273 srvs = ctx->srvs;
4274 nsrvs = ctx->nsrvs;
4275
4276 i = 0;
4277 n = 0;
4278
4279 do {
4280 nw = 0;
4281
4282 for (j = i; j < nsrvs; j++) {
4283 if (srvs[j].priority != srvs[i].priority) {
4284 break;
4285 }
4286
4287 nw += srvs[j].naddrs * srvs[j].weight;
4288 }
4289
4290 if (nw == 0) {
4291 goto next_srv;
4292 }
4293
4294 w = ngx_randomrandom() % nw;
4295
4296 for (k = i; k < j; k++) {
4297 if (w < srvs[k].naddrs * srvs[k].weight) {
4298 break;
4299 }
4300
4301 w -= srvs[k].naddrs * srvs[k].weight;
4302 }
4303
4304 for (l = i; l < j; l++) {
4305
4306 for (m = 0; m < srvs[k].naddrs; m++) {
4307 addrs[n].socklen = srvs[k].addrs[m].socklen;
4308 addrs[n].sockaddr = srvs[k].addrs[m].sockaddr;
4309 addrs[n].name = srvs[k].name;
4310 addrs[n].priority = srvs[k].priority;
4311 addrs[n].weight = srvs[k].weight;
4312 n++;
4313 }
4314
4315 if (++k == j) {
4316 k = i;
4317 }
4318 }
4319
4320next_srv:
4321
4322 i = j;
4323
4324 } while (i < ctx->nsrvs);
4325
4326 ctx->state = NGX_OK0;
4327 ctx->addrs = addrs;
4328 ctx->naddrs = naddrs;
4329
4330 ctx->handler(ctx);
4331
4332 ngx_resolver_free(r, addrs);
4333}
4334
4335
4336char *
4337ngx_resolver_strerror(ngx_int_t err)
4338{
4339 static char *errors[] = {
4340 "Format error", /* FORMERR */
4341 "Server failure", /* SERVFAIL */
4342 "Host not found", /* NXDOMAIN */
4343 "Unimplemented", /* NOTIMP */
4344 "Operation refused" /* REFUSED */
4345 };
4346
4347 if (err > 0 && err < 6) {
4348 return errors[err - 1];
4349 }
4350
4351 if (err == NGX_RESOLVE_TIMEDOUT110) {
4352 return "Operation timed out";
4353 }
4354
4355 return "Unknown error";
4356}
4357
4358
4359static u_char *
4360ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
4361{
4362 u_char *p;
4363 ngx_resolver_connection_t *rec;
4364
4365 p = buf;
4366
4367 if (log->action) {
4368 p = ngx_snprintf(buf, len, " while %s", log->action);
4369 len -= p - buf;
4370 }
4371
4372 rec = log->data;
4373
4374 if (rec) {
4375 p = ngx_snprintf(p, len, ", resolver: %V", &rec->server);
4376 }
4377
4378 return p;
4379}
4380
4381
4382ngx_int_t
4383ngx_udp_connect(ngx_resolver_connection_t *rec)
4384{
4385 int rc;
4386 ngx_int_t event;
4387 ngx_event_t *rev, *wev;
4388 ngx_socket_t s;
4389 ngx_connection_t *c;
4390
4391 s = ngx_socketsocket(rec->sockaddr->sa_family, SOCK_DGRAMSOCK_DGRAM, 0);
4392
4393 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "UDP socket %d", s);
4394
4395 if (s == (ngx_socket_t) -1) {
4396 ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "socket()" " failed"
)
4397 ngx_socket_n " failed")if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "socket()" " failed"
)
;
4398 return NGX_ERROR-1;
4399 }
4400
4401 c = ngx_get_connection(s, &rec->log);
4402
4403 if (c == NULL((void*)0)) {
4404 if (ngx_close_socketclose(s) == -1) {
4405 ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "close() socket"
"failed")
4406 ngx_close_socket_n "failed")if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "close() socket"
"failed")
;
4407 }
4408
4409 return NGX_ERROR-1;
4410 }
4411
4412 if (ngx_nonblocking(s) == -1) {
4413 ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "ioctl(FIONBIO)"
" failed")
4414 ngx_nonblocking_n " failed")if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "ioctl(FIONBIO)"
" failed")
;
4415
4416 goto failed;
4417 }
4418
4419 rev = c->read;
4420 wev = c->write;
4421
4422 rev->log = &rec->log;
4423 wev->log = &rec->log;
4424
4425 rec->udp = c;
4426
4427 c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1)__sync_fetch_and_add(ngx_connection_counter, 1);
4428
4429 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0,
4430 "connect to %V, fd:%d #%uA", &rec->server, s, c->number);
4431
4432 rc = connect(s, rec->sockaddr, rec->socklen);
4433
4434 /* TODO: iocp */
4435
4436 if (rc == -1) {
4437 ngx_log_error(NGX_LOG_CRIT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 3) ngx_log_error_core
(3, &rec->log, (*__errno_location ()), "connect() failed"
)
4438 "connect() failed")if ((&rec->log)->log_level >= 3) ngx_log_error_core
(3, &rec->log, (*__errno_location ()), "connect() failed"
)
;
4439
4440 goto failed;
4441 }
4442
4443 /* UDP sockets are always ready to write */
4444 wev->ready = 1;
4445
4446 event = (ngx_event_flags & NGX_USE_CLEAR_EVENT0x00000004) ?
4447 /* kqueue, epoll */ NGX_CLEAR_EVENTEPOLLET:
4448 /* select, poll, /dev/poll */ NGX_LEVEL_EVENT0;
4449 /* eventport event type has no meaning: oneshot only */
4450
4451 if (ngx_add_eventngx_event_actions.add(rev, NGX_READ_EVENT(EPOLLIN|EPOLLRDHUP), event) != NGX_OK0) {
4452 goto failed;
4453 }
4454
4455 return NGX_OK0;
4456
4457failed:
4458
4459 ngx_close_connection(c);
4460 rec->udp = NULL((void*)0);
4461
4462 return NGX_ERROR-1;
4463}
4464
4465
4466ngx_int_t
4467ngx_tcp_connect(ngx_resolver_connection_t *rec)
4468{
4469 int rc;
4470 ngx_int_t event;
4471 ngx_err_t err;
4472 ngx_uint_t level;
4473 ngx_socket_t s;
4474 ngx_event_t *rev, *wev;
4475 ngx_connection_t *c;
4476
4477 s = ngx_socketsocket(rec->sockaddr->sa_family, SOCK_STREAMSOCK_STREAM, 0);
4478
4479 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "TCP socket %d", s);
4480
4481 if (s == (ngx_socket_t) -1) {
4482 ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "socket()" " failed"
)
4483 ngx_socket_n " failed")if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "socket()" " failed"
)
;
4484 return NGX_ERROR-1;
4485 }
4486
4487 c = ngx_get_connection(s, &rec->log);
4488
4489 if (c == NULL((void*)0)) {
4490 if (ngx_close_socketclose(s) == -1) {
4491 ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "close() socket"
"failed")
4492 ngx_close_socket_n "failed")if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "close() socket"
"failed")
;
4493 }
4494
4495 return NGX_ERROR-1;
4496 }
4497
4498 if (ngx_nonblocking(s) == -1) {
4499 ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "ioctl(FIONBIO)"
" failed")
4500 ngx_nonblocking_n " failed")if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "ioctl(FIONBIO)"
" failed")
;
4501
4502 goto failed;
4503 }
4504
4505 rev = c->read;
4506 wev = c->write;
4507
4508 rev->log = &rec->log;
4509 wev->log = &rec->log;
4510
4511 rec->tcp = c;
4512
4513 c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1)__sync_fetch_and_add(ngx_connection_counter, 1);
4514
4515 if (ngx_add_connngx_event_actions.add_conn) {
4516 if (ngx_add_connngx_event_actions.add_conn(c) == NGX_ERROR-1) {
4517 goto failed;
4518 }
4519 }
4520
4521 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0,
4522 "connect to %V, fd:%d #%uA", &rec->server, s, c->number);
4523
4524 rc = connect(s, rec->sockaddr, rec->socklen);
4525
4526 if (rc == -1) {
4527 err = ngx_socket_errno(*__errno_location ());
4528
4529
4530 if (err != NGX_EINPROGRESS115
4531#if (NGX_WIN32)
4532 /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
4533 && err != NGX_EAGAIN11
4534#endif
4535 )
4536 {
4537 if (err == NGX_ECONNREFUSED111
4538#if (NGX_LINUX1)
4539 /*
4540 * Linux returns EAGAIN instead of ECONNREFUSED
4541 * for unix sockets if listen queue is full
4542 */
4543 || err == NGX_EAGAIN11
4544#endif
4545 || err == NGX_ECONNRESET104
4546 || err == NGX_ENETDOWN100
4547 || err == NGX_ENETUNREACH101
4548 || err == NGX_EHOSTDOWN112
4549 || err == NGX_EHOSTUNREACH113)
4550 {
4551 level = NGX_LOG_ERR4;
4552
4553 } else {
4554 level = NGX_LOG_CRIT3;
4555 }
4556
4557 ngx_log_error(level, c->log, err, "connect() to %V failed",if ((c->log)->log_level >= level) ngx_log_error_core
(level, c->log, err, "connect() to %V failed", &rec->
server)
4558 &rec->server)if ((c->log)->log_level >= level) ngx_log_error_core
(level, c->log, err, "connect() to %V failed", &rec->
server)
;
4559
4560 ngx_close_connection(c);
4561 rec->tcp = NULL((void*)0);
4562
4563 return NGX_ERROR-1;
4564 }
4565 }
4566
4567 if (ngx_add_connngx_event_actions.add_conn) {
4568 if (rc == -1) {
4569
4570 /* NGX_EINPROGRESS */
4571
4572 return NGX_AGAIN-2;
4573 }
4574
4575 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected");
4576
4577 wev->ready = 1;
4578
4579 return NGX_OK0;
4580 }
4581
4582 if (ngx_event_flags & NGX_USE_IOCP_EVENT0x00000200) {
4583
4584 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, ngx_socket_errno,
4585 "connect(): %d", rc);
4586
4587 if (ngx_blocking(s) == -1) {
4588 ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "ioctl(!FIONBIO)"
" failed")
4589 ngx_blocking_n " failed")if ((&rec->log)->log_level >= 2) ngx_log_error_core
(2, &rec->log, (*__errno_location ()), "ioctl(!FIONBIO)"
" failed")
;
4590 goto failed;
4591 }
4592
4593 /*
4594 * FreeBSD's aio allows to post an operation on non-connected socket.
4595 * NT does not support it.
4596 *
4597 * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT
4598 */
4599
4600 rev->ready = 1;
4601 wev->ready = 1;
4602
4603 return NGX_OK0;
4604 }
4605
4606 if (ngx_event_flags & NGX_USE_CLEAR_EVENT0x00000004) {
4607
4608 /* kqueue */
4609
4610 event = NGX_CLEAR_EVENTEPOLLET;
4611
4612 } else {
4613
4614 /* select, poll, /dev/poll */
4615
4616 event = NGX_LEVEL_EVENT0;
4617 }
4618
4619 if (ngx_add_eventngx_event_actions.add(rev, NGX_READ_EVENT(EPOLLIN|EPOLLRDHUP), event) != NGX_OK0) {
4620 goto failed;
4621 }
4622
4623 if (rc == -1) {
4624
4625 /* NGX_EINPROGRESS */
4626
4627 if (ngx_add_eventngx_event_actions.add(wev, NGX_WRITE_EVENTEPOLLOUT, event) != NGX_OK0) {
4628 goto failed;
4629 }
4630
4631 return NGX_AGAIN-2;
4632 }
4633
4634 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected");
4635
4636 wev->ready = 1;
4637
4638 return NGX_OK0;
4639
4640failed:
4641
4642 ngx_close_connection(c);
4643 rec->tcp = NULL((void*)0);
4644
4645 return NGX_ERROR-1;
4646}
4647
4648
4649static ngx_int_t
4650ngx_resolver_cmp_srvs(const void *one, const void *two)
4651{
4652 ngx_int_t p1, p2;
4653 ngx_resolver_srv_t *first, *second;
4654
4655 first = (ngx_resolver_srv_t *) one;
4656 second = (ngx_resolver_srv_t *) two;
4657
4658 p1 = first->priority;
4659 p2 = second->priority;
4660
4661 return p1 - p2;
4662}