3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
12 #define NGX_RESOLVER_UDP_SIZE 4096
28 } ngx_resolver_query_t
;
50 ngx_int_t
ngx_udp_connect(ngx_udp_connection_t
*uc
);
53 static void ngx_resolver_cleanup(void *data
);
54 static void ngx_resolver_cleanup_tree(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
);
55 static ngx_int_t
ngx_resolve_name_locked(ngx_resolver_t
*r
,
56 ngx_resolver_ctx_t
*ctx
);
57 static void ngx_resolver_expire(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
,
59 static ngx_int_t
ngx_resolver_send_query(ngx_resolver_t
*r
,
60 ngx_resolver_node_t
*rn
);
61 static ngx_int_t
ngx_resolver_create_name_query(ngx_resolver_node_t
*rn
,
62 ngx_resolver_ctx_t
*ctx
);
63 static ngx_int_t
ngx_resolver_create_addr_query(ngx_resolver_node_t
*rn
,
64 ngx_resolver_ctx_t
*ctx
);
65 static void ngx_resolver_resend_handler(ngx_event_t
*ev
);
66 static time_t ngx_resolver_resend(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
,
68 static void ngx_resolver_read_response(ngx_event_t
*rev
);
69 static void ngx_resolver_process_response(ngx_resolver_t
*r
, u_char
*buf
,
71 static void ngx_resolver_process_a(ngx_resolver_t
*r
, u_char
*buf
, size_t n
,
72 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
, ngx_uint_t ans
);
73 static void ngx_resolver_process_ptr(ngx_resolver_t
*r
, u_char
*buf
, size_t n
,
74 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
);
75 static ngx_resolver_node_t
*ngx_resolver_lookup_name(ngx_resolver_t
*r
,
76 ngx_str_t
*name
, uint32_t hash
);
77 static ngx_resolver_node_t
*ngx_resolver_lookup_addr(ngx_resolver_t
*r
,
79 static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
80 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
);
81 static ngx_int_t
ngx_resolver_copy(ngx_resolver_t
*r
, ngx_str_t
*name
,
82 u_char
*buf
, u_char
*src
, u_char
*last
);
83 static void ngx_resolver_timeout_handler(ngx_event_t
*ev
);
84 static void ngx_resolver_free_node(ngx_resolver_t
*r
, ngx_resolver_node_t
*rn
);
85 static void *ngx_resolver_alloc(ngx_resolver_t
*r
, size_t size
);
86 static void *ngx_resolver_calloc(ngx_resolver_t
*r
, size_t size
);
87 static void ngx_resolver_free(ngx_resolver_t
*r
, void *p
);
88 static void ngx_resolver_free_locked(ngx_resolver_t
*r
, void *p
);
89 static void *ngx_resolver_dup(ngx_resolver_t
*r
, void *src
, size_t size
);
90 static u_char
*ngx_resolver_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
);
94 ngx_resolver_create(ngx_conf_t
*cf
, ngx_addr_t
*addr
)
97 ngx_pool_cleanup_t
*cln
;
98 ngx_udp_connection_t
*uc
;
100 cln
= ngx_pool_cleanup_add(cf
->pool
, 0);
105 cln
->handler
= ngx_resolver_cleanup
;
107 r
= ngx_calloc(sizeof(ngx_resolver_t
), cf
->log
);
114 r
->event
= ngx_calloc(sizeof(ngx_event_t
), cf
->log
);
115 if (r
->event
== NULL
) {
119 ngx_rbtree_init(&r
->name_rbtree
, &r
->name_sentinel
,
120 ngx_resolver_rbtree_insert_value
);
122 ngx_rbtree_init(&r
->addr_rbtree
, &r
->addr_sentinel
,
123 ngx_rbtree_insert_value
);
125 ngx_queue_init(&r
->name_resend_queue
);
126 ngx_queue_init(&r
->addr_resend_queue
);
128 ngx_queue_init(&r
->name_expire_queue
);
129 ngx_queue_init(&r
->addr_expire_queue
);
131 r
->event
->handler
= ngx_resolver_resend_handler
;
133 r
->event
->log
= &cf
->cycle
->new_log
;
136 r
->resend_timeout
= 5;
140 r
->log
= &cf
->cycle
->new_log
;
141 r
->log_level
= NGX_LOG_ALERT
;
144 uc
= ngx_calloc(sizeof(ngx_udp_connection_t
), cf
->log
);
149 r
->udp_connection
= uc
;
151 uc
->sockaddr
= addr
->sockaddr
;
152 uc
->socklen
= addr
->socklen
;
153 uc
->server
= addr
->name
;
155 uc
->log
= cf
->cycle
->new_log
;
156 uc
->log
.handler
= ngx_resolver_log_error
;
158 uc
->log
.action
= "resolving";
166 ngx_resolver_cleanup(void *data
)
168 ngx_resolver_t
*r
= data
;
171 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, ngx_cycle
->log
, 0,
174 ngx_resolver_cleanup_tree(r
, &r
->name_rbtree
);
176 ngx_resolver_cleanup_tree(r
, &r
->addr_rbtree
);
182 if (r
->udp_connection
) {
183 if (r
->udp_connection
->connection
) {
184 ngx_close_connection(r
->udp_connection
->connection
);
187 ngx_free(r
->udp_connection
);
196 ngx_resolver_cleanup_tree(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
)
198 ngx_resolver_ctx_t
*ctx
, *next
;
199 ngx_resolver_node_t
*rn
;
201 while (tree
->root
!= tree
->sentinel
) {
203 rn
= (ngx_resolver_node_t
*) ngx_rbtree_min(tree
->root
, tree
->sentinel
);
205 ngx_queue_remove(&rn
->queue
);
207 for (ctx
= rn
->waiting
; ctx
; ctx
= next
) {
211 ngx_resolver_free(r
, ctx
->event
);
214 ngx_resolver_free(r
, ctx
);
217 ngx_rbtree_delete(tree
, &rn
->node
);
219 ngx_resolver_free_node(r
, rn
);
225 ngx_resolve_start(ngx_resolver_t
*r
, ngx_resolver_ctx_t
*temp
)
228 ngx_resolver_ctx_t
*ctx
;
231 addr
= ngx_inet_addr(temp
->name
.data
, temp
->name
.len
);
233 if (addr
!= INADDR_NONE
) {
235 temp
->state
= NGX_OK
;
237 temp
->addrs
= &temp
->addr
;
245 if (r
->udp_connection
== NULL
) {
246 return NGX_NO_RESOLVER
;
249 ctx
= ngx_resolver_calloc(r
, sizeof(ngx_resolver_ctx_t
));
260 ngx_resolve_name(ngx_resolver_ctx_t
*ctx
)
267 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
268 "resolve: \"%V\"", &ctx
->name
);
275 /* lock name mutex */
277 rc
= ngx_resolve_name_locked(r
, ctx
);
283 /* unlock name mutex */
285 if (rc
== NGX_AGAIN
) {
292 ngx_resolver_free(r
, ctx
->event
);
295 ngx_resolver_free(r
, ctx
);
302 ngx_resolve_name_done(ngx_resolver_ctx_t
*ctx
)
306 ngx_resolver_ctx_t
*w
, **p
;
307 ngx_resolver_node_t
*rn
;
311 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
312 "resolve name done: %i", ctx
->state
);
318 if (ctx
->event
&& ctx
->event
->timer_set
) {
319 ngx_del_timer(ctx
->event
);
322 /* lock name mutex */
324 if (ctx
->state
== NGX_AGAIN
|| ctx
->state
== NGX_RESOLVE_TIMEDOUT
) {
326 hash
= ngx_crc32_short(ctx
->name
.data
, ctx
->name
.len
);
328 rn
= ngx_resolver_lookup_name(r
, &ctx
->name
, hash
);
346 ngx_log_error(NGX_LOG_ALERT
, r
->log
, 0,
347 "could not cancel %V resolving", &ctx
->name
);
352 ngx_resolver_expire(r
, &r
->name_rbtree
, &r
->name_expire_queue
);
354 /* unlock name mutex */
356 /* lock alloc mutex */
359 ngx_resolver_free_locked(r
, ctx
->event
);
362 ngx_resolver_free_locked(r
, ctx
);
364 /* unlock alloc mutex */
368 /* NGX_RESOLVE_A only */
371 ngx_resolve_name_locked(ngx_resolver_t
*r
, ngx_resolver_ctx_t
*ctx
)
374 in_addr_t addr
, *addrs
;
377 ngx_resolver_ctx_t
*next
;
378 ngx_resolver_node_t
*rn
;
380 hash
= ngx_crc32_short(ctx
->name
.data
, ctx
->name
.len
);
382 rn
= ngx_resolver_lookup_name(r
, &ctx
->name
, hash
);
386 if (rn
->valid
>= ngx_time()) {
388 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolve cached");
390 ngx_queue_remove(&rn
->queue
);
392 rn
->expire
= ngx_time() + r
->expire
;
394 ngx_queue_insert_head(&r
->name_expire_queue
, &rn
->queue
);
400 /* NGX_RESOLVE_A answer */
404 addrs
= ngx_resolver_dup(r
, rn
->u
.addrs
,
405 naddrs
* sizeof(in_addr_t
));
415 ctx
->next
= rn
->waiting
;
418 /* unlock name mutex */
422 ctx
->naddrs
= naddrs
;
423 ctx
->addrs
= (naddrs
== 1) ? &ctx
->addr
: addrs
;
433 ngx_resolver_free(r
, addrs
);
439 /* NGX_RESOLVE_CNAME */
441 if (ctx
->recursion
++ < NGX_RESOLVER_MAX_RECURSION
) {
443 ctx
->name
.len
= rn
->cnlen
;
444 ctx
->name
.data
= rn
->u
.cname
;
446 return ngx_resolve_name_locked(r
, ctx
);
449 ctx
->next
= rn
->waiting
;
452 /* unlock name mutex */
455 ctx
->state
= NGX_RESOLVE_NXDOMAIN
;
468 ctx
->next
= rn
->waiting
;
470 ctx
->state
= NGX_AGAIN
;
475 ngx_queue_remove(&rn
->queue
);
477 /* lock alloc mutex */
479 ngx_resolver_free_locked(r
, rn
->query
);
483 ngx_resolver_free_locked(r
, rn
->u
.cname
);
486 if (rn
->naddrs
> 1) {
487 ngx_resolver_free_locked(r
, rn
->u
.addrs
);
490 /* unlock alloc mutex */
494 rn
= ngx_resolver_alloc(r
, sizeof(ngx_resolver_node_t
));
499 rn
->name
= ngx_resolver_dup(r
, ctx
->name
.data
, ctx
->name
.len
);
500 if (rn
->name
== NULL
) {
501 ngx_resolver_free(r
, rn
);
506 rn
->nlen
= (u_short
) ctx
->name
.len
;
509 ngx_rbtree_insert(&r
->name_rbtree
, &rn
->node
);
512 rc
= ngx_resolver_create_name_query(rn
, ctx
);
514 if (rc
== NGX_ERROR
) {
518 if (rc
== NGX_DECLINED
) {
519 ngx_rbtree_delete(&r
->name_rbtree
, &rn
->node
);
521 ngx_resolver_free(r
, rn
->query
);
522 ngx_resolver_free(r
, rn
->name
);
523 ngx_resolver_free(r
, rn
);
525 ctx
->state
= NGX_RESOLVE_NXDOMAIN
;
531 if (ngx_resolver_send_query(r
, rn
) != NGX_OK
) {
535 if (ctx
->event
== NULL
) {
536 ctx
->event
= ngx_resolver_calloc(r
, sizeof(ngx_event_t
));
537 if (ctx
->event
== NULL
) {
541 ctx
->event
->handler
= ngx_resolver_timeout_handler
;
542 ctx
->event
->data
= ctx
;
543 ctx
->event
->log
= r
->log
;
546 ngx_add_timer(ctx
->event
, ctx
->timeout
);
549 if (ngx_queue_empty(&r
->name_resend_queue
)) {
550 ngx_add_timer(r
->event
, (ngx_msec_t
) (r
->resend_timeout
* 1000));
553 rn
->expire
= ngx_time() + r
->resend_timeout
;
555 ngx_queue_insert_head(&r
->name_resend_queue
, &rn
->queue
);
562 ctx
->state
= NGX_AGAIN
;
568 ngx_rbtree_delete(&r
->name_rbtree
, &rn
->node
);
571 ngx_resolver_free(r
, rn
->query
);
574 ngx_resolver_free(r
, rn
->name
);
576 ngx_resolver_free(r
, rn
);
583 ngx_resolve_addr(ngx_resolver_ctx_t
*ctx
)
587 ngx_resolver_node_t
*rn
;
591 ctx
->addr
= ntohl(ctx
->addr
);
593 /* lock addr mutex */
595 rn
= ngx_resolver_lookup_addr(r
, ctx
->addr
);
599 if (rn
->valid
>= ngx_time()) {
601 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolve cached");
603 ngx_queue_remove(&rn
->queue
);
605 rn
->expire
= ngx_time() + r
->expire
;
607 ngx_queue_insert_head(&r
->addr_expire_queue
, &rn
->queue
);
609 name
= ngx_resolver_dup(r
, rn
->name
, rn
->nlen
);
614 ctx
->name
.len
= rn
->nlen
;
615 ctx
->name
.data
= name
;
617 /* unlock addr mutex */
623 ngx_resolver_free(r
, name
);
630 ctx
->next
= rn
->waiting
;
632 ctx
->state
= NGX_AGAIN
;
634 /* unlock addr mutex */
639 ngx_queue_remove(&rn
->queue
);
641 ngx_resolver_free(r
, rn
->query
);
645 rn
= ngx_resolver_alloc(r
, sizeof(ngx_resolver_node_t
));
650 rn
->node
.key
= ctx
->addr
;
653 ngx_rbtree_insert(&r
->addr_rbtree
, &rn
->node
);
656 if (ngx_resolver_create_addr_query(rn
, ctx
) != NGX_OK
) {
660 if (ngx_resolver_send_query(r
, rn
) != NGX_OK
) {
664 ctx
->event
= ngx_resolver_calloc(r
, sizeof(ngx_event_t
));
665 if (ctx
->event
== NULL
) {
669 ctx
->event
->handler
= ngx_resolver_timeout_handler
;
670 ctx
->event
->data
= ctx
;
671 ctx
->event
->log
= r
->log
;
674 ngx_add_timer(ctx
->event
, ctx
->timeout
);
676 if (ngx_queue_empty(&r
->addr_resend_queue
)) {
677 ngx_add_timer(r
->event
, (ngx_msec_t
) (r
->resend_timeout
* 1000));
680 rn
->expire
= ngx_time() + r
->resend_timeout
;
682 ngx_queue_insert_head(&r
->addr_resend_queue
, &rn
->queue
);
691 /* unlock addr mutex */
693 ctx
->state
= NGX_AGAIN
;
700 ngx_rbtree_delete(&r
->addr_rbtree
, &rn
->node
);
703 ngx_resolver_free(r
, rn
->query
);
706 ngx_resolver_free(r
, rn
);
709 /* unlock addr mutex */
712 ngx_resolver_free(r
, ctx
->event
);
715 ngx_resolver_free(r
, ctx
);
722 ngx_resolve_addr_done(ngx_resolver_ctx_t
*ctx
)
726 ngx_resolver_ctx_t
*w
, **p
;
727 ngx_resolver_node_t
*rn
;
731 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
732 "resolve addr done: %i", ctx
->state
);
734 if (ctx
->event
&& ctx
->event
->timer_set
) {
735 ngx_del_timer(ctx
->event
);
738 /* lock addr mutex */
740 if (ctx
->state
== NGX_AGAIN
|| ctx
->state
== NGX_RESOLVE_TIMEDOUT
) {
742 rn
= ngx_resolver_lookup_addr(r
, ctx
->addr
);
760 addr
= ntohl(ctx
->addr
);
762 ngx_log_error(NGX_LOG_ALERT
, r
->log
, 0,
763 "could not cancel %ud.%ud.%ud.%ud resolving",
764 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
765 (addr
>> 8) & 0xff, addr
& 0xff);
770 ngx_resolver_expire(r
, &r
->addr_rbtree
, &r
->addr_expire_queue
);
772 /* unlock addr mutex */
774 /* lock alloc mutex */
777 ngx_resolver_free_locked(r
, ctx
->event
);
780 ngx_resolver_free_locked(r
, ctx
);
782 /* unlock alloc mutex */
787 ngx_resolver_expire(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
, ngx_queue_t
*queue
)
792 ngx_resolver_node_t
*rn
;
794 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolver expire");
798 for (i
= 0; i
< 2; i
++) {
799 if (ngx_queue_empty(queue
)) {
803 q
= ngx_queue_last(queue
);
805 rn
= ngx_queue_data(q
, ngx_resolver_node_t
, queue
);
807 if (now
<= rn
->expire
) {
811 ngx_log_debug2(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
812 "resolver expire \"%*s\"", (size_t) rn
->nlen
, rn
->name
);
816 ngx_rbtree_delete(tree
, &rn
->node
);
818 ngx_resolver_free_node(r
, rn
);
824 ngx_resolver_send_query(ngx_resolver_t
*r
, ngx_resolver_node_t
*rn
)
827 ngx_udp_connection_t
*uc
;
829 uc
= r
->udp_connection
;
831 if (uc
->connection
== NULL
) {
832 if (ngx_udp_connect(uc
) != NGX_OK
) {
836 uc
->connection
->data
= r
;
837 uc
->connection
->read
->handler
= ngx_resolver_read_response
;
838 uc
->connection
->read
->resolver
= 1;
841 n
= ngx_send(uc
->connection
, rn
->query
, rn
->qlen
);
847 if ((size_t) n
!= (size_t) rn
->qlen
) {
848 ngx_log_error(NGX_LOG_CRIT
, &uc
->log
, 0, "send() incomplete");
857 ngx_resolver_resend_handler(ngx_event_t
*ev
)
859 time_t timer
, atimer
, ntimer
;
864 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
865 "resolver resend handler");
867 /* lock name mutex */
869 ntimer
= ngx_resolver_resend(r
, &r
->name_rbtree
, &r
->name_resend_queue
);
871 /* unlock name mutex */
873 /* lock addr mutex */
875 atimer
= ngx_resolver_resend(r
, &r
->addr_rbtree
, &r
->addr_resend_queue
);
877 /* unlock addr mutex */
882 } else if (atimer
== 0) {
886 timer
= (atimer
< ntimer
) ? atimer
: ntimer
;
890 ngx_add_timer(r
->event
, (ngx_msec_t
) (timer
* 1000));
896 ngx_resolver_resend(ngx_resolver_t
*r
, ngx_rbtree_t
*tree
, ngx_queue_t
*queue
)
900 ngx_resolver_node_t
*rn
;
905 if (ngx_queue_empty(queue
)) {
909 q
= ngx_queue_last(queue
);
911 rn
= ngx_queue_data(q
, ngx_resolver_node_t
, queue
);
913 if (now
< rn
->expire
) {
914 return rn
->expire
- now
;
917 ngx_log_debug3(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
918 "resolver resend \"%*s\" %p",
919 (size_t) rn
->nlen
, rn
->name
, rn
->waiting
);
925 if (ngx_resolver_send_query(r
, rn
) == NGX_OK
) {
927 rn
->expire
= now
+ r
->resend_timeout
;
929 ngx_queue_insert_head(queue
, &rn
->queue
);
935 ngx_rbtree_delete(tree
, &rn
->node
);
937 ngx_resolver_free_node(r
, rn
);
943 ngx_resolver_read_response(ngx_event_t
*rev
)
947 u_char buf
[NGX_RESOLVER_UDP_SIZE
];
952 n
= ngx_udp_recv(c
, buf
, NGX_RESOLVER_UDP_SIZE
);
958 ngx_resolver_process_response(c
->data
, buf
, n
);
960 } while (rev
->ready
);
965 ngx_resolver_process_response(ngx_resolver_t
*r
, u_char
*buf
, size_t n
)
969 ngx_uint_t i
, times
, ident
, qident
, flags
, code
, nqs
, nan
,
972 ngx_resolver_qs_t
*qs
;
973 ngx_resolver_node_t
*rn
;
974 ngx_resolver_query_t
*query
;
976 if ((size_t) n
< sizeof(ngx_resolver_query_t
)) {
980 query
= (ngx_resolver_query_t
*) buf
;
982 ident
= (query
->ident_hi
<< 8) + query
->ident_lo
;
983 flags
= (query
->flags_hi
<< 8) + query
->flags_lo
;
984 nqs
= (query
->nqs_hi
<< 8) + query
->nqs_lo
;
985 nan
= (query
->nan_hi
<< 8) + query
->nan_lo
;
987 ngx_log_debug6(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
988 "resolver DNS response %ui fl:%04Xui %ui/%ui/%ui/%ui",
989 ident
, flags
, nqs
, nan
,
990 (query
->nns_hi
<< 8) + query
->nns_lo
,
991 (query
->nar_hi
<< 8) + query
->nar_lo
);
993 if (!(flags
& 0x8000)) {
994 ngx_log_error(r
->log_level
, r
->log
, 0,
995 "invalid DNS response %ui fl:%04Xui", ident
, flags
);
1001 if (code
== NGX_RESOLVE_FORMERR
) {
1005 for (q
= ngx_queue_head(&r
->name_resend_queue
);
1006 q
!= ngx_queue_sentinel(&r
->name_resend_queue
) || times
++ < 100;
1007 q
= ngx_queue_next(q
))
1009 rn
= ngx_queue_data(q
, ngx_resolver_node_t
, queue
);
1010 qident
= (rn
->query
[0] << 8) + rn
->query
[1];
1012 if (qident
== ident
) {
1013 ngx_log_error(r
->log_level
, r
->log
, 0,
1014 "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
1015 code
, ngx_resolver_strerror(code
), ident
,
1016 rn
->nlen
, rn
->name
);
1024 if (code
> NGX_RESOLVE_REFUSED
) {
1029 err
= "invalid number of questions in DNS response";
1033 i
= sizeof(ngx_resolver_query_t
);
1035 while (i
< (ngx_uint_t
) n
) {
1036 if (buf
[i
] == '\0') {
1044 goto short_response
;
1049 err
= "zero-length domain name in DNS response";
1053 if (i
+ sizeof(ngx_resolver_qs_t
) + nan
* (2 + sizeof(ngx_resolver_an_t
))
1056 goto short_response
;
1059 qs
= (ngx_resolver_qs_t
*) &buf
[i
];
1061 qtype
= (qs
->type_hi
<< 8) + qs
->type_lo
;
1062 qclass
= (qs
->class_hi
<< 8) + qs
->class_lo
;
1064 ngx_log_debug2(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1065 "resolver DNS response qt:%ui cl:%ui", qtype
, qclass
);
1068 ngx_log_error(r
->log_level
, r
->log
, 0,
1069 "unknown query class %ui in DNS response", qclass
);
1077 ngx_resolver_process_a(r
, buf
, n
, ident
, code
, nan
,
1078 i
+ sizeof(ngx_resolver_qs_t
));
1082 case NGX_RESOLVE_PTR
:
1084 ngx_resolver_process_ptr(r
, buf
, n
, ident
, code
, nan
);
1089 ngx_log_error(r
->log_level
, r
->log
, 0,
1090 "unknown query type %ui in DNS response", qtype
);
1098 err
= "short dns response";
1102 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1108 ngx_log_error(r
->log_level
, r
->log
, 0,
1109 "DNS error (%ui: %s), query id:%ui",
1110 code
, ngx_resolver_strerror(code
), ident
);
1116 ngx_resolver_process_a(ngx_resolver_t
*r
, u_char
*buf
, size_t last
,
1117 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
, ngx_uint_t ans
)
1123 in_addr_t addr
, *addrs
;
1125 ngx_uint_t qtype
, qident
, naddrs
, a
, i
, n
, start
;
1126 ngx_resolver_an_t
*an
;
1127 ngx_resolver_ctx_t
*ctx
, *next
;
1128 ngx_resolver_node_t
*rn
;
1130 if (ngx_resolver_copy(r
, &name
, buf
, &buf
[12], &buf
[last
]) != NGX_OK
) {
1134 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolver qs:%V", &name
);
1136 hash
= ngx_crc32_short(name
.data
, name
.len
);
1138 /* lock name mutex */
1140 rn
= ngx_resolver_lookup_name(r
, &name
, hash
);
1142 if (rn
== NULL
|| rn
->query
== NULL
) {
1143 ngx_log_error(r
->log_level
, r
->log
, 0,
1144 "unexpected response for %V", &name
);
1148 qident
= (rn
->query
[0] << 8) + rn
->query
[1];
1150 if (ident
!= qident
) {
1151 ngx_log_error(r
->log_level
, r
->log
, 0,
1152 "wrong ident %ui response for %V, expect %ui",
1153 ident
, &name
, qident
);
1157 ngx_resolver_free(r
, name
.data
);
1159 if (code
== 0 && nan
== 0) {
1160 code
= 3; /* NXDOMAIN */
1167 ngx_queue_remove(&rn
->queue
);
1169 ngx_rbtree_delete(&r
->name_rbtree
, &rn
->node
);
1171 ngx_resolver_free_node(r
, rn
);
1173 /* unlock name mutex */
1193 for (a
= 0; a
< nan
; a
++) {
1199 if (buf
[i
] & 0xc0) {
1212 goto short_response
;
1216 if (i
- start
< 2) {
1217 err
= "invalid name in dns response";
1223 if (i
+ sizeof(ngx_resolver_an_t
) >= last
) {
1224 goto short_response
;
1227 an
= (ngx_resolver_an_t
*) &buf
[i
];
1229 qtype
= (an
->type_hi
<< 8) + an
->type_lo
;
1230 len
= (an
->len_hi
<< 8) + an
->len_lo
;
1232 if (qtype
== NGX_RESOLVE_A
) {
1234 i
+= sizeof(ngx_resolver_an_t
);
1236 if (i
+ len
> last
) {
1237 goto short_response
;
1240 addr
= htonl((buf
[i
] << 24) + (buf
[i
+ 1] << 16)
1241 + (buf
[i
+ 2] << 8) + (buf
[i
+ 3]));
1247 } else if (qtype
== NGX_RESOLVE_CNAME
) {
1248 cname
= &buf
[i
] + sizeof(ngx_resolver_an_t
);
1249 i
+= sizeof(ngx_resolver_an_t
) + len
;
1251 } else if (qtype
== NGX_RESOLVE_DNAME
) {
1252 i
+= sizeof(ngx_resolver_an_t
) + len
;
1255 ngx_log_error(r
->log_level
, r
->log
, 0,
1256 "unexpected qtype %ui", qtype
);
1260 ngx_log_debug2(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1261 "resolver naddrs:%ui cname:%p", naddrs
, cname
);
1270 addrs
= ngx_resolver_alloc(r
, naddrs
* sizeof(in_addr_t
));
1271 if (addrs
== NULL
) {
1278 for (a
= 0; a
< nan
; a
++) {
1282 if (buf
[i
] & 0xc0) {
1297 an
= (ngx_resolver_an_t
*) &buf
[i
];
1299 qtype
= (an
->type_hi
<< 8) + an
->type_lo
;
1300 len
= (an
->len_hi
<< 8) + an
->len_lo
;
1302 i
+= sizeof(ngx_resolver_an_t
);
1304 if (qtype
== NGX_RESOLVE_A
) {
1306 addrs
[n
++] = htonl((buf
[i
] << 24) + (buf
[i
+ 1] << 16)
1307 + (buf
[i
+ 2] << 8) + (buf
[i
+ 3]));
1317 rn
->u
.addrs
= addrs
;
1319 addrs
= ngx_resolver_dup(r
, rn
->u
.addrs
,
1320 naddrs
* sizeof(in_addr_t
));
1321 if (addrs
== NULL
) {
1326 rn
->naddrs
= (u_short
) naddrs
;
1328 ngx_queue_remove(&rn
->queue
);
1330 rn
->valid
= ngx_time() + r
->valid
;
1331 rn
->expire
= ngx_time() + r
->expire
;
1333 ngx_queue_insert_head(&r
->name_expire_queue
, &rn
->queue
);
1338 /* unlock name mutex */
1342 ctx
->state
= NGX_OK
;
1343 ctx
->naddrs
= naddrs
;
1344 ctx
->addrs
= (naddrs
== 1) ? &ctx
->addr
: addrs
;
1352 ngx_resolver_free(r
, addrs
);
1361 if (ngx_resolver_copy(r
, &name
, buf
, cname
, &buf
[last
]) != NGX_OK
) {
1365 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1366 "resolver cname:\"%V\"", &name
);
1368 ngx_queue_remove(&rn
->queue
);
1370 rn
->cnlen
= (u_short
) name
.len
;
1371 rn
->u
.cname
= name
.data
;
1372 rn
->valid
= ngx_time() + r
->valid
;
1373 rn
->expire
= ngx_time() + r
->expire
;
1375 ngx_queue_insert_head(&r
->name_expire_queue
, &rn
->queue
);
1383 (void) ngx_resolve_name_locked(r
, ctx
);
1389 ngx_log_error(r
->log_level
, r
->log
, 0,
1390 "no A or CNAME types in DNS responses, unknown query type: %ui",
1396 err
= "short dns response";
1400 /* unlock name mutex */
1402 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1408 /* unlock name mutex */
1410 ngx_resolver_free(r
, name
.data
);
1417 ngx_resolver_process_ptr(ngx_resolver_t
*r
, u_char
*buf
, size_t n
,
1418 ngx_uint_t ident
, ngx_uint_t code
, ngx_uint_t nan
)
1425 ngx_uint_t i
, mask
, qtype
, qclass
, qident
;
1426 ngx_resolver_an_t
*an
;
1427 ngx_resolver_ctx_t
*ctx
, *next
;
1428 ngx_resolver_node_t
*rn
;
1430 if (ngx_resolver_copy(r
, NULL
, buf
, &buf
[12], &buf
[n
]) != NGX_OK
) {
1431 goto invalid_in_addr_arpa
;
1437 for (mask
= 0; mask
< 32; mask
+= 8) {
1440 digit
= ngx_atoi(&buf
[i
], len
);
1441 if (digit
== NGX_ERROR
|| digit
> 255) {
1442 goto invalid_in_addr_arpa
;
1445 addr
+= digit
<< mask
;
1449 if (ngx_strcmp(&buf
[i
], "\7in-addr\4arpa") != 0) {
1450 goto invalid_in_addr_arpa
;
1453 /* lock addr mutex */
1455 rn
= ngx_resolver_lookup_addr(r
, addr
);
1457 if (rn
== NULL
|| rn
->query
== NULL
) {
1458 ngx_log_error(r
->log_level
, r
->log
, 0,
1459 "unexpected response for %ud.%ud.%ud.%ud",
1460 (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
1461 (addr
>> 8) & 0xff, addr
& 0xff);
1465 qident
= (rn
->query
[0] << 8) + rn
->query
[1];
1467 if (ident
!= qident
) {
1468 ngx_log_error(r
->log_level
, r
->log
, 0,
1469 "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui",
1470 ident
, (addr
>> 24) & 0xff, (addr
>> 16) & 0xff,
1471 (addr
>> 8) & 0xff, addr
& 0xff, qident
);
1475 if (code
== 0 && nan
== 0) {
1476 code
= 3; /* NXDOMAIN */
1483 ngx_queue_remove(&rn
->queue
);
1485 ngx_rbtree_delete(&r
->addr_rbtree
, &rn
->node
);
1487 ngx_resolver_free_node(r
, rn
);
1489 /* unlock addr mutex */
1502 i
+= sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t
);
1504 if (i
+ 2 + sizeof(ngx_resolver_an_t
) > (ngx_uint_t
) n
) {
1505 goto short_response
;
1508 /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */
1510 if (buf
[i
] != 0xc0 || buf
[i
+ 1] != 0x0c) {
1511 err
= "invalid in-addr.arpa name in DNS response";
1515 an
= (ngx_resolver_an_t
*) &buf
[i
+ 2];
1517 qtype
= (an
->type_hi
<< 8) + an
->type_lo
;
1518 qclass
= (an
->class_hi
<< 8) + an
->class_lo
;
1519 len
= (an
->len_hi
<< 8) + an
->len_lo
;
1521 ngx_log_debug3(NGX_LOG_DEBUG_CORE
, r
->log
, 0,
1522 "resolver qt:%ui cl:%ui len:%uz", qtype
, qclass
, len
);
1524 i
+= 2 + sizeof(ngx_resolver_an_t
);
1526 if (i
+ len
> (ngx_uint_t
) n
) {
1527 goto short_response
;
1530 if (ngx_resolver_copy(r
, &name
, buf
, &buf
[i
], &buf
[n
]) != NGX_OK
) {
1534 ngx_log_debug1(NGX_LOG_DEBUG_CORE
, r
->log
, 0, "resolver an:%V", &name
);
1536 if (name
.len
!= (size_t) rn
->nlen
1537 || ngx_strncmp(name
.data
, rn
->name
, name
.len
) != 0)
1540 ngx_resolver_free(r
, rn
->name
);
1543 rn
->nlen
= (u_short
) name
.len
;
1544 rn
->name
= name
.data
;
1546 name
.data
= ngx_resolver_dup(r
, rn
->name
, name
.len
);
1547 if (name
.data
== NULL
) {
1552 ngx_queue_remove(&rn
->queue
);
1554 rn
->valid
= ngx_time() + r
->valid
;
1555 rn
->expire
= ngx_time() + r
->expire
;
1557 ngx_queue_insert_head(&r
->addr_expire_queue
, &rn
->queue
);
1562 /* unlock addr mutex */
1566 ctx
->state
= NGX_OK
;
1573 ngx_resolver_free(r
, name
.data
);
1577 invalid_in_addr_arpa
:
1579 ngx_log_error(r
->log_level
, r
->log
, 0,
1580 "invalid in-addr.arpa name in DNS response");
1585 err
= "short DNS response";
1589 /* unlock addr mutex */
1591 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1597 /* unlock addr mutex */
1603 static ngx_resolver_node_t
*
1604 ngx_resolver_lookup_name(ngx_resolver_t
*r
, ngx_str_t
*name
, uint32_t hash
)
1607 ngx_rbtree_node_t
*node
, *sentinel
;
1608 ngx_resolver_node_t
*rn
;
1610 node
= r
->name_rbtree
.root
;
1611 sentinel
= r
->name_rbtree
.sentinel
;
1613 while (node
!= sentinel
) {
1615 if (hash
< node
->key
) {
1620 if (hash
> node
->key
) {
1625 /* hash == node->key */
1628 rn
= (ngx_resolver_node_t
*) node
;
1630 rc
= ngx_memn2cmp(name
->data
, rn
->name
, name
->len
, rn
->nlen
);
1636 node
= (rc
< 0) ? node
->left
: node
->right
;
1638 } while (node
!= sentinel
&& hash
== node
->key
);
1649 static ngx_resolver_node_t
*
1650 ngx_resolver_lookup_addr(ngx_resolver_t
*r
, in_addr_t addr
)
1652 ngx_rbtree_node_t
*node
, *sentinel
;
1654 node
= r
->addr_rbtree
.root
;
1655 sentinel
= r
->addr_rbtree
.sentinel
;
1657 while (node
!= sentinel
) {
1659 if (addr
< node
->key
) {
1664 if (addr
> node
->key
) {
1669 /* addr == node->key */
1671 return (ngx_resolver_node_t
*) node
;
1681 ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t
*temp
,
1682 ngx_rbtree_node_t
*node
, ngx_rbtree_node_t
*sentinel
)
1684 ngx_rbtree_node_t
**p
;
1685 ngx_resolver_node_t
*rn
, *rn_temp
;
1689 if (node
->key
< temp
->key
) {
1693 } else if (node
->key
> temp
->key
) {
1697 } else { /* node->key == temp->key */
1699 rn
= (ngx_resolver_node_t
*) node
;
1700 rn_temp
= (ngx_resolver_node_t
*) temp
;
1702 p
= (ngx_memn2cmp(rn
->name
, rn_temp
->name
, rn
->nlen
, rn_temp
->nlen
)
1703 < 0) ? &temp
->left
: &temp
->right
;
1706 if (*p
== sentinel
) {
1714 node
->parent
= temp
;
1715 node
->left
= sentinel
;
1716 node
->right
= sentinel
;
1722 ngx_resolver_create_name_query(ngx_resolver_node_t
*rn
, ngx_resolver_ctx_t
*ctx
)
1727 ngx_resolver_qs_t
*qs
;
1728 ngx_resolver_query_t
*query
;
1730 nlen
= ctx
->name
.len
? (1 + ctx
->name
.len
+ 1) : 1;
1732 len
= sizeof(ngx_resolver_query_t
) + nlen
+ sizeof(ngx_resolver_qs_t
);
1734 p
= ngx_resolver_alloc(ctx
->resolver
, len
);
1739 rn
->qlen
= (u_short
) len
;
1742 query
= (ngx_resolver_query_t
*) p
;
1744 ident
= ngx_random();
1746 ngx_log_debug2(NGX_LOG_DEBUG_CORE
, ctx
->resolver
->log
, 0,
1747 "resolve: \"%V\" %i", &ctx
->name
, ident
& 0xffff);
1749 query
->ident_hi
= (u_char
) ((ident
>> 8) & 0xff);
1750 query
->ident_lo
= (u_char
) (ident
& 0xff);
1752 /* recursion query */
1753 query
->flags_hi
= 1; query
->flags_lo
= 0;
1756 query
->nqs_hi
= 0; query
->nqs_lo
= 1;
1757 query
->nan_hi
= 0; query
->nan_lo
= 0;
1758 query
->nns_hi
= 0; query
->nns_lo
= 0;
1759 query
->nar_hi
= 0; query
->nar_lo
= 0;
1761 p
+= sizeof(ngx_resolver_query_t
) + nlen
;
1763 qs
= (ngx_resolver_qs_t
*) p
;
1766 qs
->type_hi
= 0; qs
->type_lo
= (u_char
) ctx
->type
;
1768 /* IP query class */
1769 qs
->class_hi
= 0; qs
->class_lo
= 1;
1771 /* convert "www.example.com" to "\3www\7example\3com\0" */
1777 for (s
= ctx
->name
.data
+ ctx
->name
.len
- 1; s
>= ctx
->name
.data
; s
--) {
1784 return NGX_DECLINED
;
1803 ngx_resolver_create_addr_query(ngx_resolver_node_t
*rn
, ngx_resolver_ctx_t
*ctx
)
1809 ngx_resolver_query_t
*query
;
1811 len
= sizeof(ngx_resolver_query_t
)
1812 + sizeof(".255.255.255.255.in-addr.arpa.") - 1
1813 + sizeof(ngx_resolver_qs_t
);
1815 p
= ngx_resolver_alloc(ctx
->resolver
, len
);
1821 query
= (ngx_resolver_query_t
*) p
;
1823 ident
= ngx_random();
1825 query
->ident_hi
= (u_char
) ((ident
>> 8) & 0xff);
1826 query
->ident_lo
= (u_char
) (ident
& 0xff);
1828 /* recursion query */
1829 query
->flags_hi
= 1; query
->flags_lo
= 0;
1832 query
->nqs_hi
= 0; query
->nqs_lo
= 1;
1833 query
->nan_hi
= 0; query
->nan_lo
= 0;
1834 query
->nns_hi
= 0; query
->nns_lo
= 0;
1835 query
->nar_hi
= 0; query
->nar_lo
= 0;
1837 p
+= sizeof(ngx_resolver_query_t
);
1839 for (n
= 0; n
< 32; n
+= 8){
1840 d
= ngx_sprintf(&p
[1], "%ud", (ctx
->addr
>> n
) & 0xff);
1841 *p
= (u_char
) (d
- &p
[1]);
1845 /* query type "PTR", IP query class */
1846 ngx_memcpy(p
, "\7in-addr\4arpa\0\0\14\0\1", 18);
1848 rn
->qlen
= (u_short
)
1849 (p
+ sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t
)
1857 ngx_resolver_copy(ngx_resolver_t
*r
, ngx_str_t
*name
, u_char
*buf
, u_char
*src
,
1869 * compression pointers allow to create endless loop, so we set limit;
1870 * 128 pointers should be enough to store 255-byte name
1873 for (i
= 0; i
< 128; i
++) {
1881 n
= ((n
& 0x3f) << 8) + *p
;
1890 err
= "name is out of response";
1895 err
= "compression pointers loop";
1899 ngx_log_error(r
->log_level
, r
->log
, 0, err
);
1915 dst
= ngx_resolver_alloc(r
, len
);
1926 ngx_memcpy(dst
, src
, n
);
1937 n
= ((n
& 0x3f) << 8) + *src
;
1944 name
->len
= dst
- name
->data
;
1952 ngx_resolver_timeout_handler(ngx_event_t
*ev
)
1954 ngx_resolver_ctx_t
*ctx
;
1958 ctx
->state
= NGX_RESOLVE_TIMEDOUT
;
1965 ngx_resolver_free_node(ngx_resolver_t
*r
, ngx_resolver_node_t
*rn
)
1967 /* lock alloc mutex */
1970 ngx_resolver_free_locked(r
, rn
->query
);
1974 ngx_resolver_free_locked(r
, rn
->name
);
1978 ngx_resolver_free_locked(r
, rn
->u
.cname
);
1981 if (rn
->naddrs
> 1) {
1982 ngx_resolver_free_locked(r
, rn
->u
.addrs
);
1985 ngx_resolver_free_locked(r
, rn
);
1987 /* unlock alloc mutex */
1992 ngx_resolver_alloc(ngx_resolver_t
*r
, size_t size
)
1996 /* lock alloc mutex */
1998 p
= ngx_alloc(size
, r
->log
);
2000 /* unlock alloc mutex */
2007 ngx_resolver_calloc(ngx_resolver_t
*r
, size_t size
)
2011 p
= ngx_resolver_alloc(r
, size
);
2014 ngx_memzero(p
, size
);
2022 ngx_resolver_free(ngx_resolver_t
*r
, void *p
)
2024 /* lock alloc mutex */
2028 /* unlock alloc mutex */
2033 ngx_resolver_free_locked(ngx_resolver_t
*r
, void *p
)
2040 ngx_resolver_dup(ngx_resolver_t
*r
, void *src
, size_t size
)
2044 dst
= ngx_resolver_alloc(r
, size
);
2050 ngx_memcpy(dst
, src
, size
);
2057 ngx_resolver_strerror(ngx_int_t err
)
2059 static char *errors
[] = {
2060 "Format error", /* FORMERR */
2061 "Server failure", /* SERVFAIL */
2062 "Host not found", /* NXDOMAIN */
2063 "Unimplemented", /* NOTIMP */
2064 "Operation refused" /* REFUSED */
2067 if (err
> 0 && err
< 6) {
2068 return errors
[err
- 1];
2071 if (err
== NGX_RESOLVE_TIMEDOUT
) {
2072 return "Operation timed out";
2075 return "Unknown error";
2080 ngx_resolver_log_error(ngx_log_t
*log
, u_char
*buf
, size_t len
)
2083 ngx_udp_connection_t
*uc
;
2088 p
= ngx_snprintf(buf
, len
, " while %s", log
->action
);
2095 p
= ngx_snprintf(p
, len
, ", resolver: %V", &uc
->server
);
2103 ngx_udp_connect(ngx_udp_connection_t
*uc
)
2107 ngx_event_t
*rev
, *wev
;
2109 ngx_connection_t
*c
;
2111 s
= ngx_socket(AF_INET
, SOCK_DGRAM
, 0);
2113 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, &uc
->log
, 0, "UDP socket %d", s
);
2116 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2117 ngx_socket_n
" failed");
2121 c
= ngx_get_connection(s
, &uc
->log
);
2124 if (ngx_close_socket(s
) == -1) {
2125 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2126 ngx_close_socket_n
"failed");
2132 if (ngx_nonblocking(s
) == -1) {
2133 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2134 ngx_nonblocking_n
" failed");
2136 ngx_free_connection(c
);
2138 if (ngx_close_socket(s
) == -1) {
2139 ngx_log_error(NGX_LOG_ALERT
, &uc
->log
, ngx_socket_errno
,
2140 ngx_close_socket_n
" failed");
2149 rev
->log
= &uc
->log
;
2150 wev
->log
= &uc
->log
;
2154 c
->number
= ngx_atomic_fetch_add(ngx_connection_counter
, 1);
2158 /* TODO: lock event when call completion handler */
2160 rev
->lock
= &c
->lock
;
2161 wev
->lock
= &c
->lock
;
2162 rev
->own_lock
= &c
->lock
;
2163 wev
->own_lock
= &c
->lock
;
2167 ngx_log_debug3(NGX_LOG_DEBUG_EVENT
, &uc
->log
, 0,
2168 "connect to %V, fd:%d #%d", &uc
->server
, s
, c
->number
);
2170 rc
= connect(s
, uc
->sockaddr
, uc
->socklen
);
2172 /* TODO: aio, iocp */
2175 ngx_log_error(NGX_LOG_CRIT
, &uc
->log
, ngx_socket_errno
,
2176 "connect() failed");
2181 /* UDP sockets are always ready to write */
2184 if (ngx_add_event
) {
2186 event
= (ngx_event_flags
& NGX_USE_CLEAR_EVENT
) ?
2187 /* kqueue, epoll */ NGX_CLEAR_EVENT
:
2188 /* select, poll, /dev/poll */ NGX_LEVEL_EVENT
;
2189 /* eventport event type has no meaning: oneshot only */
2191 if (ngx_add_event(rev
, NGX_READ_EVENT
, event
) != NGX_OK
) {
2198 if (ngx_add_conn(c
) == NGX_ERROR
) {