3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
13 #define NGX_RESOLVER_UDP_SIZE 4096
29 } ngx_resolver_query_t
;
51 ngx_int_t
ngx_udp_connect(ngx_udp_connection_t
*uc
);
54 static void ngx_resolver_cleanup(void *data
);
55 static void ngx_resolver_cleanup_tree(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
);
56 static ngx_int_t
ngx_resolve_name_locked(ngx_resolver_t
*r
,
57 ngx_resolver_ctx_t
*ctx
);
58 static void ngx_resolver_expire(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
,
60 static ngx_int_t
ngx_resolver_send_query(ngx_resolver_t
*r
,
61 ngx_resolver_node_t
*rn
);
62 static ngx_int_t
ngx_resolver_create_name_query(ngx_resolver_node_t
*rn
,
63 ngx_resolver_ctx_t
*ctx
);
64 static ngx_int_t
ngx_resolver_create_addr_query(ngx_resolver_node_t
*rn
,
65 ngx_resolver_ctx_t
*ctx
);
66 static void ngx_resolver_resend_handler(ngx_event_t
*ev
);
67 static time_t ngx_resolver_resend(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
,
69 static void ngx_resolver_read_response(ngx_event_t
*rev
);
70 static void ngx_resolver_process_response(ngx_resolver_t
*r
, u_char
*buf
,
72 static void ngx_resolver_process_a(ngx_resolver_t
*r
, u_char
*buf
, size_t n
,
73 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
, ngx_uint_t ans
);
74 static void ngx_resolver_process_ptr(ngx_resolver_t
*r
, u_char
*buf
, size_t n
,
75 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
);
76 static ngx_resolver_node_t
*ngx_resolver_lookup_name(ngx_resolver_t
*r
,
77 ngx_str_t
*name
, uint32_t hash
);
78 static ngx_resolver_node_t
*ngx_resolver_lookup_addr(ngx_resolver_t
*r
,
80 static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
81 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
);
82 static ngx_int_t
ngx_resolver_copy(ngx_resolver_t
*r
, ngx_str_t
*name
,
83 u_char
*buf
, u_char
*src
, u_char
*last
);
84 static void ngx_resolver_timeout_handler(ngx_event_t
*ev
);
85 static void ngx_resolver_free_node(ngx_resolver_t
*r
, ngx_resolver_node_t
*rn
);
86 static void *ngx_resolver_alloc(ngx_resolver_t
*r
, size_t size
);
87 static void *ngx_resolver_calloc(ngx_resolver_t
*r
, size_t size
);
88 static void ngx_resolver_free(ngx_resolver_t
*r
, void *p
);
89 static void ngx_resolver_free_locked(ngx_resolver_t
*r
, void *p
);
90 static void *ngx_resolver_dup(ngx_resolver_t
*r
, void *src
, size_t size
);
91 static in_addr_t
*ngx_resolver_rotate(ngx_resolver_t
*r
, in_addr_t
*src
,
93 static u_char
*ngx_resolver_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
);
97 ngx_resolver_create(ngx_conf_t
*cf
, ngx_str_t
*names
, ngx_uint_t n
)
103 ngx_pool_cleanup_t
*cln
;
104 ngx_udp_connection_t
*uc
;
106 cln
= ngx_pool_cleanup_add(cf
->pool
, 0);
111 cln
->handler
= ngx_resolver_cleanup
;
113 r
= ngx_calloc(sizeof(ngx_resolver_t
), cf
->log
);
120 r
->event
= ngx_calloc(sizeof(ngx_event_t
), cf
->log
);
121 if (r
->event
== NULL
) {
125 ngx_rbtree_init(&r
->name_rbtree
, &r
->name_sentinel
,
126 ngx_resolver_rbtree_insert_value
);
128 ngx_rbtree_init(&r
->addr_rbtree
, &r
->addr_sentinel
,
129 ngx_rbtree_insert_value
);
131 ngx_queue_init(&r
->name_resend_queue
);
132 ngx_queue_init(&r
->addr_resend_queue
);
134 ngx_queue_init(&r
->name_expire_queue
);
135 ngx_queue_init(&r
->addr_expire_queue
);
137 r
->event
->handler
= ngx_resolver_resend_handler
;
139 r
->event
->log
= &cf
->cycle
->new_log
;
142 r
->resend_timeout
= 5;
146 r
->log
= &cf
->cycle
->new_log
;
147 r
->log_level
= NGX_LOG_ERR
;
150 if (ngx_array_init(&r
->udp_connections
, cf
->pool
, n
,
151 sizeof(ngx_udp_connection_t
))
158 for (i
= 0; i
< n
; i
++) {
159 if (ngx_strncmp(names
[i
].data
, "valid=", 6) == 0) {
160 s
.len
= names
[i
].len
- 6;
161 s
.data
= names
[i
].data
+ 6;
163 r
->valid
= ngx_parse_time(&s
, 1);
165 if (r
->valid
== (time_t) NGX_ERROR
) {
166 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
167 "invalid parameter: %V", &names
[i
]);
174 ngx_memzero(&u
, sizeof(ngx_url_t
));
179 if (ngx_parse_url(cf
->pool
, &u
) != NGX_OK
) {
181 ngx_conf_log_error(NGX_LOG_EMERG
, cf
, 0,
182 "%s in resolver \"%V\"",
189 uc
= ngx_array_push_n(&r
->udp_connections
, u
.naddrs
);
194 ngx_memzero(uc
, u
.naddrs
* sizeof(ngx_udp_connection_t
));
196 for (j
= 0; j
< u
.naddrs
; j
++) {
197 uc
[j
].sockaddr
= u
.addrs
[j
].sockaddr
;
198 uc
[j
].socklen
= u
.addrs
[j
].socklen
;
199 uc
[j
].server
= u
.addrs
[j
].name
;
208 ngx_resolver_cleanup(void *data
)
210 ngx_resolver_t
*r
= data
;
213 ngx_udp_connection_t
*uc
;
216 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, ngx_cycle
->log
, 0,
219 ngx_resolver_cleanup_tree(r
, &r
->name_rbtree
);
221 ngx_resolver_cleanup_tree(r
, &r
->addr_rbtree
);
228 uc
= r
->udp_connections
.elts
;
230 for (i
= 0; i
< r
->udp_connections
.nelts
; i
++) {
231 if (uc
[i
].connection
) {
232 ngx_close_connection(uc
[i
].connection
);
242 ngx_resolver_cleanup_tree(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
)
244 ngx_resolver_ctx_t
*ctx
, *next
;
245 ngx_resolver_node_t
*rn
;
247 while (tree
->root
!= tree
->sentinel
) {
249 rn
= (ngx_resolver_node_t
*) ngx_rbtree_min(tree
->root
, tree
->sentinel
);
251 ngx_queue_remove(&rn
->queue
);
253 for (ctx
= rn
->waiting
; ctx
; ctx
= next
) {
257 ngx_resolver_free(r
, ctx
->event
);
260 ngx_resolver_free(r
, ctx
);
263 ngx_rbtree_delete(tree
, &rn
->node
);
265 ngx_resolver_free_node(r
, rn
);
271 ngx_resolve_start(ngx_resolver_t
*r
, ngx_resolver_ctx_t
*temp
)
274 ngx_resolver_ctx_t
*ctx
;
277 addr
= ngx_inet_addr(temp
->name
.data
, temp
->name
.len
);
279 if (addr
!= INADDR_NONE
) {
281 temp
->state
= NGX_OK
;
283 temp
->addrs
= &temp
->addr
;
291 if (r
->udp_connections
.nelts
== 0) {
292 return NGX_NO_RESOLVER
;
295 ctx
= ngx_resolver_calloc(r
, sizeof(ngx_resolver_ctx_t
));
306 ngx_resolve_name(ngx_resolver_ctx_t
*ctx
)
313 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
314 "resolve: \"%V\"", &ctx
->name
);
321 /* lock name mutex */
323 rc
= ngx_resolve_name_locked(r
, ctx
);
329 /* unlock name mutex */
331 if (rc
== NGX_AGAIN
) {
338 ngx_resolver_free(r
, ctx
->event
);
341 ngx_resolver_free(r
, ctx
);
348 ngx_resolve_name_done(ngx_resolver_ctx_t
*ctx
)
352 ngx_resolver_ctx_t
*w
, **p
;
353 ngx_resolver_node_t
*rn
;
357 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
358 "resolve name done: %i", ctx
->state
);
364 if (ctx
->event
&& ctx
->event
->timer_set
) {
365 ngx_del_timer(ctx
->event
);
368 /* lock name mutex */
370 if (ctx
->state
== NGX_AGAIN
|| ctx
->state
== NGX_RESOLVE_TIMEDOUT
) {
372 hash
= ngx_crc32_short(ctx
->name
.data
, ctx
->name
.len
);
374 rn
= ngx_resolver_lookup_name(r
, &ctx
->name
, hash
);
392 ngx_log_error(NGX_LOG_ALERT
, r
->log
, 0,
393 "could not cancel %V resolving", &ctx
->name
);
398 ngx_resolver_expire(r
, &r
->name_rbtree
, &r
->name_expire_queue
);
400 /* unlock name mutex */
402 /* lock alloc mutex */
405 ngx_resolver_free_locked(r
, ctx
->event
);
408 ngx_resolver_free_locked(r
, ctx
);
410 /* unlock alloc mutex */
414 /* NGX_RESOLVE_A only */
417 ngx_resolve_name_locked(ngx_resolver_t
*r
, ngx_resolver_ctx_t
*ctx
)
420 in_addr_t addr
, *addrs
;
423 ngx_resolver_ctx_t
*next
;
424 ngx_resolver_node_t
*rn
;
426 hash
= ngx_crc32_short(ctx
->name
.data
, ctx
->name
.len
);
428 rn
= ngx_resolver_lookup_name(r
, &ctx
->name
, hash
);
432 if (rn
->valid
>= ngx_time()) {
434 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolve cached");
436 ngx_queue_remove(&rn
->queue
);
438 rn
->expire
= ngx_time() + r
->expire
;
440 ngx_queue_insert_head(&r
->name_expire_queue
, &rn
->queue
);
446 /* NGX_RESOLVE_A answer */
450 addrs
= ngx_resolver_rotate(r
, rn
->u
.addrs
, naddrs
);
460 ctx
->next
= rn
->waiting
;
463 /* unlock name mutex */
467 ctx
->naddrs
= naddrs
;
468 ctx
->addrs
= (naddrs
== 1) ? &ctx
->addr
: addrs
;
478 ngx_resolver_free(r
, addrs
);
484 /* NGX_RESOLVE_CNAME */
486 if (ctx
->recursion
++ < NGX_RESOLVER_MAX_RECURSION
) {
488 ctx
->name
.len
= rn
->cnlen
;
489 ctx
->name
.data
= rn
->u
.cname
;
491 return ngx_resolve_name_locked(r
, ctx
);
494 ctx
->next
= rn
->waiting
;
497 /* unlock name mutex */
500 ctx
->state
= NGX_RESOLVE_NXDOMAIN
;
513 ctx
->next
= rn
->waiting
;
515 ctx
->state
= NGX_AGAIN
;
520 ngx_queue_remove(&rn
->queue
);
522 /* lock alloc mutex */
525 ngx_resolver_free_locked(r
, rn
->query
);
530 ngx_resolver_free_locked(r
, rn
->u
.cname
);
533 if (rn
->naddrs
> 1) {
534 ngx_resolver_free_locked(r
, rn
->u
.addrs
);
537 /* unlock alloc mutex */
541 rn
= ngx_resolver_alloc(r
, sizeof(ngx_resolver_node_t
));
546 rn
->name
= ngx_resolver_dup(r
, ctx
->name
.data
, ctx
->name
.len
);
547 if (rn
->name
== NULL
) {
548 ngx_resolver_free(r
, rn
);
553 rn
->nlen
= (u_short
) ctx
->name
.len
;
556 ngx_rbtree_insert(&r
->name_rbtree
, &rn
->node
);
559 rc
= ngx_resolver_create_name_query(rn
, ctx
);
561 if (rc
== NGX_ERROR
) {
565 if (rc
== NGX_DECLINED
) {
566 ngx_rbtree_delete(&r
->name_rbtree
, &rn
->node
);
568 ngx_resolver_free(r
, rn
->query
);
569 ngx_resolver_free(r
, rn
->name
);
570 ngx_resolver_free(r
, rn
);
572 ctx
->state
= NGX_RESOLVE_NXDOMAIN
;
578 if (ngx_resolver_send_query(r
, rn
) != NGX_OK
) {
582 if (ctx
->event
== NULL
) {
583 ctx
->event
= ngx_resolver_calloc(r
, sizeof(ngx_event_t
));
584 if (ctx
->event
== NULL
) {
588 ctx
->event
->handler
= ngx_resolver_timeout_handler
;
589 ctx
->event
->data
= ctx
;
590 ctx
->event
->log
= r
->log
;
593 ngx_add_timer(ctx
->event
, ctx
->timeout
);
596 if (ngx_queue_empty(&r
->name_resend_queue
)) {
597 ngx_add_timer(r
->event
, (ngx_msec_t
) (r
->resend_timeout
* 1000));
600 rn
->expire
= ngx_time() + r
->resend_timeout
;
602 ngx_queue_insert_head(&r
->name_resend_queue
, &rn
->queue
);
609 ctx
->state
= NGX_AGAIN
;
615 ngx_rbtree_delete(&r
->name_rbtree
, &rn
->node
);
618 ngx_resolver_free(r
, rn
->query
);
621 ngx_resolver_free(r
, rn
->name
);
623 ngx_resolver_free(r
, rn
);
630 ngx_resolve_addr(ngx_resolver_ctx_t
*ctx
)
634 ngx_resolver_node_t
*rn
;
638 ctx
->addr
= ntohl(ctx
->addr
);
640 /* lock addr mutex */
642 rn
= ngx_resolver_lookup_addr(r
, ctx
->addr
);
646 if (rn
->valid
>= ngx_time()) {
648 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolve cached");
650 ngx_queue_remove(&rn
->queue
);
652 rn
->expire
= ngx_time() + r
->expire
;
654 ngx_queue_insert_head(&r
->addr_expire_queue
, &rn
->queue
);
656 name
= ngx_resolver_dup(r
, rn
->name
, rn
->nlen
);
661 ctx
->name
.len
= rn
->nlen
;
662 ctx
->name
.data
= name
;
664 /* unlock addr mutex */
670 ngx_resolver_free(r
, name
);
677 ctx
->next
= rn
->waiting
;
679 ctx
->state
= NGX_AGAIN
;
681 /* unlock addr mutex */
686 ngx_queue_remove(&rn
->queue
);
688 ngx_resolver_free(r
, rn
->query
);
692 rn
= ngx_resolver_alloc(r
, sizeof(ngx_resolver_node_t
));
697 rn
->node
.key
= ctx
->addr
;
700 ngx_rbtree_insert(&r
->addr_rbtree
, &rn
->node
);
703 if (ngx_resolver_create_addr_query(rn
, ctx
) != NGX_OK
) {
707 if (ngx_resolver_send_query(r
, rn
) != NGX_OK
) {
711 ctx
->event
= ngx_resolver_calloc(r
, sizeof(ngx_event_t
));
712 if (ctx
->event
== NULL
) {
716 ctx
->event
->handler
= ngx_resolver_timeout_handler
;
717 ctx
->event
->data
= ctx
;
718 ctx
->event
->log
= r
->log
;
721 ngx_add_timer(ctx
->event
, ctx
->timeout
);
723 if (ngx_queue_empty(&r
->addr_resend_queue
)) {
724 ngx_add_timer(r
->event
, (ngx_msec_t
) (r
->resend_timeout
* 1000));
727 rn
->expire
= ngx_time() + r
->resend_timeout
;
729 ngx_queue_insert_head(&r
->addr_resend_queue
, &rn
->queue
);
738 /* unlock addr mutex */
740 ctx
->state
= NGX_AGAIN
;
747 ngx_rbtree_delete(&r
->addr_rbtree
, &rn
->node
);
750 ngx_resolver_free(r
, rn
->query
);
753 ngx_resolver_free(r
, rn
);
756 /* unlock addr mutex */
759 ngx_resolver_free(r
, ctx
->event
);
762 ngx_resolver_free(r
, ctx
);
769 ngx_resolve_addr_done(ngx_resolver_ctx_t
*ctx
)
773 ngx_resolver_ctx_t
*w
, **p
;
774 ngx_resolver_node_t
*rn
;
778 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
779 "resolve addr done: %i", ctx
->state
);
781 if (ctx
->event
&& ctx
->event
->timer_set
) {
782 ngx_del_timer(ctx
->event
);
785 /* lock addr mutex */
787 if (ctx
->state
== NGX_AGAIN
|| ctx
->state
== NGX_RESOLVE_TIMEDOUT
) {
789 rn
= ngx_resolver_lookup_addr(r
, ctx
->addr
);
807 addr
= ntohl(ctx
->addr
);
809 ngx_log_error(NGX_LOG_ALERT
, r
->log
, 0,
810 "could not cancel %ud.%ud.%ud.%ud resolving",
811 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
812 (addr
>> 8) & 0xff, addr
& 0xff);
817 ngx_resolver_expire(r
, &r
->addr_rbtree
, &r
->addr_expire_queue
);
819 /* unlock addr mutex */
821 /* lock alloc mutex */
824 ngx_resolver_free_locked(r
, ctx
->event
);
827 ngx_resolver_free_locked(r
, ctx
);
829 /* unlock alloc mutex */
834 ngx_resolver_expire(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
, ngx_queue_t
*queue
)
839 ngx_resolver_node_t
*rn
;
841 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolver expire");
845 for (i
= 0; i
< 2; i
++) {
846 if (ngx_queue_empty(queue
)) {
850 q
= ngx_queue_last(queue
);
852 rn
= ngx_queue_data(q
, ngx_resolver_node_t
, queue
);
854 if (now
<= rn
->expire
) {
858 ngx_log_debug2(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
859 "resolver expire \"%*s\"", (size_t) rn
->nlen
, rn
->name
);
863 ngx_rbtree_delete(tree
, &rn
->node
);
865 ngx_resolver_free_node(r
, rn
);
871 ngx_resolver_send_query(ngx_resolver_t
*r
, ngx_resolver_node_t
*rn
)
874 ngx_udp_connection_t
*uc
;
876 uc
= r
->udp_connections
.elts
;
878 uc
= &uc
[r
->last_connection
++];
879 if (r
->last_connection
== r
->udp_connections
.nelts
) {
880 r
->last_connection
= 0;
883 if (uc
->connection
== NULL
) {
886 uc
->log
.handler
= ngx_resolver_log_error
;
888 uc
->log
.action
= "resolving";
890 if (ngx_udp_connect(uc
) != NGX_OK
) {
894 uc
->connection
->data
= r
;
895 uc
->connection
->read
->handler
= ngx_resolver_read_response
;
896 uc
->connection
->read
->resolver
= 1;
899 n
= ngx_send(uc
->connection
, rn
->query
, rn
->qlen
);
905 if ((size_t) n
!= (size_t) rn
->qlen
) {
906 ngx_log_error(NGX_LOG_CRIT
, &uc
->log
, 0, "send() incomplete");
915 ngx_resolver_resend_handler(ngx_event_t
*ev
)
917 time_t timer
, atimer
, ntimer
;
922 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
923 "resolver resend handler");
925 /* lock name mutex */
927 ntimer
= ngx_resolver_resend(r
, &r
->name_rbtree
, &r
->name_resend_queue
);
929 /* unlock name mutex */
931 /* lock addr mutex */
933 atimer
= ngx_resolver_resend(r
, &r
->addr_rbtree
, &r
->addr_resend_queue
);
935 /* unlock addr mutex */
940 } else if (atimer
== 0) {
944 timer
= (atimer
< ntimer
) ? atimer
: ntimer
;
948 ngx_add_timer(r
->event
, (ngx_msec_t
) (timer
* 1000));
954 ngx_resolver_resend(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
, ngx_queue_t
*queue
)
958 ngx_resolver_node_t
*rn
;
963 if (ngx_queue_empty(queue
)) {
967 q
= ngx_queue_last(queue
);
969 rn
= ngx_queue_data(q
, ngx_resolver_node_t
, queue
);
971 if (now
< rn
->expire
) {
972 return rn
->expire
- now
;
975 ngx_log_debug3(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
976 "resolver resend \"%*s\" %p",
977 (size_t) rn
->nlen
, rn
->name
, rn
->waiting
);
983 (void) ngx_resolver_send_query(r
, rn
);
985 rn
->expire
= now
+ r
->resend_timeout
;
987 ngx_queue_insert_head(queue
, q
);
992 ngx_rbtree_delete(tree
, &rn
->node
);
994 ngx_resolver_free_node(r
, rn
);
1000 ngx_resolver_read_response(ngx_event_t
*rev
)
1003 ngx_connection_t
*c
;
1004 u_char buf
[NGX_RESOLVER_UDP_SIZE
];
1009 n
= ngx_udp_recv(c
, buf
, NGX_RESOLVER_UDP_SIZE
);
1015 ngx_resolver_process_response(c
->data
, buf
, n
);
1017 } while (rev
->ready
);
1022 ngx_resolver_process_response(ngx_resolver_t
*r
, u_char
*buf
, size_t n
)
1026 ngx_uint_t i
, times
, ident
, qident
, flags
, code
, nqs
, nan
,
1029 ngx_resolver_qs_t
*qs
;
1030 ngx_resolver_node_t
*rn
;
1031 ngx_resolver_query_t
*query
;
1033 if ((size_t) n
< sizeof(ngx_resolver_query_t
)) {
1034 goto short_response
;
1037 query
= (ngx_resolver_query_t
*) buf
;
1039 ident
= (query
->ident_hi
<< 8) + query
->ident_lo
;
1040 flags
= (query
->flags_hi
<< 8) + query
->flags_lo
;
1041 nqs
= (query
->nqs_hi
<< 8) + query
->nqs_lo
;
1042 nan
= (query
->nan_hi
<< 8) + query
->nan_lo
;
1044 ngx_log_debug6(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1045 "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
1046 ident
, flags
, nqs
, nan
,
1047 (query
->nns_hi
<< 8) + query
->nns_lo
,
1048 (query
->nar_hi
<< 8) + query
->nar_lo
);
1050 if (!(flags
& 0x8000)) {
1051 ngx_log_error(r
->log_level
, r
->log
, 0,
1052 "invalid DNS response %ui fl:%04Xui", ident
, flags
);
1056 code
= flags
& 0x7f;
1058 if (code
== NGX_RESOLVE_FORMERR
) {
1062 for (q
= ngx_queue_head(&r
->name_resend_queue
);
1063 q
!= ngx_queue_sentinel(&r
->name_resend_queue
) || times
++ < 100;
1064 q
= ngx_queue_next(q
))
1066 rn
= ngx_queue_data(q
, ngx_resolver_node_t
, queue
);
1067 qident
= (rn
->query
[0] << 8) + rn
->query
[1];
1069 if (qident
== ident
) {
1070 ngx_log_error(r
->log_level
, r
->log
, 0,
1071 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1072 code
, ngx_resolver_strerror(code
), ident
,
1073 rn
->nlen
, rn
->name
);
1081 if (code
> NGX_RESOLVE_REFUSED
) {
1086 err
= "invalid number of questions in DNS response";
1090 i
= sizeof(ngx_resolver_query_t
);
1092 while (i
< (ngx_uint_t
) n
) {
1093 if (buf
[i
] == '\0') {
1101 goto short_response
;
1106 err
= "zero-length domain name in DNS response";
1110 if (i
+ sizeof(ngx_resolver_qs_t
) + nan
* (2 + sizeof(ngx_resolver_an_t
))
1113 goto short_response
;
1116 qs
= (ngx_resolver_qs_t
*) &buf
[i
];
1118 qtype
= (qs
->type_hi
<< 8) + qs
->type_lo
;
1119 qclass
= (qs
->class_hi
<< 8) + qs
->class_lo
;
1121 ngx_log_debug2(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1122 "resolver DNS response qt:%ui cl:%ui", qtype
, qclass
);
1125 ngx_log_error(r
->log_level
, r
->log
, 0,
1126 "unknown query class %ui in DNS response", qclass
);
1134 ngx_resolver_process_a(r
, buf
, n
, ident
, code
, nan
,
1135 i
+ sizeof(ngx_resolver_qs_t
));
1139 case NGX_RESOLVE_PTR
:
1141 ngx_resolver_process_ptr(r
, buf
, n
, ident
, code
, nan
);
1146 ngx_log_error(r
->log_level
, r
->log
, 0,
1147 "unknown query type %ui in DNS response", qtype
);
1155 err
= "short dns response";
1159 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1165 ngx_log_error(r
->log_level
, r
->log
, 0,
1166 "DNS error (%ui: %s), query id:%ui",
1167 code
, ngx_resolver_strerror(code
), ident
);
1173 ngx_resolver_process_a(ngx_resolver_t
*r
, u_char
*buf
, size_t last
,
1174 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
, ngx_uint_t ans
)
1181 in_addr_t addr
, *addrs
;
1183 ngx_uint_t qtype
, qident
, naddrs
, a
, i
, n
, start
;
1184 ngx_resolver_an_t
*an
;
1185 ngx_resolver_ctx_t
*ctx
, *next
;
1186 ngx_resolver_node_t
*rn
;
1188 if (ngx_resolver_copy(r
, &name
, buf
, &buf
[12], &buf
[last
]) != NGX_OK
) {
1192 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolver qs:%V", &name
);
1194 hash
= ngx_crc32_short(name
.data
, name
.len
);
1196 /* lock name mutex */
1198 rn
= ngx_resolver_lookup_name(r
, &name
, hash
);
1200 if (rn
== NULL
|| rn
->query
== NULL
) {
1201 ngx_log_error(r
->log_level
, r
->log
, 0,
1202 "unexpected response for %V", &name
);
1206 qident
= (rn
->query
[0] << 8) + rn
->query
[1];
1208 if (ident
!= qident
) {
1209 ngx_log_error(r
->log_level
, r
->log
, 0,
1210 "wrong ident %ui response for %V, expect %ui",
1211 ident
, &name
, qident
);
1215 ngx_resolver_free(r
, name
.data
);
1217 if (code
== 0 && nan
== 0) {
1218 code
= 3; /* NXDOMAIN */
1225 ngx_queue_remove(&rn
->queue
);
1227 ngx_rbtree_delete(&r
->name_rbtree
, &rn
->node
);
1229 ngx_resolver_free_node(r
, rn
);
1231 /* unlock name mutex */
1252 for (a
= 0; a
< nan
; a
++) {
1258 if (buf
[i
] & 0xc0) {
1271 goto short_response
;
1275 if (i
- start
< 2) {
1276 err
= "invalid name in dns response";
1282 if (i
+ sizeof(ngx_resolver_an_t
) >= last
) {
1283 goto short_response
;
1286 an
= (ngx_resolver_an_t
*) &buf
[i
];
1288 qtype
= (an
->type_hi
<< 8) + an
->type_lo
;
1289 len
= (an
->len_hi
<< 8) + an
->len_lo
;
1290 ttl
= (an
->ttl
[0] << 24) + (an
->ttl
[1] << 16)
1291 + (an
->ttl
[2] << 8) + (an
->ttl
[3]);
1297 if (qtype
== NGX_RESOLVE_A
) {
1299 i
+= sizeof(ngx_resolver_an_t
);
1301 if (i
+ len
> last
) {
1302 goto short_response
;
1305 addr
= htonl((buf
[i
] << 24) + (buf
[i
+ 1] << 16)
1306 + (buf
[i
+ 2] << 8) + (buf
[i
+ 3]));
1312 } else if (qtype
== NGX_RESOLVE_CNAME
) {
1313 cname
= &buf
[i
] + sizeof(ngx_resolver_an_t
);
1314 i
+= sizeof(ngx_resolver_an_t
) + len
;
1316 } else if (qtype
== NGX_RESOLVE_DNAME
) {
1317 i
+= sizeof(ngx_resolver_an_t
) + len
;
1320 ngx_log_error(r
->log_level
, r
->log
, 0,
1321 "unexpected qtype %ui", qtype
);
1325 ngx_log_debug3(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1326 "resolver naddrs:%ui cname:%p ttl:%d",
1327 naddrs
, cname
, ttl
);
1336 addrs
= ngx_resolver_alloc(r
, naddrs
* sizeof(in_addr_t
));
1337 if (addrs
== NULL
) {
1344 for (a
= 0; a
< nan
; a
++) {
1348 if (buf
[i
] & 0xc0) {
1363 an
= (ngx_resolver_an_t
*) &buf
[i
];
1365 qtype
= (an
->type_hi
<< 8) + an
->type_lo
;
1366 len
= (an
->len_hi
<< 8) + an
->len_lo
;
1368 i
+= sizeof(ngx_resolver_an_t
);
1370 if (qtype
== NGX_RESOLVE_A
) {
1372 addrs
[n
++] = htonl((buf
[i
] << 24) + (buf
[i
+ 1] << 16)
1373 + (buf
[i
+ 2] << 8) + (buf
[i
+ 3]));
1383 rn
->u
.addrs
= addrs
;
1385 addrs
= ngx_resolver_dup(r
, rn
->u
.addrs
,
1386 naddrs
* sizeof(in_addr_t
));
1387 if (addrs
== NULL
) {
1392 rn
->naddrs
= (u_short
) naddrs
;
1394 ngx_queue_remove(&rn
->queue
);
1396 rn
->valid
= ngx_time() + (r
->valid
? r
->valid
: ttl
);
1397 rn
->expire
= ngx_time() + r
->expire
;
1399 ngx_queue_insert_head(&r
->name_expire_queue
, &rn
->queue
);
1404 /* unlock name mutex */
1408 ctx
->state
= NGX_OK
;
1409 ctx
->naddrs
= naddrs
;
1410 ctx
->addrs
= (naddrs
== 1) ? &ctx
->addr
: addrs
;
1418 ngx_resolver_free(r
, addrs
);
1421 ngx_resolver_free(r
, rn
->query
);
1430 if (ngx_resolver_copy(r
, &name
, buf
, cname
, &buf
[last
]) != NGX_OK
) {
1434 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1435 "resolver cname:\"%V\"", &name
);
1437 ngx_queue_remove(&rn
->queue
);
1439 rn
->cnlen
= (u_short
) name
.len
;
1440 rn
->u
.cname
= name
.data
;
1442 rn
->valid
= ngx_time() + (r
->valid
? r
->valid
: ttl
);
1443 rn
->expire
= ngx_time() + r
->expire
;
1445 ngx_queue_insert_head(&r
->name_expire_queue
, &rn
->queue
);
1453 (void) ngx_resolve_name_locked(r
, ctx
);
1456 ngx_resolver_free(r
, rn
->query
);
1462 ngx_log_error(r
->log_level
, r
->log
, 0,
1463 "no A or CNAME types in DNS responses, unknown query type: %ui",
1469 err
= "short dns response";
1473 /* unlock name mutex */
1475 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1481 /* unlock name mutex */
1483 ngx_resolver_free(r
, name
.data
);
1490 ngx_resolver_process_ptr(ngx_resolver_t
*r
, u_char
*buf
, size_t n
,
1491 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
)
1499 ngx_uint_t i
, mask
, qident
;
1500 ngx_resolver_an_t
*an
;
1501 ngx_resolver_ctx_t
*ctx
, *next
;
1502 ngx_resolver_node_t
*rn
;
1504 if (ngx_resolver_copy(r
, NULL
, buf
, &buf
[12], &buf
[n
]) != NGX_OK
) {
1505 goto invalid_in_addr_arpa
;
1511 for (mask
= 0; mask
< 32; mask
+= 8) {
1514 digit
= ngx_atoi(&buf
[i
], len
);
1515 if (digit
== NGX_ERROR
|| digit
> 255) {
1516 goto invalid_in_addr_arpa
;
1519 addr
+= digit
<< mask
;
1523 if (ngx_strcmp(&buf
[i
], "\7in-addr\4arpa") != 0) {
1524 goto invalid_in_addr_arpa
;
1527 /* lock addr mutex */
1529 rn
= ngx_resolver_lookup_addr(r
, addr
);
1531 if (rn
== NULL
|| rn
->query
== NULL
) {
1532 ngx_log_error(r
->log_level
, r
->log
, 0,
1533 "unexpected response for %ud.%ud.%ud.%ud",
1534 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
1535 (addr
>> 8) & 0xff, addr
& 0xff);
1539 qident
= (rn
->query
[0] << 8) + rn
->query
[1];
1541 if (ident
!= qident
) {
1542 ngx_log_error(r
->log_level
, r
->log
, 0,
1543 "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui",
1544 ident
, (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
1545 (addr
>> 8) & 0xff, addr
& 0xff, qident
);
1549 if (code
== 0 && nan
== 0) {
1550 code
= 3; /* NXDOMAIN */
1557 ngx_queue_remove(&rn
->queue
);
1559 ngx_rbtree_delete(&r
->addr_rbtree
, &rn
->node
);
1561 ngx_resolver_free_node(r
, rn
);
1563 /* unlock addr mutex */
1576 i
+= sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t
);
1578 if (i
+ 2 + sizeof(ngx_resolver_an_t
) > (ngx_uint_t
) n
) {
1579 goto short_response
;
1582 /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */
1584 if (buf
[i
] != 0xc0 || buf
[i
+ 1] != 0x0c) {
1585 err
= "invalid in-addr.arpa name in DNS response";
1589 an
= (ngx_resolver_an_t
*) &buf
[i
+ 2];
1591 len
= (an
->len_hi
<< 8) + an
->len_lo
;
1592 ttl
= (an
->ttl
[0] << 24) + (an
->ttl
[1] << 16)
1593 + (an
->ttl
[2] << 8) + (an
->ttl
[3]);
1599 ngx_log_debug3(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1600 "resolver qt:%ui cl:%ui len:%uz",
1601 (an
->type_hi
<< 8) + an
->type_lo
,
1602 (an
->class_hi
<< 8) + an
->class_lo
, len
);
1604 i
+= 2 + sizeof(ngx_resolver_an_t
);
1606 if (i
+ len
> (ngx_uint_t
) n
) {
1607 goto short_response
;
1610 if (ngx_resolver_copy(r
, &name
, buf
, &buf
[i
], &buf
[n
]) != NGX_OK
) {
1614 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolver an:%V", &name
);
1616 if (name
.len
!= (size_t) rn
->nlen
1617 || ngx_strncmp(name
.data
, rn
->name
, name
.len
) != 0)
1620 ngx_resolver_free(r
, rn
->name
);
1623 rn
->nlen
= (u_short
) name
.len
;
1624 rn
->name
= name
.data
;
1626 name
.data
= ngx_resolver_dup(r
, rn
->name
, name
.len
);
1627 if (name
.data
== NULL
) {
1632 ngx_queue_remove(&rn
->queue
);
1634 rn
->valid
= ngx_time() + (r
->valid
? r
->valid
: ttl
);
1635 rn
->expire
= ngx_time() + r
->expire
;
1637 ngx_queue_insert_head(&r
->addr_expire_queue
, &rn
->queue
);
1642 /* unlock addr mutex */
1646 ctx
->state
= NGX_OK
;
1653 ngx_resolver_free(r
, name
.data
);
1657 invalid_in_addr_arpa
:
1659 ngx_log_error(r
->log_level
, r
->log
, 0,
1660 "invalid in-addr.arpa name in DNS response");
1665 err
= "short DNS response";
1669 /* unlock addr mutex */
1671 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1677 /* unlock addr mutex */
1683 static ngx_resolver_node_t
*
1684 ngx_resolver_lookup_name(ngx_resolver_t
*r
, ngx_str_t
*name
, uint32_t hash
)
1687 ngx_rbtree_node_t
*node
, *sentinel
;
1688 ngx_resolver_node_t
*rn
;
1690 node
= r
->name_rbtree
.root
;
1691 sentinel
= r
->name_rbtree
.sentinel
;
1693 while (node
!= sentinel
) {
1695 if (hash
< node
->key
) {
1700 if (hash
> node
->key
) {
1705 /* hash == node->key */
1707 rn
= (ngx_resolver_node_t
*) node
;
1709 rc
= ngx_memn2cmp(name
->data
, rn
->name
, name
->len
, rn
->nlen
);
1715 node
= (rc
< 0) ? node
->left
: node
->right
;
1724 static ngx_resolver_node_t
*
1725 ngx_resolver_lookup_addr(ngx_resolver_t
*r
, in_addr_t addr
)
1727 ngx_rbtree_node_t
*node
, *sentinel
;
1729 node
= r
->addr_rbtree
.root
;
1730 sentinel
= r
->addr_rbtree
.sentinel
;
1732 while (node
!= sentinel
) {
1734 if (addr
< node
->key
) {
1739 if (addr
> node
->key
) {
1744 /* addr == node->key */
1746 return (ngx_resolver_node_t
*) node
;
1756 ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
1757 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
)
1759 ngx_rbtree_node_t
**p
;
1760 ngx_resolver_node_t
*rn
, *rn_temp
;
1764 if (node
->key
< temp
->key
) {
1768 } else if (node
->key
> temp
->key
) {
1772 } else { /* node->key == temp->key */
1774 rn
= (ngx_resolver_node_t
*) node
;
1775 rn_temp
= (ngx_resolver_node_t
*) temp
;
1777 p
= (ngx_memn2cmp(rn
->name
, rn_temp
->name
, rn
->nlen
, rn_temp
->nlen
)
1778 < 0) ? &temp
->left
: &temp
->right
;
1781 if (*p
== sentinel
) {
1789 node
->parent
= temp
;
1790 node
->left
= sentinel
;
1791 node
->right
= sentinel
;
1797 ngx_resolver_create_name_query(ngx_resolver_node_t
*rn
, ngx_resolver_ctx_t
*ctx
)
1802 ngx_resolver_qs_t
*qs
;
1803 ngx_resolver_query_t
*query
;
1805 nlen
= ctx
->name
.len
? (1 + ctx
->name
.len
+ 1) : 1;
1807 len
= sizeof(ngx_resolver_query_t
) + nlen
+ sizeof(ngx_resolver_qs_t
);
1809 p
= ngx_resolver_alloc(ctx
->resolver
, len
);
1814 rn
->qlen
= (u_short
) len
;
1817 query
= (ngx_resolver_query_t
*) p
;
1819 ident
= ngx_random();
1821 ngx_log_debug2(NGX_LOG_DEBUG_CORE
, ctx
->resolver
->log
, 0,
1822 "resolve: \"%V\" %i", &ctx
->name
, ident
& 0xffff);
1824 query
->ident_hi
= (u_char
) ((ident
>> 8) & 0xff);
1825 query
->ident_lo
= (u_char
) (ident
& 0xff);
1827 /* recursion query */
1828 query
->flags_hi
= 1; query
->flags_lo
= 0;
1831 query
->nqs_hi
= 0; query
->nqs_lo
= 1;
1832 query
->nan_hi
= 0; query
->nan_lo
= 0;
1833 query
->nns_hi
= 0; query
->nns_lo
= 0;
1834 query
->nar_hi
= 0; query
->nar_lo
= 0;
1836 p
+= sizeof(ngx_resolver_query_t
) + nlen
;
1838 qs
= (ngx_resolver_qs_t
*) p
;
1841 qs
->type_hi
= 0; qs
->type_lo
= (u_char
) ctx
->type
;
1843 /* IP query class */
1844 qs
->class_hi
= 0; qs
->class_lo
= 1;
1846 /* convert "www.example.com" to "\3www\7example\3com\0" */
1852 if (ctx
->name
.len
== 0) {
1853 return NGX_DECLINED
;
1856 for (s
= ctx
->name
.data
+ ctx
->name
.len
- 1; s
>= ctx
->name
.data
; s
--) {
1862 if (len
== 0 || len
> 255) {
1863 return NGX_DECLINED
;
1873 if (len
== 0 || len
> 255) {
1874 return NGX_DECLINED
;
1886 ngx_resolver_create_addr_query(ngx_resolver_node_t
*rn
, ngx_resolver_ctx_t
*ctx
)
1892 ngx_resolver_query_t
*query
;
1894 len
= sizeof(ngx_resolver_query_t
)
1895 + sizeof(".255.255.255.255.in-addr.arpa.") - 1
1896 + sizeof(ngx_resolver_qs_t
);
1898 p
= ngx_resolver_alloc(ctx
->resolver
, len
);
1904 query
= (ngx_resolver_query_t
*) p
;
1906 ident
= ngx_random();
1908 query
->ident_hi
= (u_char
) ((ident
>> 8) & 0xff);
1909 query
->ident_lo
= (u_char
) (ident
& 0xff);
1911 /* recursion query */
1912 query
->flags_hi
= 1; query
->flags_lo
= 0;
1915 query
->nqs_hi
= 0; query
->nqs_lo
= 1;
1916 query
->nan_hi
= 0; query
->nan_lo
= 0;
1917 query
->nns_hi
= 0; query
->nns_lo
= 0;
1918 query
->nar_hi
= 0; query
->nar_lo
= 0;
1920 p
+= sizeof(ngx_resolver_query_t
);
1922 for (n
= 0; n
< 32; n
+= 8) {
1923 d
= ngx_sprintf(&p
[1], "%ud", (ctx
->addr
>> n
) & 0xff);
1924 *p
= (u_char
) (d
- &p
[1]);
1928 /* query type "PTR", IP query class */
1929 ngx_memcpy(p
, "\7in-addr\4arpa\0\0\14\0\1", 18);
1931 rn
->qlen
= (u_short
)
1932 (p
+ sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t
)
1940 ngx_resolver_copy(ngx_resolver_t
*r
, ngx_str_t
*name
, u_char
*buf
, u_char
*src
,
1952 * compression pointers allow to create endless loop, so we set limit;
1953 * 128 pointers should be enough to store 255-byte name
1956 for (i
= 0; i
< 128; i
++) {
1964 n
= ((n
& 0x3f) << 8) + *p
;
1973 err
= "name is out of response";
1978 err
= "compression pointers loop";
1982 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1998 dst
= ngx_resolver_alloc(r
, len
);
2009 n
= ((n
& 0x3f) << 8) + *src
;
2015 ngx_memcpy(dst
, src
, n
);
2027 name
->len
= dst
- name
->data
;
2035 ngx_resolver_timeout_handler(ngx_event_t
*ev
)
2037 ngx_resolver_ctx_t
*ctx
;
2041 ctx
->state
= NGX_RESOLVE_TIMEDOUT
;
2048 ngx_resolver_free_node(ngx_resolver_t
*r
, ngx_resolver_node_t
*rn
)
2050 /* lock alloc mutex */
2053 ngx_resolver_free_locked(r
, rn
->query
);
2057 ngx_resolver_free_locked(r
, rn
->name
);
2061 ngx_resolver_free_locked(r
, rn
->u
.cname
);
2064 if (rn
->naddrs
> 1) {
2065 ngx_resolver_free_locked(r
, rn
->u
.addrs
);
2068 ngx_resolver_free_locked(r
, rn
);
2070 /* unlock alloc mutex */
2075 ngx_resolver_alloc(ngx_resolver_t
*r
, size_t size
)
2079 /* lock alloc mutex */
2081 p
= ngx_alloc(size
, r
->log
);
2083 /* unlock alloc mutex */
2090 ngx_resolver_calloc(ngx_resolver_t
*r
, size_t size
)
2094 p
= ngx_resolver_alloc(r
, size
);
2097 ngx_memzero(p
, size
);
2105 ngx_resolver_free(ngx_resolver_t
*r
, void *p
)
2107 /* lock alloc mutex */
2111 /* unlock alloc mutex */
2116 ngx_resolver_free_locked(ngx_resolver_t
*r
, void *p
)
2123 ngx_resolver_dup(ngx_resolver_t
*r
, void *src
, size_t size
)
2127 dst
= ngx_resolver_alloc(r
, size
);
2133 ngx_memcpy(dst
, src
, size
);
2140 ngx_resolver_rotate(ngx_resolver_t
*r
, in_addr_t
*src
, ngx_uint_t n
)
2145 dst
= ngx_resolver_alloc(r
, n
* sizeof(in_addr_t
));
2151 j
= ngx_random() % n
;
2154 ngx_memcpy(dst
, src
, n
* sizeof(in_addr_t
));
2158 p
= ngx_cpymem(dst
, &src
[j
], (n
- j
) * sizeof(in_addr_t
));
2159 ngx_memcpy(p
, src
, j
* sizeof(in_addr_t
));
2166 ngx_resolver_strerror(ngx_int_t err
)
2168 static char *errors
[] = {
2169 "Format error", /* FORMERR */
2170 "Server failure", /* SERVFAIL */
2171 "Host not found", /* NXDOMAIN */
2172 "Unimplemented", /* NOTIMP */
2173 "Operation refused" /* REFUSED */
2176 if (err
> 0 && err
< 6) {
2177 return errors
[err
- 1];
2180 if (err
== NGX_RESOLVE_TIMEDOUT
) {
2181 return "Operation timed out";
2184 return "Unknown error";
2189 ngx_resolver_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
)
2192 ngx_udp_connection_t
*uc
;
2197 p
= ngx_snprintf(buf
, len
, " while %s", log
->action
);
2204 p
= ngx_snprintf(p
, len
, ", resolver: %V", &uc
->server
);
2212 ngx_udp_connect(ngx_udp_connection_t
*uc
)
2216 ngx_event_t
*rev
, *wev
;
2218 ngx_connection_t
*c
;
2220 s
= ngx_socket(uc
->sockaddr
->sa_family
, SOCK_DGRAM
, 0);
2222 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, &uc
->log
, 0, "UDP socket %d", s
);
2225 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2226 ngx_socket_n
" failed");
2230 c
= ngx_get_connection(s
, &uc
->log
);
2233 if (ngx_close_socket(s
) == -1) {
2234 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2235 ngx_close_socket_n
"failed");
2241 if (ngx_nonblocking(s
) == -1) {
2242 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2243 ngx_nonblocking_n
" failed");
2245 ngx_free_connection(c
);
2247 if (ngx_close_socket(s
) == -1) {
2248 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2249 ngx_close_socket_n
" failed");
2258 rev
->log
= &uc
->log
;
2259 wev
->log
= &uc
->log
;
2263 c
->number
= ngx_atomic_fetch_add(ngx_connection_counter
, 1);
2267 /* TODO: lock event when call completion handler */
2269 rev
->lock
= &c
->lock
;
2270 wev
->lock
= &c
->lock
;
2271 rev
->own_lock
= &c
->lock
;
2272 wev
->own_lock
= &c
->lock
;
2276 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, &uc
->log
, 0,
2277 "connect to %V, fd:%d #%d", &uc
->server
, s
, c
->number
);
2279 rc
= connect(s
, uc
->sockaddr
, uc
->socklen
);
2281 /* TODO: aio, iocp */
2284 ngx_log_error(NGX_LOG_CRIT
, &uc
->log
, ngx_socket_errno
,
2285 "connect() failed");
2290 /* UDP sockets are always ready to write */
2293 if (ngx_add_event
) {
2295 event
= (ngx_event_flags
& NGX_USE_CLEAR_EVENT
) ?
2296 /* kqueue, epoll */ NGX_CLEAR_EVENT
:
2297 /* select, poll, /dev/poll */ NGX_LEVEL_EVENT
;
2298 /* eventport event type has no meaning: oneshot only */
2300 if (ngx_add_event(rev
, NGX_READ_EVENT
, event
) != NGX_OK
) {
2307 if (ngx_add_conn(c
) == NGX_ERROR
) {