📄 ngx_resolver.c
字号:
ngx_log_error(r->log_level, r->log, 0, err); return;}static voidngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans){ char *err; u_char *cname; size_t len; uint32_t hash; in_addr_t addr, *addrs; ngx_str_t name; ngx_uint_t qtype, qident, naddrs, a, i, n, start; ngx_resolver_an_t *an; ngx_resolver_ctx_t *ctx, *next; ngx_resolver_node_t *rn; if (ngx_resolver_copy(r, &name, buf, &buf[12], &buf[last]) != NGX_OK) { return; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name); hash = ngx_crc32_short(name.data, name.len); /* lock name mutex */ rn = ngx_resolver_lookup_name(r, &name, hash); if (rn == NULL || rn->query == NULL) { ngx_log_error(r->log_level, r->log, 0, "unexpected response for %V", &name); goto failed; } qident = (rn->query[0] << 8) + rn->query[1]; if (ident != qident) { ngx_log_error(r->log_level, r->log, 0, "wrong ident %ui response for %V, expect %ui", ident, &name, qident); goto failed; } if (code == 0 && nan == 0) { code = 3; /* NXDOMAIN */ } if (code) { next = rn->waiting; rn->waiting = NULL; ngx_queue_remove(&rn->queue); ngx_rbtree_delete(&r->name_rbtree, &rn->node); ngx_resolver_free_node(r, rn); /* unlock name mutex */ while (next) { ctx = next; ctx->state = code; next = ctx->next; ctx->handler(ctx); } return; } i = ans; naddrs = 0; addr = 0; addrs = NULL; cname = NULL; qtype = 0; for (a = 0; a < nan; a++) { start = i; while (i < last) { if (buf[i] & 0xc0) { i += 2; goto found; } if (buf[i] == 0) { i++; goto test_length; } i += 1 + buf[i]; } goto short_response; test_length: if (i - start < 2) { err = "invalid name in dns response"; goto invalid; } found: if (i + sizeof(ngx_resolver_an_t) >= last) { goto short_response; } an = (ngx_resolver_an_t *) &buf[i]; qtype = (an->type_hi << 8) + an->type_lo; len = (an->len_hi << 8) + an->len_lo; if (qtype == NGX_RESOLVE_A) { i += sizeof(ngx_resolver_an_t); if (i + len > last) { goto short_response; } addr = htonl((buf[i] << 24) + (buf[i + 1] << 16) + (buf[i + 2] << 8) + (buf[i + 3])); naddrs++; i += len; } else if (qtype == NGX_RESOLVE_CNAME) { cname = &buf[i] + sizeof(ngx_resolver_an_t); i += sizeof(ngx_resolver_an_t) + len; } else if (qtype == NGX_RESOLVE_DNAME) { i += sizeof(ngx_resolver_an_t) + len; } else { ngx_log_error(r->log_level, r->log, 0, "unexpected qtype %ui", qtype); } } ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver naddrs:%ui cname:%p", naddrs, cname); if (naddrs) { if (naddrs == 1) { rn->u.addr = addr; } else { addrs = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t)); if (addrs == NULL) { return; } n = 0; i = ans; for (a = 0; a < nan; a++) { for ( ;; ) { if (buf[i] & 0xc0) { i += 2; goto ok; } if (buf[i] == 0) { i++; goto ok; } i += 1 + buf[i]; } ok: an = (ngx_resolver_an_t *) &buf[i]; qtype = (an->type_hi << 8) + an->type_lo; len = (an->len_hi << 8) + an->len_lo; i += sizeof(ngx_resolver_an_t); if (qtype == NGX_RESOLVE_A) { addrs[n++] = htonl((buf[i] << 24) + (buf[i + 1] << 16) + (buf[i + 2] << 8) + (buf[i + 3])); if (n == naddrs) { break; } } i += len; } rn->u.addrs = addrs; addrs = ngx_resolver_dup(r, rn->u.addrs, naddrs * sizeof(in_addr_t)); if (addrs == NULL) { return; } } rn->naddrs = (u_short) naddrs; ngx_queue_remove(&rn->queue); rn->valid = ngx_time() + r->valid; rn->expire = ngx_time() + r->expire; ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); next = rn->waiting; rn->waiting = NULL; /* unlock name mutex */ while (next) { ctx = next; ctx->state = NGX_OK; ctx->naddrs = naddrs; ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs; ctx->addr = addr; next = ctx->next; ctx->handler(ctx); } if (naddrs) { ngx_resolver_free(r, addrs); } return; } else if (cname) { /* CNAME only */ if (ngx_resolver_copy(r, &name, buf, cname, &buf[last]) != NGX_OK) { return; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver cname:\"%V\"", &name); ngx_queue_remove(&rn->queue); rn->cnlen = (u_short) name.len; rn->u.cname = name.data; rn->valid = ngx_time() + r->valid; rn->expire = ngx_time() + r->expire; ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); ctx = rn->waiting; rn->waiting = NULL; if (ctx) { ctx->name = name; (void) ngx_resolve_name_locked(r, ctx); } return; } ngx_log_error(r->log_level, r->log, 0, "no A or CNAME types in DNS responses, unknown query type: %ui", qtype); return;short_response: err = "short dns response";invalid: /* unlock name mutex */ ngx_log_error(r->log_level, r->log, 0, err); return;failed: /* unlock name mutex */ return;}static voidngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan){ char *err; size_t len; in_addr_t addr; ngx_int_t digit; ngx_str_t name; ngx_uint_t i, mask, qtype, qclass, qident; ngx_resolver_an_t *an; ngx_resolver_ctx_t *ctx, *next; ngx_resolver_node_t *rn; if (ngx_resolver_copy(r, NULL, buf, &buf[12], &buf[n]) != NGX_OK) { goto invalid_in_addr_arpa; } addr = 0; i = 12; for (mask = 0; mask < 32; mask += 8) { len = buf[i++]; digit = ngx_atoi(&buf[i], len); if (digit == NGX_ERROR || digit > 255) { goto invalid_in_addr_arpa; } addr += digit << mask; i += len; } if (ngx_strcmp(&buf[i], "\7in-addr\4arpa") != 0) { goto invalid_in_addr_arpa; } /* lock addr mutex */ rn = ngx_resolver_lookup_addr(r, addr); if (rn == NULL || rn->query == NULL) { ngx_log_error(r->log_level, r->log, 0, "unexpected response for %ud.%ud.%ud.%ud", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); goto failed; } qident = (rn->query[0] << 8) + rn->query[1]; if (ident != qident) { ngx_log_error(r->log_level, r->log, 0, "wrong ident %ui response for %ud.%ud.%ud.%ud, expect %ui", ident, (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, qident); goto failed; } if (code == 0 && nan == 0) { code = 3; /* NXDOMAIN */ } if (code) { next = rn->waiting; rn->waiting = NULL; ngx_queue_remove(&rn->queue); ngx_rbtree_delete(&r->addr_rbtree, &rn->node); ngx_resolver_free_node(r, rn); /* unlock addr mutex */ while (next) { ctx = next; ctx->state = code; next = ctx->next; ctx->handler(ctx); } return; } i += sizeof("\7in-addr\4arpa") + sizeof(ngx_resolver_qs_t); if (i + 2 + sizeof(ngx_resolver_an_t) > (ngx_uint_t) n) { goto short_response; } /* compression pointer to "XX.XX.XX.XX.in-addr.arpa */ if (buf[i] != 0xc0 || buf[i + 1] != 0x0c) { err = "invalid in-addr.arpa name in DNS response"; goto invalid; } an = (ngx_resolver_an_t *) &buf[i + 2]; qtype = (an->type_hi << 8) + an->type_lo; qclass = (an->class_hi << 8) + an->class_lo; len = (an->len_hi << 8) + an->len_lo; ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qt:%ui cl:%ui len:%uz", qtype, qclass, len); i += 2 + sizeof(ngx_resolver_an_t); if (i + len > (ngx_uint_t) n) { goto short_response; } len -= 2; if (ngx_resolver_copy(r, &name, buf, &buf[i], &buf[n]) != NGX_OK) { return; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name); if (len != (size_t) rn->nlen || ngx_strncmp(name.data, rn->name, len) != 0) { ngx_resolver_free(r, rn->name); rn->name = name.data; name.data = ngx_resolver_dup(r, rn->name, len); if (name.data == NULL) { goto failed; } } ngx_queue_remove(&rn->queue); rn->valid = ngx_time() + r->valid; rn->expire = ngx_time() + r->expire; ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue); next = rn->waiting; rn->waiting = NULL; /* unlock addr mutex */ while (next) { ctx = next; ctx->state = NGX_OK; ctx->name = name; next = ctx->next; ctx->handler(ctx); } ngx_resolver_free(r, name.data); return;invalid_in_addr_arpa: ngx_log_error(r->log_level, r->log, 0, "invalid in-addr.arpa name in DNS response"); return;short_response: err = "short DNS response";invalid: /* unlock addr mutex */ ngx_log_error(r->log_level, r->log, 0, err); return;failed: /* unlock addr mutex */ return;}static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash){ ngx_int_t rc; size_t len; ngx_rbtree_node_t *node, *sentinel; ngx_resolver_node_t *rn; node = r->name_rbtree.root; sentinel = r->name_rbtree.sentinel; while (node != sentinel) { if (hash < node->key) { node = node->left; continue; } if (hash > node->key) { node = node->right; continue; } /* hash == node->key */ do { rn = (ngx_resolver_node_t *) node; len = (name->len > (size_t) rn->nlen) ? rn->nlen : name->len; rc = ngx_strncmp(name->data, rn->name, len); if (rc == 0) { return rn; } node = (rc < 0) ? node->left : node->right; } while (node != sentinel && hash == node->key); break; } /* not found */ return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -