src/core/ngx_resolver.c - nginx-1.7.10

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. #define NGX_RESOLVER_UDP_SIZE   4096


  9. typedef struct {
  10.     u_char  ident_hi;
  11.     u_char  ident_lo;
  12.     u_char  flags_hi;
  13.     u_char  flags_lo;
  14.     u_char  nqs_hi;
  15.     u_char  nqs_lo;
  16.     u_char  nan_hi;
  17.     u_char  nan_lo;
  18.     u_char  nns_hi;
  19.     u_char  nns_lo;
  20.     u_char  nar_hi;
  21.     u_char  nar_lo;
  22. } ngx_resolver_hdr_t;


  23. typedef struct {
  24.     u_char  type_hi;
  25.     u_char  type_lo;
  26.     u_char  class_hi;
  27.     u_char  class_lo;
  28. } ngx_resolver_qs_t;


  29. typedef struct {
  30.     u_char  type_hi;
  31.     u_char  type_lo;
  32.     u_char  class_hi;
  33.     u_char  class_lo;
  34.     u_char  ttl[4];
  35.     u_char  len_hi;
  36.     u_char  len_lo;
  37. } ngx_resolver_an_t;


  38. #define ngx_resolver_node(n)                                                 \
  39.     (ngx_resolver_node_t *)                                                  \
  40.         ((u_char *) (n) - offsetof(ngx_resolver_node_t, node))


  41. ngx_int_t ngx_udp_connect(ngx_udp_connection_t *uc);


  42. static void ngx_resolver_cleanup(void *data);
  43. static void ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree);
  44. static ngx_int_t ngx_resolve_name_locked(ngx_resolver_t *r,
  45.     ngx_resolver_ctx_t *ctx);
  46. static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree,
  47.     ngx_queue_t *queue);
  48. static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r,
  49.     ngx_resolver_node_t *rn);
  50. static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_node_t *rn,
  51.     ngx_resolver_ctx_t *ctx);
  52. static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_node_t *rn,
  53.     ngx_resolver_ctx_t *ctx);
  54. static void ngx_resolver_resend_handler(ngx_event_t *ev);
  55. static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree,
  56.     ngx_queue_t *queue);
  57. static void ngx_resolver_read_response(ngx_event_t *rev);
  58. static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
  59.     size_t n);
  60. static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
  61.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
  62.     ngx_uint_t nan, ngx_uint_t ans);
  63. static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
  64.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
  65. static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
  66.     ngx_str_t *name, uint32_t hash);
  67. static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
  68.     in_addr_t addr);
  69. static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
  70.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
  71. static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name,
  72.     u_char *buf, u_char *src, u_char *last);
  73. static void ngx_resolver_timeout_handler(ngx_event_t *ev);
  74. static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn);
  75. static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size);
  76. static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
  77. static void ngx_resolver_free(ngx_resolver_t *r, void *p);
  78. static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
  79. static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
  80. static ngx_addr_t *ngx_resolver_export(ngx_resolver_t *r,
  81.     ngx_resolver_node_t *rn, ngx_uint_t rotate);
  82. static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);

  83. #if (NGX_HAVE_INET6)
  84. static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
  85.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
  86. static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
  87.     struct in6_addr *addr, uint32_t hash);
  88. #endif


  89. ngx_resolver_t *
  90. ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
  91. {
  92.     ngx_str_t              s;
  93.     ngx_url_t              u;
  94.     ngx_uint_t             i, j;
  95.     ngx_resolver_t        *r;
  96.     ngx_pool_cleanup_t    *cln;
  97.     ngx_udp_connection_t  *uc;

  98.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  99.     if (cln == NULL) {
  100.         return NULL;
  101.     }

  102.     cln->handler = ngx_resolver_cleanup;

  103.     r = ngx_calloc(sizeof(ngx_resolver_t), cf->log);
  104.     if (r == NULL) {
  105.         return NULL;
  106.     }

  107.     cln->data = r;

  108.     r->event = ngx_calloc(sizeof(ngx_event_t), cf->log);
  109.     if (r->event == NULL) {
  110.         return NULL;
  111.     }

  112.     ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
  113.                     ngx_resolver_rbtree_insert_value);

  114.     ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,
  115.                     ngx_rbtree_insert_value);

  116.     ngx_queue_init(&r->name_resend_queue);
  117.     ngx_queue_init(&r->addr_resend_queue);

  118.     ngx_queue_init(&r->name_expire_queue);
  119.     ngx_queue_init(&r->addr_expire_queue);

  120. #if (NGX_HAVE_INET6)
  121.     r->ipv6 = 1;

  122.     ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel,
  123.                     ngx_resolver_rbtree_insert_addr6_value);

  124.     ngx_queue_init(&r->addr6_resend_queue);

  125.     ngx_queue_init(&r->addr6_expire_queue);
  126. #endif

  127.     r->event->handler = ngx_resolver_resend_handler;
  128.     r->event->data = r;
  129.     r->event->log = &cf->cycle->new_log;
  130.     r->ident = -1;

  131.     r->resend_timeout = 5;
  132.     r->expire = 30;
  133.     r->valid = 0;

  134.     r->log = &cf->cycle->new_log;
  135.     r->log_level = NGX_LOG_ERR;

  136.     if (n) {
  137.         if (ngx_array_init(&r->udp_connections, cf->pool, n,
  138.                            sizeof(ngx_udp_connection_t))
  139.             != NGX_OK)
  140.         {
  141.             return NULL;
  142.         }
  143.     }

  144.     for (i = 0; i < n; i++) {
  145.         if (ngx_strncmp(names[i].data, "valid=", 6) == 0) {
  146.             s.len = names[i].len - 6;
  147.             s.data = names[i].data + 6;

  148.             r->valid = ngx_parse_time(&s, 1);

  149.             if (r->valid == (time_t) NGX_ERROR) {
  150.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  151.                                    "invalid parameter: %V", &names[i]);
  152.                 return NULL;
  153.             }

  154.             continue;
  155.         }

  156. #if (NGX_HAVE_INET6)
  157.         if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {

  158.             if (ngx_strcmp(&names[i].data[5], "on") == 0) {
  159.                 r->ipv6 = 1;

  160.             } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
  161.                 r->ipv6 = 0;

  162.             } else {
  163.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  164.                                    "invalid parameter: %V", &names[i]);
  165.                 return NULL;
  166.             }

  167.             continue;
  168.         }
  169. #endif

  170.         ngx_memzero(&u, sizeof(ngx_url_t));

  171.         u.url = names[i];
  172.         u.default_port = 53;

  173.         if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
  174.             if (u.err) {
  175.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  176.                                    "%s in resolver \"%V\"",
  177.                                    u.err, &u.url);
  178.             }

  179.             return NULL;
  180.         }

  181.         uc = ngx_array_push_n(&r->udp_connections, u.naddrs);
  182.         if (uc == NULL) {
  183.             return NULL;
  184.         }

  185.         ngx_memzero(uc, u.naddrs * sizeof(ngx_udp_connection_t));

  186.         for (j = 0; j < u.naddrs; j++) {
  187.             uc[j].sockaddr = u.addrs[j].sockaddr;
  188.             uc[j].socklen = u.addrs[j].socklen;
  189.             uc[j].server = u.addrs[j].name;
  190.         }
  191.     }

  192.     return r;
  193. }


  194. static void
  195. ngx_resolver_cleanup(void *data)
  196. {
  197.     ngx_resolver_t  *r = data;

  198.     ngx_uint_t             i;
  199.     ngx_udp_connection_t  *uc;

  200.     if (r) {
  201.         ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
  202.                        "cleanup resolver");

  203.         ngx_resolver_cleanup_tree(r, &r->name_rbtree);

  204.         ngx_resolver_cleanup_tree(r, &r->addr_rbtree);

  205. #if (NGX_HAVE_INET6)
  206.         ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
  207. #endif

  208.         if (r->event) {
  209.             ngx_free(r->event);
  210.         }


  211.         uc = r->udp_connections.elts;

  212.         for (i = 0; i < r->udp_connections.nelts; i++) {
  213.             if (uc[i].connection) {
  214.                 ngx_close_connection(uc[i].connection);
  215.             }
  216.         }

  217.         ngx_free(r);
  218.     }
  219. }


  220. static void
  221. ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree)
  222. {
  223.     ngx_resolver_ctx_t   *ctx, *next;
  224.     ngx_resolver_node_t  *rn;

  225.     while (tree->root != tree->sentinel) {

  226.         rn = ngx_resolver_node(ngx_rbtree_min(tree->root, tree->sentinel));

  227.         ngx_queue_remove(&rn->queue);

  228.         for (ctx = rn->waiting; ctx; ctx = next) {
  229.             next = ctx->next;

  230.             if (ctx->event) {
  231.                 ngx_resolver_free(r, ctx->event);
  232.             }

  233.             ngx_resolver_free(r, ctx);
  234.         }

  235.         ngx_rbtree_delete(tree, &rn->node);

  236.         ngx_resolver_free_node(r, rn);
  237.     }
  238. }


  239. ngx_resolver_ctx_t *
  240. ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
  241. {
  242.     in_addr_t            addr;
  243.     ngx_resolver_ctx_t  *ctx;

  244.     if (temp) {
  245.         addr = ngx_inet_addr(temp->name.data, temp->name.len);

  246.         if (addr != INADDR_NONE) {
  247.             temp->resolver = r;
  248.             temp->state = NGX_OK;
  249.             temp->naddrs = 1;
  250.             temp->addrs = &temp->addr;
  251.             temp->addr.sockaddr = (struct sockaddr *) &temp->sin;
  252.             temp->addr.socklen = sizeof(struct sockaddr_in);
  253.             ngx_memzero(&temp->sin, sizeof(struct sockaddr_in));
  254.             temp->sin.sin_family = AF_INET;
  255.             temp->sin.sin_addr.s_addr = addr;
  256.             temp->quick = 1;

  257.             return temp;
  258.         }
  259.     }

  260.     if (r->udp_connections.nelts == 0) {
  261.         return NGX_NO_RESOLVER;
  262.     }

  263.     ctx = ngx_resolver_calloc(r, sizeof(ngx_resolver_ctx_t));

  264.     if (ctx) {
  265.         ctx->resolver = r;
  266.     }

  267.     return ctx;
  268. }


  269. ngx_int_t
  270. ngx_resolve_name(ngx_resolver_ctx_t *ctx)
  271. {
  272.     ngx_int_t        rc;
  273.     ngx_resolver_t  *r;

  274.     r = ctx->resolver;

  275.     if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') {
  276.         ctx->name.len--;
  277.     }

  278.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  279.                    "resolve: \"%V\"", &ctx->name);

  280.     if (ctx->quick) {
  281.         ctx->handler(ctx);
  282.         return NGX_OK;
  283.     }

  284.     /* lock name mutex */

  285.     rc = ngx_resolve_name_locked(r, ctx);

  286.     if (rc == NGX_OK) {
  287.         return NGX_OK;
  288.     }

  289.     /* unlock name mutex */

  290.     if (rc == NGX_AGAIN) {
  291.         return NGX_OK;
  292.     }

  293.     /* NGX_ERROR */

  294.     if (ctx->event) {
  295.         ngx_resolver_free(r, ctx->event);
  296.     }

  297.     ngx_resolver_free(r, ctx);

  298.     return NGX_ERROR;
  299. }


  300. void
  301. ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
  302. {
  303.     uint32_t              hash;
  304.     ngx_resolver_t       *r;
  305.     ngx_resolver_ctx_t   *w, **p;
  306.     ngx_resolver_node_t  *rn;

  307.     r = ctx->resolver;

  308.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  309.                    "resolve name done: %i", ctx->state);

  310.     if (ctx->quick) {
  311.         return;
  312.     }

  313.     if (ctx->event && ctx->event->timer_set) {
  314.         ngx_del_timer(ctx->event);
  315.     }

  316.     /* lock name mutex */

  317.     if (ctx->state == NGX_AGAIN) {

  318.         hash = ngx_crc32_short(ctx->name.data, ctx->name.len);

  319.         rn = ngx_resolver_lookup_name(r, &ctx->name, hash);

  320.         if (rn) {
  321.             p = &rn->waiting;
  322.             w = rn->waiting;

  323.             while (w) {
  324.                 if (w == ctx) {
  325.                     *p = w->next;

  326.                     goto done;
  327.                 }

  328.                 p = &w->next;
  329.                 w = w->next;
  330.             }
  331.         }

  332.         ngx_log_error(NGX_LOG_ALERT, r->log, 0,
  333.                       "could not cancel %V resolving", &ctx->name);
  334.     }

  335. done:

  336.     ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue);

  337.     /* unlock name mutex */

  338.     /* lock alloc mutex */

  339.     if (ctx->event) {
  340.         ngx_resolver_free_locked(r, ctx->event);
  341.     }

  342.     ngx_resolver_free_locked(r, ctx);

  343.     /* unlock alloc mutex */
  344. }


  345. static ngx_int_t
  346. ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
  347. {
  348.     uint32_t              hash;
  349.     ngx_int_t             rc;
  350.     ngx_uint_t            naddrs;
  351.     ngx_addr_t           *addrs;
  352.     ngx_resolver_ctx_t   *next;
  353.     ngx_resolver_node_t  *rn;

  354.     ngx_strlow(ctx->name.data, ctx->name.data, ctx->name.len);

  355.     hash = ngx_crc32_short(ctx->name.data, ctx->name.len);

  356.     rn = ngx_resolver_lookup_name(r, &ctx->name, hash);

  357.     if (rn) {

  358.         if (rn->valid >= ngx_time()) {

  359.             ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached");

  360.             ngx_queue_remove(&rn->queue);

  361.             rn->expire = ngx_time() + r->expire;

  362.             ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);

  363.             naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
  364. #if (NGX_HAVE_INET6)
  365.             naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
  366. #endif

  367.             if (naddrs) {

  368.                 if (naddrs == 1 && rn->naddrs == 1) {
  369.                     addrs = NULL;

  370.                 } else {
  371.                     addrs = ngx_resolver_export(r, rn, 1);
  372.                     if (addrs == NULL) {
  373.                         return NGX_ERROR;
  374.                     }
  375.                 }

  376.                 ctx->next = rn->waiting;
  377.                 rn->waiting = NULL;

  378.                 /* unlock name mutex */

  379.                 do {
  380.                     ctx->state = NGX_OK;
  381.                     ctx->naddrs = naddrs;

  382.                     if (addrs == NULL) {
  383.                         ctx->addrs = &ctx->addr;
  384.                         ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
  385.                         ctx->addr.socklen = sizeof(struct sockaddr_in);
  386.                         ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
  387.                         ctx->sin.sin_family = AF_INET;
  388.                         ctx->sin.sin_addr.s_addr = rn->u.addr;

  389.                     } else {
  390.                         ctx->addrs = addrs;
  391.                     }

  392.                     next = ctx->next;

  393.                     ctx->handler(ctx);

  394.                     ctx = next;
  395.                 } while (ctx);

  396.                 if (addrs != NULL) {
  397.                     ngx_resolver_free(r, addrs->sockaddr);
  398.                     ngx_resolver_free(r, addrs);
  399.                 }

  400.                 return NGX_OK;
  401.             }

  402.             /* NGX_RESOLVE_CNAME */

  403.             if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) {

  404.                 ctx->name.len = rn->cnlen;
  405.                 ctx->name.data = rn->u.cname;

  406.                 return ngx_resolve_name_locked(r, ctx);
  407.             }

  408.             ctx->next = rn->waiting;
  409.             rn->waiting = NULL;

  410.             /* unlock name mutex */

  411.             do {
  412.                 ctx->state = NGX_RESOLVE_NXDOMAIN;
  413.                 next = ctx->next;

  414.                 ctx->handler(ctx);

  415.                 ctx = next;
  416.             } while (ctx);

  417.             return NGX_OK;
  418.         }

  419.         if (rn->waiting) {

  420.             ctx->next = rn->waiting;
  421.             rn->waiting = ctx;
  422.             ctx->state = NGX_AGAIN;

  423.             return NGX_AGAIN;
  424.         }

  425.         ngx_queue_remove(&rn->queue);

  426.         /* lock alloc mutex */

  427.         if (rn->query) {
  428.             ngx_resolver_free_locked(r, rn->query);
  429.             rn->query = NULL;
  430. #if (NGX_HAVE_INET6)
  431.             rn->query6 = NULL;
  432. #endif
  433.         }

  434.         if (rn->cnlen) {
  435.             ngx_resolver_free_locked(r, rn->u.cname);
  436.         }

  437.         if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
  438.             ngx_resolver_free_locked(r, rn->u.addrs);
  439.         }

  440. #if (NGX_HAVE_INET6)
  441.         if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
  442.             ngx_resolver_free_locked(r, rn->u6.addrs6);
  443.         }
  444. #endif

  445.         /* unlock alloc mutex */

  446.     } else {

  447.         rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
  448.         if (rn == NULL) {
  449.             return NGX_ERROR;
  450.         }

  451.         rn->name = ngx_resolver_dup(r, ctx->name.data, ctx->name.len);
  452.         if (rn->name == NULL) {
  453.             ngx_resolver_free(r, rn);
  454.             return NGX_ERROR;
  455.         }

  456.         rn->node.key = hash;
  457.         rn->nlen = (u_short) ctx->name.len;
  458.         rn->query = NULL;
  459. #if (NGX_HAVE_INET6)
  460.         rn->query6 = NULL;
  461. #endif

  462.         ngx_rbtree_insert(&r->name_rbtree, &rn->node);
  463.     }

  464.     rc = ngx_resolver_create_name_query(rn, ctx);

  465.     if (rc == NGX_ERROR) {
  466.         goto failed;
  467.     }

  468.     if (rc == NGX_DECLINED) {
  469.         ngx_rbtree_delete(&r->name_rbtree, &rn->node);

  470.         ngx_resolver_free(r, rn->query);
  471.         ngx_resolver_free(r, rn->name);
  472.         ngx_resolver_free(r, rn);

  473.         ctx->state = NGX_RESOLVE_NXDOMAIN;
  474.         ctx->handler(ctx);

  475.         return NGX_OK;
  476.     }

  477.     rn->naddrs = (u_short) -1;
  478. #if (NGX_HAVE_INET6)
  479.     rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
  480. #endif

  481.     if (ngx_resolver_send_query(r, rn) != NGX_OK) {
  482.         goto failed;
  483.     }

  484.     if (ctx->event == NULL) {
  485.         ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
  486.         if (ctx->event == NULL) {
  487.             goto failed;
  488.         }

  489.         ctx->event->handler = ngx_resolver_timeout_handler;
  490.         ctx->event->data = rn;
  491.         ctx->event->log = r->log;
  492.         rn->ident = -1;

  493.         ngx_add_timer(ctx->event, ctx->timeout);
  494.     }

  495.     if (ngx_queue_empty(&r->name_resend_queue)) {
  496.         ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
  497.     }

  498.     rn->expire = ngx_time() + r->resend_timeout;

  499.     ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);

  500.     rn->code = 0;
  501.     rn->cnlen = 0;
  502.     rn->valid = 0;
  503.     rn->ttl = NGX_MAX_UINT32_VALUE;
  504.     rn->waiting = ctx;

  505.     ctx->state = NGX_AGAIN;

  506.     return NGX_AGAIN;

  507. failed:

  508.     ngx_rbtree_delete(&r->name_rbtree, &rn->node);

  509.     if (rn->query) {
  510.         ngx_resolver_free(r, rn->query);
  511.     }

  512.     ngx_resolver_free(r, rn->name);

  513.     ngx_resolver_free(r, rn);

  514.     return NGX_ERROR;
  515. }


  516. ngx_int_t
  517. ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
  518. {
  519.     u_char               *name;
  520.     in_addr_t             addr;
  521.     ngx_queue_t          *resend_queue, *expire_queue;
  522.     ngx_rbtree_t         *tree;
  523.     ngx_resolver_t       *r;
  524.     struct sockaddr_in   *sin;
  525.     ngx_resolver_node_t  *rn;
  526. #if (NGX_HAVE_INET6)
  527.     uint32_t              hash;
  528.     struct sockaddr_in6  *sin6;
  529. #endif

  530. #if (NGX_SUPPRESS_WARN)
  531.     addr = 0;
  532. #if (NGX_HAVE_INET6)
  533.     hash = 0;
  534.     sin6 = NULL;
  535. #endif
  536. #endif

  537.     r = ctx->resolver;

  538.     switch (ctx->addr.sockaddr->sa_family) {

  539. #if (NGX_HAVE_INET6)
  540.     case AF_INET6:
  541.         sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
  542.         hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);

  543.         /* lock addr mutex */

  544.         rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);

  545.         tree = &r->addr6_rbtree;
  546.         resend_queue = &r->addr6_resend_queue;
  547.         expire_queue = &r->addr6_expire_queue;

  548.         break;
  549. #endif

  550.     default: /* AF_INET */
  551.         sin = (struct sockaddr_in *) ctx->addr.sockaddr;
  552.         addr = ntohl(sin->sin_addr.s_addr);

  553.         /* lock addr mutex */

  554.         rn = ngx_resolver_lookup_addr(r, addr);

  555.         tree = &r->addr_rbtree;
  556.         resend_queue = &r->addr_resend_queue;
  557.         expire_queue = &r->addr_expire_queue;
  558.     }

  559.     if (rn) {

  560.         if (rn->valid >= ngx_time()) {

  561.             ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached");

  562.             ngx_queue_remove(&rn->queue);

  563.             rn->expire = ngx_time() + r->expire;

  564.             ngx_queue_insert_head(expire_queue, &rn->queue);

  565.             name = ngx_resolver_dup(r, rn->name, rn->nlen);
  566.             if (name == NULL) {
  567.                 goto failed;
  568.             }

  569.             ctx->name.len = rn->nlen;
  570.             ctx->name.data = name;

  571.             /* unlock addr mutex */

  572.             ctx->state = NGX_OK;

  573.             ctx->handler(ctx);

  574.             ngx_resolver_free(r, name);

  575.             return NGX_OK;
  576.         }

  577.         if (rn->waiting) {

  578.             ctx->next = rn->waiting;
  579.             rn->waiting = ctx;
  580.             ctx->state = NGX_AGAIN;

  581.             /* unlock addr mutex */

  582.             return NGX_OK;
  583.         }

  584.         ngx_queue_remove(&rn->queue);

  585.         ngx_resolver_free(r, rn->query);
  586.         rn->query = NULL;
  587. #if (NGX_HAVE_INET6)
  588.         rn->query6 = NULL;
  589. #endif

  590.     } else {
  591.         rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
  592.         if (rn == NULL) {
  593.             goto failed;
  594.         }

  595.         switch (ctx->addr.sockaddr->sa_family) {

  596. #if (NGX_HAVE_INET6)
  597.         case AF_INET6:
  598.             rn->addr6 = sin6->sin6_addr;
  599.             rn->node.key = hash;
  600.             break;
  601. #endif

  602.         default: /* AF_INET */
  603.             rn->node.key = addr;
  604.         }

  605.         rn->query = NULL;
  606. #if (NGX_HAVE_INET6)
  607.         rn->query6 = NULL;
  608. #endif

  609.         ngx_rbtree_insert(tree, &rn->node);
  610.     }

  611.     if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) {
  612.         goto failed;
  613.     }

  614.     rn->naddrs = (u_short) -1;
  615. #if (NGX_HAVE_INET6)
  616.     rn->naddrs6 = (u_short) -1;
  617. #endif

  618.     if (ngx_resolver_send_query(r, rn) != NGX_OK) {
  619.         goto failed;
  620.     }

  621.     ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
  622.     if (ctx->event == NULL) {
  623.         goto failed;
  624.     }

  625.     ctx->event->handler = ngx_resolver_timeout_handler;
  626.     ctx->event->data = rn;
  627.     ctx->event->log = r->log;
  628.     rn->ident = -1;

  629.     ngx_add_timer(ctx->event, ctx->timeout);

  630.     if (ngx_queue_empty(resend_queue)) {
  631.         ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
  632.     }

  633.     rn->expire = ngx_time() + r->resend_timeout;

  634.     ngx_queue_insert_head(resend_queue, &rn->queue);

  635.     rn->code = 0;
  636.     rn->cnlen = 0;
  637.     rn->name = NULL;
  638.     rn->nlen = 0;
  639.     rn->valid = 0;
  640.     rn->ttl = NGX_MAX_UINT32_VALUE;
  641.     rn->waiting = ctx;

  642.     /* unlock addr mutex */

  643.     ctx->state = NGX_AGAIN;

  644.     return NGX_OK;

  645. failed:

  646.     if (rn) {
  647.         ngx_rbtree_delete(tree, &rn->node);

  648.         if (rn->query) {
  649.             ngx_resolver_free(r, rn->query);
  650.         }

  651.         ngx_resolver_free(r, rn);
  652.     }

  653.     /* unlock addr mutex */

  654.     if (ctx->event) {
  655.         ngx_resolver_free(r, ctx->event);
  656.     }

  657.     ngx_resolver_free(r, ctx);

  658.     return NGX_ERROR;
  659. }


  660. void
  661. ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
  662. {
  663.     in_addr_t             addr;
  664.     ngx_queue_t          *expire_queue;
  665.     ngx_rbtree_t         *tree;
  666.     ngx_resolver_t       *r;
  667.     ngx_resolver_ctx_t   *w, **p;
  668.     struct sockaddr_in   *sin;
  669.     ngx_resolver_node_t  *rn;
  670. #if (NGX_HAVE_INET6)
  671.     uint32_t              hash;
  672.     struct sockaddr_in6  *sin6;
  673. #endif

  674.     r = ctx->resolver;

  675.     switch (ctx->addr.sockaddr->sa_family) {

  676. #if (NGX_HAVE_INET6)
  677.     case AF_INET6:
  678.         tree = &r->addr6_rbtree;
  679.         expire_queue = &r->addr6_expire_queue;
  680.         break;
  681. #endif

  682.     default: /* AF_INET */
  683.         tree = &r->addr_rbtree;
  684.         expire_queue = &r->addr_expire_queue;
  685.     }

  686.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  687.                    "resolve addr done: %i", ctx->state);

  688.     if (ctx->event && ctx->event->timer_set) {
  689.         ngx_del_timer(ctx->event);
  690.     }

  691.     /* lock addr mutex */

  692.     if (ctx->state == NGX_AGAIN) {

  693.         switch (ctx->addr.sockaddr->sa_family) {

  694. #if (NGX_HAVE_INET6)
  695.         case AF_INET6:
  696.             sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
  697.             hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);
  698.             rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);
  699.             break;
  700. #endif

  701.         default: /* AF_INET */
  702.             sin = (struct sockaddr_in *) ctx->addr.sockaddr;
  703.             addr = ntohl(sin->sin_addr.s_addr);
  704.             rn = ngx_resolver_lookup_addr(r, addr);
  705.         }

  706.         if (rn) {
  707.             p = &rn->waiting;
  708.             w = rn->waiting;

  709.             while (w) {
  710.                 if (w == ctx) {
  711.                     *p = w->next;

  712.                     goto done;
  713.                 }

  714.                 p = &w->next;
  715.                 w = w->next;
  716.             }
  717.         }

  718.         {
  719.             u_char     text[NGX_SOCKADDR_STRLEN];
  720.             ngx_str_t  addrtext;

  721.             addrtext.data = text;
  722.             addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen,
  723.                                          text, NGX_SOCKADDR_STRLEN, 0);

  724.             ngx_log_error(NGX_LOG_ALERT, r->log, 0,
  725.                           "could not cancel %V resolving", &addrtext);
  726.         }
  727.     }

  728. done:

  729.     ngx_resolver_expire(r, tree, expire_queue);

  730.     /* unlock addr mutex */

  731.     /* lock alloc mutex */

  732.     if (ctx->event) {
  733.         ngx_resolver_free_locked(r, ctx->event);
  734.     }

  735.     ngx_resolver_free_locked(r, ctx);

  736.     /* unlock alloc mutex */
  737. }


  738. static void
  739. ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
  740. {
  741.     time_t                now;
  742.     ngx_uint_t            i;
  743.     ngx_queue_t          *q;
  744.     ngx_resolver_node_t  *rn;

  745.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver expire");

  746.     now = ngx_time();

  747.     for (i = 0; i < 2; i++) {
  748.         if (ngx_queue_empty(queue)) {
  749.             return;
  750.         }

  751.         q = ngx_queue_last(queue);

  752.         rn = ngx_queue_data(q, ngx_resolver_node_t, queue);

  753.         if (now <= rn->expire) {
  754.             return;
  755.         }

  756.         ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
  757.                        "resolver expire \"%*s\"", (size_t) rn->nlen, rn->name);

  758.         ngx_queue_remove(q);

  759.         ngx_rbtree_delete(tree, &rn->node);

  760.         ngx_resolver_free_node(r, rn);
  761.     }
  762. }


  763. static ngx_int_t
  764. ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
  765. {
  766.     ssize_t                n;
  767.     ngx_udp_connection_t  *uc;

  768.     uc = r->udp_connections.elts;

  769.     uc = &uc[r->last_connection++];
  770.     if (r->last_connection == r->udp_connections.nelts) {
  771.         r->last_connection = 0;
  772.     }

  773.     if (uc->connection == NULL) {

  774.         uc->log = *r->log;
  775.         uc->log.handler = ngx_resolver_log_error;
  776.         uc->log.data = uc;
  777.         uc->log.action = "resolving";

  778.         if (ngx_udp_connect(uc) != NGX_OK) {
  779.             return NGX_ERROR;
  780.         }

  781.         uc->connection->data = r;
  782.         uc->connection->read->handler = ngx_resolver_read_response;
  783.         uc->connection->read->resolver = 1;
  784.     }

  785.     if (rn->naddrs == (u_short) -1) {
  786.         n = ngx_send(uc->connection, rn->query, rn->qlen);

  787.         if (n == -1) {
  788.             return NGX_ERROR;
  789.         }

  790.         if ((size_t) n != (size_t) rn->qlen) {
  791.             ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
  792.             return NGX_ERROR;
  793.         }
  794.     }

  795. #if (NGX_HAVE_INET6)
  796.     if (rn->query6 && rn->naddrs6 == (u_short) -1) {
  797.         n = ngx_send(uc->connection, rn->query6, rn->qlen);

  798.         if (n == -1) {
  799.             return NGX_ERROR;
  800.         }

  801.         if ((size_t) n != (size_t) rn->qlen) {
  802.             ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
  803.             return NGX_ERROR;
  804.         }
  805.     }
  806. #endif

  807.     return NGX_OK;
  808. }


  809. static void
  810. ngx_resolver_resend_handler(ngx_event_t *ev)
  811. {
  812.     time_t           timer, atimer, ntimer;
  813. #if (NGX_HAVE_INET6)
  814.     time_t           a6timer;
  815. #endif
  816.     ngx_resolver_t  *r;

  817.     r = ev->data;

  818.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0,
  819.                    "resolver resend handler");

  820.     /* lock name mutex */

  821.     ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue);

  822.     /* unlock name mutex */

  823.     /* lock addr mutex */

  824.     atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue);

  825.     /* unlock addr mutex */

  826. #if (NGX_HAVE_INET6)

  827.     /* lock addr6 mutex */

  828.     a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue);

  829.     /* unlock addr6 mutex */

  830. #endif

  831.     timer = ntimer;

  832.     if (timer == 0) {
  833.         timer = atimer;

  834.     } else if (atimer) {
  835.         timer = ngx_min(timer, atimer);
  836.     }

  837. #if (NGX_HAVE_INET6)

  838.     if (timer == 0) {
  839.         timer = a6timer;

  840.     } else if (a6timer) {
  841.         timer = ngx_min(timer, a6timer);
  842.     }

  843. #endif

  844.     if (timer) {
  845.         ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000));
  846.     }
  847. }


  848. static time_t
  849. ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
  850. {
  851.     time_t                now;
  852.     ngx_queue_t          *q;
  853.     ngx_resolver_node_t  *rn;

  854.     now = ngx_time();

  855.     for ( ;; ) {
  856.         if (ngx_queue_empty(queue)) {
  857.             return 0;
  858.         }

  859.         q = ngx_queue_last(queue);

  860.         rn = ngx_queue_data(q, ngx_resolver_node_t, queue);

  861.         if (now < rn->expire) {
  862.             return rn->expire - now;
  863.         }

  864.         ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
  865.                        "resolver resend \"%*s\" %p",
  866.                        (size_t) rn->nlen, rn->name, rn->waiting);

  867.         ngx_queue_remove(q);

  868.         if (rn->waiting) {

  869.             (void) ngx_resolver_send_query(r, rn);

  870.             rn->expire = now + r->resend_timeout;

  871.             ngx_queue_insert_head(queue, q);

  872.             continue;
  873.         }

  874.         ngx_rbtree_delete(tree, &rn->node);

  875.         ngx_resolver_free_node(r, rn);
  876.     }
  877. }


  878. static void
  879. ngx_resolver_read_response(ngx_event_t *rev)
  880. {
  881.     ssize_t            n;
  882.     ngx_connection_t  *c;
  883.     u_char             buf[NGX_RESOLVER_UDP_SIZE];

  884.     c = rev->data;

  885.     do {
  886.         n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE);

  887.         if (n < 0) {
  888.             return;
  889.         }

  890.         ngx_resolver_process_response(c->data, buf, n);

  891.     } while (rev->ready);
  892. }


  893. static void
  894. ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n)
  895. {
  896.     char                 *err;
  897.     ngx_uint_t            i, times, ident, qident, flags, code, nqs, nan,
  898.                           qtype, qclass;
  899. #if (NGX_HAVE_INET6)
  900.     ngx_uint_t            qident6;
  901. #endif
  902.     ngx_queue_t          *q;
  903.     ngx_resolver_qs_t    *qs;
  904.     ngx_resolver_hdr_t   *response;
  905.     ngx_resolver_node_t  *rn;

  906.     if (n < sizeof(ngx_resolver_hdr_t)) {
  907.         goto short_response;
  908.     }

  909.     response = (ngx_resolver_hdr_t *) buf;

  910.     ident = (response->ident_hi << 8) + response->ident_lo;
  911.     flags = (response->flags_hi << 8) + response->flags_lo;
  912.     nqs = (response->nqs_hi << 8) + response->nqs_lo;
  913.     nan = (response->nan_hi << 8) + response->nan_lo;

  914.     ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
  915.                    "resolver DNS response %ui fl:%04Xui %ui/%ui/%ud/%ud",
  916.                    ident, flags, nqs, nan,
  917.                    (response->nns_hi << 8) + response->nns_lo,
  918.                    (response->nar_hi << 8) + response->nar_lo);

  919.     /* response to a standard query */
  920.     if ((flags & 0xf870) != 0x8000) {
  921.         ngx_log_error(r->log_level, r->log, 0,
  922.                       "invalid DNS response %ui fl:%04Xui", ident, flags);
  923.         return;
  924.     }

  925.     code = flags & 0xf;

  926.     if (code == NGX_RESOLVE_FORMERR) {

  927.         times = 0;

  928.         for (q = ngx_queue_head(&r->name_resend_queue);
  929.              q != ngx_queue_sentinel(&r->name_resend_queue) || times++ < 100;
  930.              q = ngx_queue_next(q))
  931.         {
  932.             rn = ngx_queue_data(q, ngx_resolver_node_t, queue);
  933.             qident = (rn->query[0] << 8) + rn->query[1];

  934.             if (qident == ident) {
  935.                 goto dns_error_name;
  936.             }

  937. #if (NGX_HAVE_INET6)
  938.             if (rn->query6) {
  939.                 qident6 = (rn->query6[0] << 8) + rn->query6[1];

  940.                 if (qident6 == ident) {
  941.                     goto dns_error_name;
  942.                 }
  943.             }
  944. #endif
  945.         }

  946.         goto dns_error;
  947.     }

  948.     if (code > NGX_RESOLVE_REFUSED) {
  949.         goto dns_error;
  950.     }

  951.     if (nqs != 1) {
  952.         err = "invalid number of questions in DNS response";
  953.         goto done;
  954.     }

  955.     i = sizeof(ngx_resolver_hdr_t);

  956.     while (i < (ngx_uint_t) n) {
  957.         if (buf[i] == '\0') {
  958.             goto found;
  959.         }

  960.         i += 1 + buf[i];
  961.     }

  962.     goto short_response;

  963. found:

  964.     if (i++ == sizeof(ngx_resolver_hdr_t)) {
  965.         err = "zero-length domain name in DNS response";
  966.         goto done;
  967.     }

  968.     if (i + sizeof(ngx_resolver_qs_t) + nan * (2 + sizeof(ngx_resolver_an_t))
  969.         > (ngx_uint_t) n)
  970.     {
  971.         goto short_response;
  972.     }

  973.     qs = (ngx_resolver_qs_t *) &buf[i];

  974.     qtype = (qs->type_hi << 8) + qs->type_lo;
  975.     qclass = (qs->class_hi << 8) + qs->class_lo;

  976.     ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
  977.                    "resolver DNS response qt:%ui cl:%ui", qtype, qclass);

  978.     if (qclass != 1) {
  979.         ngx_log_error(r->log_level, r->log, 0,
  980.                       "unknown query class %ui in DNS response", qclass);
  981.         return;
  982.     }

  983.     switch (qtype) {

  984.     case NGX_RESOLVE_A:
  985. #if (NGX_HAVE_INET6)
  986.     case NGX_RESOLVE_AAAA:
  987. #endif

  988.         ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan,
  989.                                i + sizeof(ngx_resolver_qs_t));

  990.         break;

  991.     case NGX_RESOLVE_PTR:

  992.         ngx_resolver_process_ptr(r, buf, n, ident, code, nan);

  993.         break;

  994.     default:
  995.         ngx_log_error(r->log_level, r->log, 0,
  996.                       "unknown query type %ui in DNS response", qtype);
  997.         return;
  998.     }

  999.     return;

  1000. short_response:

  1001.     err = "short DNS response";

  1002. done:

  1003.     ngx_log_error(r->log_level, r->log, 0, err);

  1004.     return;

  1005. dns_error_name:

  1006.     ngx_log_error(r->log_level, r->log, 0,
  1007.                   "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
  1008.                   code, ngx_resolver_strerror(code), ident,
  1009.                   rn->nlen, rn->name);
  1010.     return;

  1011. dns_error:

  1012.     ngx_log_error(r->log_level, r->log, 0,
  1013.                   "DNS error (%ui: %s), query id:%ui",
  1014.                   code, ngx_resolver_strerror(code), ident);
  1015.     return;
  1016. }


  1017. static void
  1018. ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last,
  1019.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
  1020.     ngx_uint_t nan, ngx_uint_t ans)
  1021. {
  1022.     char                 *err;
  1023.     u_char               *cname;
  1024.     size_t                len;
  1025.     int32_t               ttl;
  1026.     uint32_t              hash;
  1027.     in_addr_t            *addr;
  1028.     ngx_str_t             name;
  1029.     ngx_addr_t           *addrs;
  1030.     ngx_uint_t            type, class, qident, naddrs, a, i, n, start;
  1031. #if (NGX_HAVE_INET6)
  1032.     struct in6_addr      *addr6;
  1033. #endif
  1034.     ngx_resolver_an_t    *an;
  1035.     ngx_resolver_ctx_t   *ctx, *next;
  1036.     ngx_resolver_node_t  *rn;

  1037.     if (ngx_resolver_copy(r, &name, buf,
  1038.                           buf + sizeof(ngx_resolver_hdr_t), buf + last)
  1039.         != NGX_OK)
  1040.     {
  1041.         return;
  1042.     }

  1043.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);

  1044.     hash = ngx_crc32_short(name.data, name.len);

  1045.     /* lock name mutex */

  1046.     rn = ngx_resolver_lookup_name(r, &name, hash);

  1047.     if (rn == NULL) {
  1048.         ngx_log_error(r->log_level, r->log, 0,
  1049.                       "unexpected response for %V", &name);
  1050.         ngx_resolver_free(r, name.data);
  1051.         goto failed;
  1052.     }

  1053.     switch (qtype) {

  1054. #if (NGX_HAVE_INET6)
  1055.     case NGX_RESOLVE_AAAA:

  1056.         if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
  1057.             ngx_log_error(r->log_level, r->log, 0,
  1058.                           "unexpected response for %V", &name);
  1059.             ngx_resolver_free(r, name.data);
  1060.             goto failed;
  1061.         }

  1062.         qident = (rn->query6[0] << 8) + rn->query6[1];

  1063.         break;
  1064. #endif

  1065.     default: /* NGX_RESOLVE_A */

  1066.         if (rn->query == NULL || rn->naddrs != (u_short) -1) {
  1067.             ngx_log_error(r->log_level, r->log, 0,
  1068.                           "unexpected response for %V", &name);
  1069.             ngx_resolver_free(r, name.data);
  1070.             goto failed;
  1071.         }

  1072.         qident = (rn->query[0] << 8) + rn->query[1];
  1073.     }

  1074.     if (ident != qident) {
  1075.         ngx_log_error(r->log_level, r->log, 0,
  1076.                       "wrong ident %ui response for %V, expect %ui",
  1077.                       ident, &name, qident);
  1078.         ngx_resolver_free(r, name.data);
  1079.         goto failed;
  1080.     }

  1081.     ngx_resolver_free(r, name.data);

  1082.     if (code == 0 && rn->code) {
  1083.         code = rn->code;
  1084.     }

  1085.     if (code == 0 && nan == 0) {

  1086. #if (NGX_HAVE_INET6)
  1087.         switch (qtype) {

  1088.         case NGX_RESOLVE_AAAA:

  1089.             rn->naddrs6 = 0;

  1090.             if (rn->naddrs == (u_short) -1) {
  1091.                 goto next;
  1092.             }

  1093.             if (rn->naddrs) {
  1094.                 goto export;
  1095.             }

  1096.             break;

  1097.         default: /* NGX_RESOLVE_A */

  1098.             rn->naddrs = 0;

  1099.             if (rn->naddrs6 == (u_short) -1) {
  1100.                 goto next;
  1101.             }

  1102.             if (rn->naddrs6) {
  1103.                 goto export;
  1104.             }
  1105.         }
  1106. #endif

  1107.         code = NGX_RESOLVE_NXDOMAIN;
  1108.     }

  1109.     if (code) {

  1110. #if (NGX_HAVE_INET6)
  1111.         switch (qtype) {

  1112.         case NGX_RESOLVE_AAAA:

  1113.             rn->naddrs6 = 0;

  1114.             if (rn->naddrs == (u_short) -1) {
  1115.                 rn->code = (u_char) code;
  1116.                 goto next;
  1117.             }

  1118.             break;

  1119.         default: /* NGX_RESOLVE_A */

  1120.             rn->naddrs = 0;

  1121.             if (rn->naddrs6 == (u_short) -1) {
  1122.                 rn->code = (u_char) code;
  1123.                 goto next;
  1124.             }
  1125.         }
  1126. #endif

  1127.         next = rn->waiting;
  1128.         rn->waiting = NULL;

  1129.         ngx_queue_remove(&rn->queue);

  1130.         ngx_rbtree_delete(&r->name_rbtree, &rn->node);

  1131.         /* unlock name mutex */

  1132.         while (next) {
  1133.             ctx = next;
  1134.             ctx->state = code;
  1135.             next = ctx->next;

  1136.             ctx->handler(ctx);
  1137.         }

  1138.         ngx_resolver_free_node(r, rn);

  1139.         return;
  1140.     }

  1141.     i = ans;
  1142.     naddrs = 0;
  1143.     cname = NULL;

  1144.     for (a = 0; a < nan; a++) {

  1145.         start = i;

  1146.         while (i < last) {

  1147.             if (buf[i] & 0xc0) {
  1148.                 i += 2;
  1149.                 goto found;
  1150.             }

  1151.             if (buf[i] == 0) {
  1152.                 i++;
  1153.                 goto test_length;
  1154.             }

  1155.             i += 1 + buf[i];
  1156.         }

  1157.         goto short_response;

  1158.     test_length:

  1159.         if (i - start < 2) {
  1160.             err = "invalid name in DNS response";
  1161.             goto invalid;
  1162.         }

  1163.     found:

  1164.         if (i + sizeof(ngx_resolver_an_t) >= last) {
  1165.             goto short_response;
  1166.         }

  1167.         an = (ngx_resolver_an_t *) &buf[i];

  1168.         type = (an->type_hi << 8) + an->type_lo;
  1169.         class = (an->class_hi << 8) + an->class_lo;
  1170.         len = (an->len_hi << 8) + an->len_lo;
  1171.         ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
  1172.             + (an->ttl[2] << 8) + (an->ttl[3]);

  1173.         if (class != 1) {
  1174.             ngx_log_error(r->log_level, r->log, 0,
  1175.                           "unexpected RR class %ui", class);
  1176.             goto failed;
  1177.         }

  1178.         if (ttl < 0) {
  1179.             ttl = 0;
  1180.         }

  1181.         rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);

  1182.         i += sizeof(ngx_resolver_an_t);

  1183.         switch (type) {

  1184.         case NGX_RESOLVE_A:

  1185.             if (qtype != NGX_RESOLVE_A) {
  1186.                 err = "unexpected A record in DNS response";
  1187.                 goto invalid;
  1188.             }

  1189.             if (len != 4) {
  1190.                 err = "invalid A record in DNS response";
  1191.                 goto invalid;
  1192.             }

  1193.             if (i + 4 > last) {
  1194.                 goto short_response;
  1195.             }

  1196.             naddrs++;

  1197.             break;

  1198. #if (NGX_HAVE_INET6)
  1199.         case NGX_RESOLVE_AAAA:

  1200.             if (qtype != NGX_RESOLVE_AAAA) {
  1201.                 err = "unexpected AAAA record in DNS response";
  1202.                 goto invalid;
  1203.             }

  1204.             if (len != 16) {
  1205.                 err = "invalid AAAA record in DNS response";
  1206.                 goto invalid;
  1207.             }

  1208.             if (i + 16 > last) {
  1209.                 goto short_response;
  1210.             }

  1211.             naddrs++;

  1212.             break;
  1213. #endif

  1214.         case NGX_RESOLVE_CNAME:

  1215.             cname = &buf[i];

  1216.             break;

  1217.         case NGX_RESOLVE_DNAME:

  1218.             break;

  1219.         default:

  1220.             ngx_log_error(r->log_level, r->log, 0,
  1221.                           "unexpected RR type %ui", type);
  1222.         }

  1223.         i += len;
  1224.     }

  1225.     ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
  1226.                    "resolver naddrs:%ui cname:%p ttl:%uD",
  1227.                    naddrs, cname, rn->ttl);

  1228.     if (naddrs) {

  1229.         switch (qtype) {

  1230. #if (NGX_HAVE_INET6)
  1231.         case NGX_RESOLVE_AAAA:

  1232.             if (naddrs == 1) {
  1233.                 addr6 = &rn->u6.addr6;
  1234.                 rn->naddrs6 = 1;

  1235.             } else {
  1236.                 addr6 = ngx_resolver_alloc(r, naddrs * sizeof(struct in6_addr));
  1237.                 if (addr6 == NULL) {
  1238.                     goto failed;
  1239.                 }

  1240.                 rn->u6.addrs6 = addr6;
  1241.                 rn->naddrs6 = (u_short) naddrs;
  1242.             }

  1243. #if (NGX_SUPPRESS_WARN)
  1244.             addr = NULL;
  1245. #endif

  1246.             break;
  1247. #endif

  1248.         default: /* NGX_RESOLVE_A */

  1249.             if (naddrs == 1) {
  1250.                 addr = &rn->u.addr;
  1251.                 rn->naddrs = 1;

  1252.             } else {
  1253.                 addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
  1254.                 if (addr == NULL) {
  1255.                     goto failed;
  1256.                 }

  1257.                 rn->u.addrs = addr;
  1258.                 rn->naddrs = (u_short) naddrs;
  1259.             }

  1260. #if (NGX_HAVE_INET6 && NGX_SUPPRESS_WARN)
  1261.             addr6 = NULL;
  1262. #endif
  1263.         }

  1264.         n = 0;
  1265.         i = ans;

  1266.         for (a = 0; a < nan; a++) {

  1267.             for ( ;; ) {

  1268.                 if (buf[i] & 0xc0) {
  1269.                     i += 2;
  1270.                     break;
  1271.                 }

  1272.                 if (buf[i] == 0) {
  1273.                     i++;
  1274.                     break;
  1275.                 }

  1276.                 i += 1 + buf[i];
  1277.             }

  1278.             an = (ngx_resolver_an_t *) &buf[i];

  1279.             type = (an->type_hi << 8) + an->type_lo;
  1280.             len = (an->len_hi << 8) + an->len_lo;

  1281.             i += sizeof(ngx_resolver_an_t);

  1282.             if (type == NGX_RESOLVE_A) {

  1283.                 addr[n] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
  1284.                                 + (buf[i + 2] << 8) + (buf[i + 3]));

  1285.                 if (++n == naddrs) {

  1286. #if (NGX_HAVE_INET6)
  1287.                     if (rn->naddrs6 == (u_short) -1) {
  1288.                         goto next;
  1289.                     }
  1290. #endif

  1291.                     break;
  1292.                 }
  1293.             }

  1294. #if (NGX_HAVE_INET6)
  1295.             else if (type == NGX_RESOLVE_AAAA) {

  1296.                 ngx_memcpy(addr6[n].s6_addr, &buf[i], 16);

  1297.                 if (++n == naddrs) {

  1298.                     if (rn->naddrs == (u_short) -1) {
  1299.                         goto next;
  1300.                     }

  1301.                     break;
  1302.                 }
  1303.             }
  1304. #endif

  1305.             i += len;
  1306.         }
  1307.     }

  1308.     switch (qtype) {

  1309. #if (NGX_HAVE_INET6)
  1310.     case NGX_RESOLVE_AAAA:

  1311.         if (rn->naddrs6 == (u_short) -1) {
  1312.             rn->naddrs6 = 0;
  1313.         }

  1314.         break;
  1315. #endif

  1316.     default: /* NGX_RESOLVE_A */

  1317.         if (rn->naddrs == (u_short) -1) {
  1318.             rn->naddrs = 0;
  1319.         }
  1320.     }

  1321.     if (rn->naddrs != (u_short) -1
  1322. #if (NGX_HAVE_INET6)
  1323.         && rn->naddrs6 != (u_short) -1
  1324. #endif
  1325.         && rn->naddrs
  1326. #if (NGX_HAVE_INET6)
  1327.            + rn->naddrs6
  1328. #endif
  1329.            > 0)
  1330.     {

  1331. #if (NGX_HAVE_INET6)
  1332.     export:
  1333. #endif

  1334.         naddrs = rn->naddrs;
  1335. #if (NGX_HAVE_INET6)
  1336.         naddrs += rn->naddrs6;
  1337. #endif

  1338.         if (naddrs == 1 && rn->naddrs == 1) {
  1339.             addrs = NULL;

  1340.         } else {
  1341.             addrs = ngx_resolver_export(r, rn, 0);
  1342.             if (addrs == NULL) {
  1343.                 goto failed;
  1344.             }
  1345.         }

  1346.         ngx_queue_remove(&rn->queue);

  1347.         rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
  1348.         rn->expire = ngx_time() + r->expire;

  1349.         ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);

  1350.         next = rn->waiting;
  1351.         rn->waiting = NULL;

  1352.         /* unlock name mutex */

  1353.         while (next) {
  1354.             ctx = next;
  1355.             ctx->state = NGX_OK;
  1356.             ctx->naddrs = naddrs;

  1357.             if (addrs == NULL) {
  1358.                 ctx->addrs = &ctx->addr;
  1359.                 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
  1360.                 ctx->addr.socklen = sizeof(struct sockaddr_in);
  1361.                 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
  1362.                 ctx->sin.sin_family = AF_INET;
  1363.                 ctx->sin.sin_addr.s_addr = rn->u.addr;

  1364.             } else {
  1365.                 ctx->addrs = addrs;
  1366.             }

  1367.             next = ctx->next;

  1368.             ctx->handler(ctx);
  1369.         }

  1370.         if (addrs != NULL) {
  1371.             ngx_resolver_free(r, addrs->sockaddr);
  1372.             ngx_resolver_free(r, addrs);
  1373.         }

  1374.         ngx_resolver_free(r, rn->query);
  1375.         rn->query = NULL;
  1376. #if (NGX_HAVE_INET6)
  1377.         rn->query6 = NULL;
  1378. #endif

  1379.         return;
  1380.     }

  1381.     if (cname) {

  1382.         /* CNAME only */

  1383.         if (rn->naddrs == (u_short) -1
  1384. #if (NGX_HAVE_INET6)
  1385.             || rn->naddrs6 == (u_short) -1
  1386. #endif
  1387.             )
  1388.         {
  1389.             goto next;
  1390.         }

  1391.         if (ngx_resolver_copy(r, &name, buf, cname, buf + last) != NGX_OK) {
  1392.             goto failed;
  1393.         }

  1394.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  1395.                        "resolver cname:\"%V\"", &name);

  1396.         ngx_queue_remove(&rn->queue);

  1397.         rn->cnlen = (u_short) name.len;
  1398.         rn->u.cname = name.data;

  1399.         rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
  1400.         rn->expire = ngx_time() + r->expire;

  1401.         ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);

  1402.         ctx = rn->waiting;
  1403.         rn->waiting = NULL;

  1404.         if (ctx) {
  1405.             ctx->name = name;

  1406.             (void) ngx_resolve_name_locked(r, ctx);
  1407.         }

  1408.         ngx_resolver_free(r, rn->query);
  1409.         rn->query = NULL;
  1410. #if (NGX_HAVE_INET6)
  1411.         rn->query6 = NULL;
  1412. #endif

  1413.         /* unlock name mutex */

  1414.         return;
  1415.     }

  1416.     ngx_log_error(r->log_level, r->log, 0,
  1417.                   "no A or CNAME types in DNS response");
  1418.     return;

  1419. short_response:

  1420.     err = "short DNS response";

  1421. invalid:

  1422.     /* unlock name mutex */

  1423.     ngx_log_error(r->log_level, r->log, 0, err);

  1424.     return;

  1425. failed:

  1426. next:

  1427.     /* unlock name mutex */

  1428.     return;
  1429. }


  1430. static void
  1431. ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
  1432.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
  1433. {
  1434.     char                 *err;
  1435.     size_t                len;
  1436.     u_char                text[NGX_SOCKADDR_STRLEN];
  1437.     in_addr_t             addr;
  1438.     int32_t               ttl;
  1439.     ngx_int_t             octet;
  1440.     ngx_str_t             name;
  1441.     ngx_uint_t            i, mask, qident, class;
  1442.     ngx_queue_t          *expire_queue;
  1443.     ngx_rbtree_t         *tree;
  1444.     ngx_resolver_an_t    *an;
  1445.     ngx_resolver_ctx_t   *ctx, *next;
  1446.     ngx_resolver_node_t  *rn;
  1447. #if (NGX_HAVE_INET6)
  1448.     uint32_t              hash;
  1449.     ngx_int_t             digit;
  1450.     struct in6_addr       addr6;
  1451. #endif

  1452.     if (ngx_resolver_copy(r, NULL, buf,
  1453.                           buf + sizeof(ngx_resolver_hdr_t), buf + n)
  1454.         != NGX_OK)
  1455.     {
  1456.         return;
  1457.     }

  1458.     /* AF_INET */

  1459.     addr = 0;
  1460.     i = sizeof(ngx_resolver_hdr_t);

  1461.     for (mask = 0; mask < 32; mask += 8) {
  1462.         len = buf[i++];

  1463.         octet = ngx_atoi(&buf[i], len);
  1464.         if (octet == NGX_ERROR || octet > 255) {
  1465.             goto invalid_in_addr_arpa;
  1466.         }

  1467.         addr += octet << mask;
  1468.         i += len;
  1469.     }

  1470.     if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
  1471.         i += sizeof("\7in-addr\4arpa");

  1472.         /* lock addr mutex */

  1473.         rn = ngx_resolver_lookup_addr(r, addr);

  1474.         tree = &r->addr_rbtree;
  1475.         expire_queue = &r->addr_expire_queue;

  1476.         addr = htonl(addr);
  1477.         name.len = ngx_inet_ntop(AF_INET, &addr, text, NGX_SOCKADDR_STRLEN);
  1478.         name.data = text;

  1479.         goto valid;
  1480.     }

  1481. invalid_in_addr_arpa:

  1482. #if (NGX_HAVE_INET6)

  1483.     i = sizeof(ngx_resolver_hdr_t);

  1484.     for (octet = 15; octet >= 0; octet--) {
  1485.         if (buf[i++] != '\1') {
  1486.             goto invalid_ip6_arpa;
  1487.         }

  1488.         digit = ngx_hextoi(&buf[i++], 1);
  1489.         if (digit == NGX_ERROR) {
  1490.             goto invalid_ip6_arpa;
  1491.         }

  1492.         addr6.s6_addr[octet] = (u_char) digit;

  1493.         if (buf[i++] != '\1') {
  1494.             goto invalid_ip6_arpa;
  1495.         }

  1496.         digit = ngx_hextoi(&buf[i++], 1);
  1497.         if (digit == NGX_ERROR) {
  1498.             goto invalid_ip6_arpa;
  1499.         }

  1500.         addr6.s6_addr[octet] += (u_char) (digit * 16);
  1501.     }

  1502.     if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
  1503.         i += sizeof("\3ip6\4arpa");

  1504.         /* lock addr mutex */

  1505.         hash = ngx_crc32_short(addr6.s6_addr, 16);
  1506.         rn = ngx_resolver_lookup_addr6(r, &addr6, hash);

  1507.         tree = &r->addr6_rbtree;
  1508.         expire_queue = &r->addr6_expire_queue;

  1509.         name.len = ngx_inet6_ntop(addr6.s6_addr, text, NGX_SOCKADDR_STRLEN);
  1510.         name.data = text;

  1511.         goto valid;
  1512.     }

  1513. invalid_ip6_arpa:
  1514. #endif

  1515.     ngx_log_error(r->log_level, r->log, 0,
  1516.                   "invalid in-addr.arpa or ip6.arpa name in DNS response");
  1517.     return;

  1518. valid:

  1519.     if (rn == NULL || rn->query == NULL) {
  1520.         ngx_log_error(r->log_level, r->log, 0,
  1521.                       "unexpected response for %V", &name);
  1522.         goto failed;
  1523.     }

  1524.     qident = (rn->query[0] << 8) + rn->query[1];

  1525.     if (ident != qident) {
  1526.         ngx_log_error(r->log_level, r->log, 0,
  1527.                       "wrong ident %ui response for %V, expect %ui",
  1528.                       ident, &name, qident);
  1529.         goto failed;
  1530.     }

  1531.     if (code == 0 && nan == 0) {
  1532.         code = NGX_RESOLVE_NXDOMAIN;
  1533.     }

  1534.     if (code) {
  1535.         next = rn->waiting;
  1536.         rn->waiting = NULL;

  1537.         ngx_queue_remove(&rn->queue);

  1538.         ngx_rbtree_delete(tree, &rn->node);

  1539.         /* unlock addr mutex */

  1540.         while (next) {
  1541.             ctx = next;
  1542.             ctx->state = code;
  1543.             next = ctx->next;

  1544.             ctx->handler(ctx);
  1545.         }

  1546.         ngx_resolver_free_node(r, rn);

  1547.         return;
  1548.     }

  1549.     i += sizeof(ngx_resolver_qs_t);

  1550.     if (i + 2 + sizeof(ngx_resolver_an_t) >= n) {
  1551.         goto short_response;
  1552.     }

  1553.     /* compression pointer to *.arpa */

  1554.     if (buf[i] != 0xc0 || buf[i + 1] != sizeof(ngx_resolver_hdr_t)) {
  1555.         err = "invalid in-addr.arpa or ip6.arpa name in DNS response";
  1556.         goto invalid;
  1557.     }

  1558.     an = (ngx_resolver_an_t *) &buf[i + 2];

  1559.     class = (an->class_hi << 8) + an->class_lo;
  1560.     len = (an->len_hi << 8) + an->len_lo;
  1561.     ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
  1562.         + (an->ttl[2] << 8) + (an->ttl[3]);

  1563.     if (class != 1) {
  1564.         ngx_log_error(r->log_level, r->log, 0,
  1565.                       "unexpected RR class %ui", class);
  1566.         goto failed;
  1567.     }

  1568.     if (ttl < 0) {
  1569.         ttl = 0;
  1570.     }

  1571.     ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
  1572.                   "resolver qt:%ui cl:%ui len:%uz",
  1573.                   (an->type_hi << 8) + an->type_lo,
  1574.                   class, len);

  1575.     i += 2 + sizeof(ngx_resolver_an_t);

  1576.     if (i + len > n) {
  1577.         goto short_response;
  1578.     }

  1579.     if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
  1580.         goto failed;
  1581.     }

  1582.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);

  1583.     if (name.len != (size_t) rn->nlen
  1584.         || ngx_strncmp(name.data, rn->name, name.len) != 0)
  1585.     {
  1586.         if (rn->nlen) {
  1587.             ngx_resolver_free(r, rn->name);
  1588.         }

  1589.         rn->nlen = (u_short) name.len;
  1590.         rn->name = name.data;

  1591.         name.data = ngx_resolver_dup(r, rn->name, name.len);
  1592.         if (name.data == NULL) {
  1593.             goto failed;
  1594.         }
  1595.     }

  1596.     ngx_queue_remove(&rn->queue);

  1597.     rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
  1598.     rn->expire = ngx_time() + r->expire;

  1599.     ngx_queue_insert_head(expire_queue, &rn->queue);

  1600.     next = rn->waiting;
  1601.     rn->waiting = NULL;

  1602.     /* unlock addr mutex */

  1603.     while (next) {
  1604.         ctx = next;
  1605.         ctx->state = NGX_OK;
  1606.         ctx->name = name;
  1607.         next = ctx->next;

  1608.         ctx->handler(ctx);
  1609.     }

  1610.     ngx_resolver_free(r, name.data);

  1611.     return;

  1612. short_response:

  1613.     err = "short DNS response";

  1614. invalid:

  1615.     /* unlock addr mutex */

  1616.     ngx_log_error(r->log_level, r->log, 0, err);

  1617.     return;

  1618. failed:

  1619.     /* unlock addr mutex */

  1620.     return;
  1621. }


  1622. static ngx_resolver_node_t *
  1623. ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
  1624. {
  1625.     ngx_int_t             rc;
  1626.     ngx_rbtree_node_t    *node, *sentinel;
  1627.     ngx_resolver_node_t  *rn;

  1628.     node = r->name_rbtree.root;
  1629.     sentinel = r->name_rbtree.sentinel;

  1630.     while (node != sentinel) {

  1631.         if (hash < node->key) {
  1632.             node = node->left;
  1633.             continue;
  1634.         }

  1635.         if (hash > node->key) {
  1636.             node = node->right;
  1637.             continue;
  1638.         }

  1639.         /* hash == node->key */

  1640.         rn = ngx_resolver_node(node);

  1641.         rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);

  1642.         if (rc == 0) {
  1643.             return rn;
  1644.         }

  1645.         node = (rc < 0) ? node->left : node->right;
  1646.     }

  1647.     /* not found */

  1648.     return NULL;
  1649. }


  1650. static ngx_resolver_node_t *
  1651. ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
  1652. {
  1653.     ngx_rbtree_node_t  *node, *sentinel;

  1654.     node = r->addr_rbtree.root;
  1655.     sentinel = r->addr_rbtree.sentinel;

  1656.     while (node != sentinel) {

  1657.         if (addr < node->key) {
  1658.             node = node->left;
  1659.             continue;
  1660.         }

  1661.         if (addr > node->key) {
  1662.             node = node->right;
  1663.             continue;
  1664.         }

  1665.         /* addr == node->key */

  1666.         return ngx_resolver_node(node);
  1667.     }

  1668.     /* not found */

  1669.     return NULL;
  1670. }


  1671. #if (NGX_HAVE_INET6)

  1672. static ngx_resolver_node_t *
  1673. ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
  1674.     uint32_t hash)
  1675. {
  1676.     ngx_int_t             rc;
  1677.     ngx_rbtree_node_t    *node, *sentinel;
  1678.     ngx_resolver_node_t  *rn;

  1679.     node = r->addr6_rbtree.root;
  1680.     sentinel = r->addr6_rbtree.sentinel;

  1681.     while (node != sentinel) {

  1682.         if (hash < node->key) {
  1683.             node = node->left;
  1684.             continue;
  1685.         }

  1686.         if (hash > node->key) {
  1687.             node = node->right;
  1688.             continue;
  1689.         }

  1690.         /* hash == node->key */

  1691.         rn = ngx_resolver_node(node);

  1692.         rc = ngx_memcmp(addr, &rn->addr6, 16);

  1693.         if (rc == 0) {
  1694.             return rn;
  1695.         }

  1696.         node = (rc < 0) ? node->left : node->right;
  1697.     }

  1698.     /* not found */

  1699.     return NULL;
  1700. }

  1701. #endif


  1702. static void
  1703. ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
  1704.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
  1705. {
  1706.     ngx_rbtree_node_t    **p;
  1707.     ngx_resolver_node_t   *rn, *rn_temp;

  1708.     for ( ;; ) {

  1709.         if (node->key < temp->key) {

  1710.             p = &temp->left;

  1711.         } else if (node->key > temp->key) {

  1712.             p = &temp->right;

  1713.         } else { /* node->key == temp->key */

  1714.             rn = ngx_resolver_node(node);
  1715.             rn_temp = ngx_resolver_node(temp);

  1716.             p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen)
  1717.                  < 0) ? &temp->left : &temp->right;
  1718.         }

  1719.         if (*p == sentinel) {
  1720.             break;
  1721.         }

  1722.         temp = *p;
  1723.     }

  1724.     *p = node;
  1725.     node->parent = temp;
  1726.     node->left = sentinel;
  1727.     node->right = sentinel;
  1728.     ngx_rbt_red(node);
  1729. }


  1730. #if (NGX_HAVE_INET6)

  1731. static void
  1732. ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
  1733.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
  1734. {
  1735.     ngx_rbtree_node_t    **p;
  1736.     ngx_resolver_node_t   *rn, *rn_temp;

  1737.     for ( ;; ) {

  1738.         if (node->key < temp->key) {

  1739.             p = &temp->left;

  1740.         } else if (node->key > temp->key) {

  1741.             p = &temp->right;

  1742.         } else { /* node->key == temp->key */

  1743.             rn = ngx_resolver_node(node);
  1744.             rn_temp = ngx_resolver_node(temp);

  1745.             p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)
  1746.                  < 0) ? &temp->left : &temp->right;
  1747.         }

  1748.         if (*p == sentinel) {
  1749.             break;
  1750.         }

  1751.         temp = *p;
  1752.     }

  1753.     *p = node;
  1754.     node->parent = temp;
  1755.     node->left = sentinel;
  1756.     node->right = sentinel;
  1757.     ngx_rbt_red(node);
  1758. }

  1759. #endif


  1760. static ngx_int_t
  1761. ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
  1762. {
  1763.     u_char              *p, *s;
  1764.     size_t               len, nlen;
  1765.     ngx_uint_t           ident;
  1766. #if (NGX_HAVE_INET6)
  1767.     ngx_resolver_t      *r;
  1768. #endif
  1769.     ngx_resolver_qs_t   *qs;
  1770.     ngx_resolver_hdr_t  *query;

  1771.     nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1;

  1772.     len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);

  1773. #if (NGX_HAVE_INET6)
  1774.     r = ctx->resolver;

  1775.     p = ngx_resolver_alloc(ctx->resolver, r->ipv6 ? len * 2 : len);
  1776. #else
  1777.     p = ngx_resolver_alloc(ctx->resolver, len);
  1778. #endif
  1779.     if (p == NULL) {
  1780.         return NGX_ERROR;
  1781.     }

  1782.     rn->qlen = (u_short) len;
  1783.     rn->query = p;

  1784. #if (NGX_HAVE_INET6)
  1785.     if (r->ipv6) {
  1786.         rn->query6 = p + len;
  1787.     }
  1788. #endif

  1789.     query = (ngx_resolver_hdr_t *) p;

  1790.     ident = ngx_random();

  1791.     ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
  1792.                    "resolve: \"%V\" A %i", &ctx->name, ident & 0xffff);

  1793.     query->ident_hi = (u_char) ((ident >> 8) & 0xff);
  1794.     query->ident_lo = (u_char) (ident & 0xff);

  1795.     /* recursion query */
  1796.     query->flags_hi = 1; query->flags_lo = 0;

  1797.     /* one question */
  1798.     query->nqs_hi = 0; query->nqs_lo = 1;
  1799.     query->nan_hi = 0; query->nan_lo = 0;
  1800.     query->nns_hi = 0; query->nns_lo = 0;
  1801.     query->nar_hi = 0; query->nar_lo = 0;

  1802.     p += sizeof(ngx_resolver_hdr_t) + nlen;

  1803.     qs = (ngx_resolver_qs_t *) p;

  1804.     /* query type */
  1805.     qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_A;

  1806.     /* IN query class */
  1807.     qs->class_hi = 0; qs->class_lo = 1;

  1808.     /* convert "www.example.com" to "\3www\7example\3com\0" */

  1809.     len = 0;
  1810.     p--;
  1811.     *p-- = '\0';

  1812.     if (ctx->name.len == 0)  {
  1813.         return NGX_DECLINED;
  1814.     }

  1815.     for (s = ctx->name.data + ctx->name.len - 1; s >= ctx->name.data; s--) {
  1816.         if (*s != '.') {
  1817.             *p = *s;
  1818.             len++;

  1819.         } else {
  1820.             if (len == 0 || len > 255) {
  1821.                 return NGX_DECLINED;
  1822.             }

  1823.             *p = (u_char) len;
  1824.             len = 0;
  1825.         }

  1826.         p--;
  1827.     }

  1828.     if (len == 0 || len > 255) {
  1829.         return NGX_DECLINED;
  1830.     }

  1831.     *p = (u_char) len;

  1832. #if (NGX_HAVE_INET6)
  1833.     if (!r->ipv6) {
  1834.         return NGX_OK;
  1835.     }

  1836.     p = rn->query6;

  1837.     ngx_memcpy(p, rn->query, rn->qlen);

  1838.     query = (ngx_resolver_hdr_t *) p;

  1839.     ident = ngx_random();

  1840.     ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0,
  1841.                    "resolve: \"%V\" AAAA %i", &ctx->name, ident & 0xffff);

  1842.     query->ident_hi = (u_char) ((ident >> 8) & 0xff);
  1843.     query->ident_lo = (u_char) (ident & 0xff);

  1844.     p += sizeof(ngx_resolver_hdr_t) + nlen;

  1845.     qs = (ngx_resolver_qs_t *) p;

  1846.     qs->type_lo = NGX_RESOLVE_AAAA;
  1847. #endif

  1848.     return NGX_OK;
  1849. }


  1850. static ngx_int_t
  1851. ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
  1852. {
  1853.     u_char               *p, *d;
  1854.     size_t                len;
  1855.     in_addr_t             addr;
  1856.     ngx_int_t             n;
  1857.     ngx_uint_t            ident;
  1858.     ngx_resolver_hdr_t   *query;
  1859.     struct sockaddr_in   *sin;
  1860. #if (NGX_HAVE_INET6)
  1861.     struct sockaddr_in6  *sin6;
  1862. #endif

  1863.     switch (ctx->addr.sockaddr->sa_family) {

  1864. #if (NGX_HAVE_INET6)
  1865.     case AF_INET6:
  1866.         len = sizeof(ngx_resolver_hdr_t)
  1867.               + 64 + sizeof(".ip6.arpa.") - 1
  1868.               + sizeof(ngx_resolver_qs_t);

  1869.         break;
  1870. #endif

  1871.     default: /* AF_INET */
  1872.         len = sizeof(ngx_resolver_hdr_t)
  1873.               + sizeof(".255.255.255.255.in-addr.arpa.") - 1
  1874.               + sizeof(ngx_resolver_qs_t);
  1875.     }

  1876.     p = ngx_resolver_alloc(ctx->resolver, len);
  1877.     if (p == NULL) {
  1878.         return NGX_ERROR;
  1879.     }

  1880.     rn->query = p;
  1881.     query = (ngx_resolver_hdr_t *) p;

  1882.     ident = ngx_random();

  1883.     query->ident_hi = (u_char) ((ident >> 8) & 0xff);
  1884.     query->ident_lo = (u_char) (ident & 0xff);

  1885.     /* recursion query */
  1886.     query->flags_hi = 1; query->flags_lo = 0;

  1887.     /* one question */
  1888.     query->nqs_hi = 0; query->nqs_lo = 1;
  1889.     query->nan_hi = 0; query->nan_lo = 0;
  1890.     query->nns_hi = 0; query->nns_lo = 0;
  1891.     query->nar_hi = 0; query->nar_lo = 0;

  1892.     p += sizeof(ngx_resolver_hdr_t);

  1893.     switch (ctx->addr.sockaddr->sa_family) {

  1894. #if (NGX_HAVE_INET6)
  1895.     case AF_INET6:
  1896.         sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;

  1897.         for (n = 15; n >= 0; n--) {
  1898.             p = ngx_sprintf(p, "\1%xd\1%xd",
  1899.                             sin6->sin6_addr.s6_addr[n] & 0xf,
  1900.                             (sin6->sin6_addr.s6_addr[n] >> 4) & 0xf);
  1901.         }

  1902.         p = ngx_cpymem(p, "\3ip6\4arpa\0", 10);

  1903.         break;
  1904. #endif

  1905.     default: /* AF_INET */

  1906.         sin = (struct sockaddr_in *) ctx->addr.sockaddr;
  1907.         addr = ntohl(sin->sin_addr.s_addr);

  1908.         for (n = 0; n < 32; n += 8) {
  1909.             d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff);
  1910.             *p = (u_char) (d - &p[1]);
  1911.             p = d;
  1912.         }

  1913.         p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14);
  1914.     }

  1915.     /* query type "PTR", IN query class */
  1916.     p = ngx_cpymem(p, "\0\14\0\1", 4);

  1917.     rn->qlen = (u_short) (p - rn->query);

  1918.     return NGX_OK;
  1919. }


  1920. static ngx_int_t
  1921. ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
  1922.     u_char *last)
  1923. {
  1924.     char        *err;
  1925.     u_char      *p, *dst;
  1926.     ssize_t      len;
  1927.     ngx_uint_t   i, n;

  1928.     p = src;
  1929.     len = -1;

  1930.     /*
  1931.      * compression pointers allow to create endless loop, so we set limit;
  1932.      * 128 pointers should be enough to store 255-byte name
  1933.      */

  1934.     for (i = 0; i < 128; i++) {
  1935.         n = *p++;

  1936.         if (n == 0) {
  1937.             goto done;
  1938.         }

  1939.         if (n & 0xc0) {
  1940.             n = ((n & 0x3f) << 8) + *p;
  1941.             p = &buf[n];

  1942.         } else {
  1943.             len += 1 + n;
  1944.             p = &p[n];
  1945.         }

  1946.         if (p >= last) {
  1947.             err = "name is out of response";
  1948.             goto invalid;
  1949.         }
  1950.     }

  1951.     err = "compression pointers loop";

  1952. invalid:

  1953.     ngx_log_error(r->log_level, r->log, 0, err);

  1954.     return NGX_ERROR;

  1955. done:

  1956.     if (name == NULL) {
  1957.         return NGX_OK;
  1958.     }

  1959.     if (len == -1) {
  1960.         ngx_str_null(name);
  1961.         return NGX_OK;
  1962.     }

  1963.     dst = ngx_resolver_alloc(r, len);
  1964.     if (dst == NULL) {
  1965.         return NGX_ERROR;
  1966.     }

  1967.     name->data = dst;

  1968.     n = *src++;

  1969.     for ( ;; ) {
  1970.         if (n & 0xc0) {
  1971.             n = ((n & 0x3f) << 8) + *src;
  1972.             src = &buf[n];

  1973.             n = *src++;

  1974.         } else {
  1975.             ngx_strlow(dst, src, n);
  1976.             dst += n;
  1977.             src += n;

  1978.             n = *src++;

  1979.             if (n != 0) {
  1980.                 *dst++ = '.';
  1981.             }
  1982.         }

  1983.         if (n == 0) {
  1984.             name->len = dst - name->data;
  1985.             return NGX_OK;
  1986.         }
  1987.     }
  1988. }


  1989. static void
  1990. ngx_resolver_timeout_handler(ngx_event_t *ev)
  1991. {
  1992.     ngx_resolver_ctx_t   *ctx, *next;
  1993.     ngx_resolver_node_t  *rn;

  1994.     rn = ev->data;
  1995.     ctx = rn->waiting;
  1996.     rn->waiting = NULL;

  1997.     do {
  1998.         ctx->state = NGX_RESOLVE_TIMEDOUT;
  1999.         next = ctx->next;

  2000.         ctx->handler(ctx);

  2001.         ctx = next;
  2002.     } while (ctx);
  2003. }


  2004. static void
  2005. ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
  2006. {
  2007.     /* lock alloc mutex */

  2008.     if (rn->query) {
  2009.         ngx_resolver_free_locked(r, rn->query);
  2010.     }

  2011.     if (rn->name) {
  2012.         ngx_resolver_free_locked(r, rn->name);
  2013.     }

  2014.     if (rn->cnlen) {
  2015.         ngx_resolver_free_locked(r, rn->u.cname);
  2016.     }

  2017.     if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
  2018.         ngx_resolver_free_locked(r, rn->u.addrs);
  2019.     }

  2020. #if (NGX_HAVE_INET6)
  2021.     if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
  2022.         ngx_resolver_free_locked(r, rn->u6.addrs6);
  2023.     }
  2024. #endif

  2025.     ngx_resolver_free_locked(r, rn);

  2026.     /* unlock alloc mutex */
  2027. }


  2028. static void *
  2029. ngx_resolver_alloc(ngx_resolver_t *r, size_t size)
  2030. {
  2031.     u_char  *p;

  2032.     /* lock alloc mutex */

  2033.     p = ngx_alloc(size, r->log);

  2034.     /* unlock alloc mutex */

  2035.     return p;
  2036. }


  2037. static void *
  2038. ngx_resolver_calloc(ngx_resolver_t *r, size_t size)
  2039. {
  2040.     u_char  *p;

  2041.     p = ngx_resolver_alloc(r, size);

  2042.     if (p) {
  2043.         ngx_memzero(p, size);
  2044.     }

  2045.     return p;
  2046. }


  2047. static void
  2048. ngx_resolver_free(ngx_resolver_t *r, void *p)
  2049. {
  2050.     /* lock alloc mutex */

  2051.     ngx_free(p);

  2052.     /* unlock alloc mutex */
  2053. }


  2054. static void
  2055. ngx_resolver_free_locked(ngx_resolver_t *r, void *p)
  2056. {
  2057.     ngx_free(p);
  2058. }


  2059. static void *
  2060. ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
  2061. {
  2062.     void  *dst;

  2063.     dst = ngx_resolver_alloc(r, size);

  2064.     if (dst == NULL) {
  2065.         return dst;
  2066.     }

  2067.     ngx_memcpy(dst, src, size);

  2068.     return dst;
  2069. }


  2070. static ngx_addr_t *
  2071. ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
  2072.     ngx_uint_t rotate)
  2073. {
  2074.     ngx_addr_t            *dst;
  2075.     ngx_uint_t             d, i, j, n;
  2076.     u_char               (*sockaddr)[NGX_SOCKADDRLEN];
  2077.     in_addr_t             *addr;
  2078.     struct sockaddr_in    *sin;
  2079. #if (NGX_HAVE_INET6)
  2080.     struct in6_addr       *addr6;
  2081.     struct sockaddr_in6   *sin6;
  2082. #endif

  2083.     n = rn->naddrs;
  2084. #if (NGX_HAVE_INET6)
  2085.     n += rn->naddrs6;
  2086. #endif

  2087.     dst = ngx_resolver_calloc(r, n * sizeof(ngx_addr_t));
  2088.     if (dst == NULL) {
  2089.         return NULL;
  2090.     }

  2091.     sockaddr = ngx_resolver_calloc(r, n * NGX_SOCKADDRLEN);
  2092.     if (sockaddr == NULL) {
  2093.         ngx_resolver_free(r, dst);
  2094.         return NULL;
  2095.     }

  2096.     i = 0;
  2097.     d = rotate ? ngx_random() % n : 0;

  2098.     if (rn->naddrs) {
  2099.         j = rotate ? ngx_random() % rn->naddrs : 0;

  2100.         addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;

  2101.         do {
  2102.             sin = (struct sockaddr_in *) sockaddr[d];
  2103.             sin->sin_family = AF_INET;
  2104.             sin->sin_addr.s_addr = addr[j++];
  2105.             dst[d].sockaddr = (struct sockaddr *) sin;
  2106.             dst[d++].socklen = sizeof(struct sockaddr_in);

  2107.             if (d == n) {
  2108.                 d = 0;
  2109.             }

  2110.             if (j == rn->naddrs) {
  2111.                 j = 0;
  2112.             }
  2113.         } while (++i < rn->naddrs);
  2114.     }

  2115. #if (NGX_HAVE_INET6)
  2116.     if (rn->naddrs6) {
  2117.         j = rotate ? ngx_random() % rn->naddrs6 : 0;

  2118.         addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;

  2119.         do {
  2120.             sin6 = (struct sockaddr_in6 *) sockaddr[d];
  2121.             sin6->sin6_family = AF_INET6;
  2122.             ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16);
  2123.             dst[d].sockaddr = (struct sockaddr *) sin6;
  2124.             dst[d++].socklen = sizeof(struct sockaddr_in6);

  2125.             if (d == n) {
  2126.                 d = 0;
  2127.             }

  2128.             if (j == rn->naddrs6) {
  2129.                 j = 0;
  2130.             }
  2131.         } while (++i < n);
  2132.     }
  2133. #endif

  2134.     return dst;
  2135. }


  2136. char *
  2137. ngx_resolver_strerror(ngx_int_t err)
  2138. {
  2139.     static char *errors[] = {
  2140.         "Format error",     /* FORMERR */
  2141.         "Server failure",   /* SERVFAIL */
  2142.         "Host not found",   /* NXDOMAIN */
  2143.         "Unimplemented",    /* NOTIMP */
  2144.         "Operation refused" /* REFUSED */
  2145.     };

  2146.     if (err > 0 && err < 6) {
  2147.         return errors[err - 1];
  2148.     }

  2149.     if (err == NGX_RESOLVE_TIMEDOUT) {
  2150.         return "Operation timed out";
  2151.     }

  2152.     return "Unknown error";
  2153. }


  2154. static u_char *
  2155. ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
  2156. {
  2157.     u_char                *p;
  2158.     ngx_udp_connection_t  *uc;

  2159.     p = buf;

  2160.     if (log->action) {
  2161.         p = ngx_snprintf(buf, len, " while %s", log->action);
  2162.         len -= p - buf;
  2163.     }

  2164.     uc = log->data;

  2165.     if (uc) {
  2166.         p = ngx_snprintf(p, len, ", resolver: %V", &uc->server);
  2167.     }

  2168.     return p;
  2169. }


  2170. ngx_int_t
  2171. ngx_udp_connect(ngx_udp_connection_t *uc)
  2172. {
  2173.     int                rc;
  2174.     ngx_int_t          event;
  2175.     ngx_event_t       *rev, *wev;
  2176.     ngx_socket_t       s;
  2177.     ngx_connection_t  *c;

  2178.     s = ngx_socket(uc->sockaddr->sa_family, SOCK_DGRAM, 0);

  2179.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);

  2180.     if (s == (ngx_socket_t) -1) {
  2181.         ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
  2182.                       ngx_socket_n " failed");
  2183.         return NGX_ERROR;
  2184.     }

  2185.     c = ngx_get_connection(s, &uc->log);

  2186.     if (c == NULL) {
  2187.         if (ngx_close_socket(s) == -1) {
  2188.             ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
  2189.                           ngx_close_socket_n "failed");
  2190.         }

  2191.         return NGX_ERROR;
  2192.     }

  2193.     if (ngx_nonblocking(s) == -1) {
  2194.         ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
  2195.                       ngx_nonblocking_n " failed");

  2196.         goto failed;
  2197.     }

  2198.     rev = c->read;
  2199.     wev = c->write;

  2200.     rev->log = &uc->log;
  2201.     wev->log = &uc->log;

  2202.     uc->connection = c;

  2203.     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);

  2204.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
  2205.                    "connect to %V, fd:%d #%uA", &uc->server, s, c->number);

  2206.     rc = connect(s, uc->sockaddr, uc->socklen);

  2207.     /* TODO: aio, iocp */

  2208.     if (rc == -1) {
  2209.         ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
  2210.                       "connect() failed");

  2211.         goto failed;
  2212.     }

  2213.     /* UDP sockets are always ready to write */
  2214.     wev->ready = 1;

  2215.     if (ngx_add_event) {

  2216.         event = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ?
  2217.                     /* kqueue, epoll */                 NGX_CLEAR_EVENT:
  2218.                     /* select, poll, /dev/poll */       NGX_LEVEL_EVENT;
  2219.                     /* eventport event type has no meaning: oneshot only */

  2220.         if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
  2221.             goto failed;
  2222.         }

  2223.     } else {
  2224.         /* rtsig */

  2225.         if (ngx_add_conn(c) == NGX_ERROR) {
  2226.             goto failed;
  2227.         }
  2228.     }

  2229.     return NGX_OK;

  2230. failed:

  2231.     ngx_close_connection(c);
  2232.     uc->connection = NULL;

  2233.     return NGX_ERROR;
  2234. }