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